ハーツでスコアを記録するアプリを作成して、Android アプリのプログラミングを学ぼうとしています。ゲーム自体のデータは、次の階層に配置されます。
Game
ゲーム全体を表すVector
ゲームのRound
各手を表すオブジェクトの。Vector
ハンドのBoxScore
各ボックス スコアを表すオブジェクトの数。
このデータは ごとに表示されます。各ScoreTableActivity
セルには、マーカー セル、各オブジェクトのセル、およびハンドの合計スコアが正しいかどうかを示すセルが含まれます。テーブルの最後の行は、各列のボックス スコアを合計することによって、各プレーヤーの合計スコアを示します。TableLayout
TableRow
BoxScore
drawScoreTable()
アクティビティのメソッド中に呼び出されるメソッドがonCreate()
あり、期待どおりに機能しています。ボックススコアのセルを作成している間、これらのセルのクリックをキャッチするために次のことがありました。
TextView txtScore = ScoreTableCellFactory.getBoxScoreCell( this, oScore ) ;
txtScore.setOnClickListener(this) ;
rowRound.addView( txtScore ) ; // rowRound is a TableRow.
これをサポートするためにScoreTableActivity
自体が実装されています。OnClickListener
ボックススコアのみがクリック可能です。アクティビティのonClick()
メソッドは次のとおりです。
public void onClick( View oClicked )
{
// A reference to the score object is built into the view's tag.
BoxScore oScore = (BoxScore)oClicked.getTag() ;
// Create the dialog where the user modifies the box score.
BoxScoreEditorDialogFragment fragBoxScoreDialog = new BoxScoreEditorDialogFragment() ;
fragBoxScoreDialog.setBoxScore(oScore) ;
fragBoxScoreDialog.setRules(m_oGame.getRules()) ;
fragBoxScoreDialog.show(getFragmentManager(), "fragBoxScore") ;
// We passed the BoxScore object across to the editor dialog by
// reference (It's Java, after all), so we should be able to
// update the text of the box score cell by simply re-examining
// the data in that BoxScore object.
((TextView)oClicked).setText(Integer.toString(oScore.getScore())) ;
// And it's at this point that something else is clearly needed.
}
このサイトの他の回答ではsetText()
、レンダラーにセルをリフレッシュさせるにはこの方法で十分であることが示唆されていますが、そうではありません。上記のコードでは、次にセルがクリックされるまでセルは更新されません。
invalidate()
セル自体、その親行、および全体でメソッドを使用しようとしましたTableLayout
が、これらのどれも効果がありませんでした。メソッドを使用してから、もう一度removeAllViews()
呼び出してみました。drawScoreTable()
それでも、次のクリックイベントがキャッチされるまで画面は更新されませんでした。
タブレットを新しい向き (縦向きから横向き、またはその逆) に傾けると、アクティビティ全体が再作成され、新しいテーブルにすべての正しいデータが表示されます。テーブル全体を完全に破棄して再構築することに頼りたくはありませんが、それが私がやっていることだと思っていましたがremoveAllViews()
、それでもうまくいきませんでした。
編集: 強力な解決策が見つかりました。
この問題の一部は、データの更新がダイアログから行われるという事実に起因しています。これは基本的なアクティビティとは別の領域であるため、ダイアログは終了時に何かをトリガーする必要があります。
私のコードはもう少し特殊化されていますが、何が起こっているかを状況に関係なく理解できるように、以下の一般的な例を作成しました。実際には、 「ダイアログ」の公式 Android リファレンスに基づいています。残念ながら、この質問を投稿した後にのみ読んだものです。
ステップ 1: ダイアログのカスタム リスナー クラスを作成します。
/**
* Callers of this dialog must implement this interface to catch the events
* that are returned from it.
*/
public interface Listener
{
public void onDialogCommit( MyDialogClass fragDialog ) ;
}
ステップ 2: ベース アクティビティにリスナーを実装します。
メイン アクティビティ クラスの先頭で:
public class MyBaseActivity
extends Activity
implements OnClickListener, MyDialogClass.Listener
OnClickListener
私のコードは、ダイアログの作成をトリガーするクリックもキャッチするため、ここに保持しています。これをインラインの内部クラスで処理する場合OnClickListener
、implements
節に the は必要ありません。
ステップ 3: ベース アクティビティにリスナーのインターフェイスを実装します。
これは、公式の Android の例から省略されている部分です。このリスナー メソッドには何を入れますか? さて、答えは驚くほどひどいものです。
public void onDialogCommit( MyDialogClass oDialog )
{
TableLayout oLayout = (TableLayout)(findViewById(R.id.tbl_MyTableLayout)) ;
// This is where things still seem more ugly than they should.
oLayout.removeAllViews() ;
this.recreateEverything() ; // assumes you've written a method for this
}
サプライズ
この新しいインターフェイスとリスナーのモデルを作成した後でも、 メソッドinvalidate()
とrequestLayout()
メソッドを使用するだけでは十分ではありませんでした。removeAllViews()
アクティビティ全体を再描画する方法を思い出す必要がありました。確かに、これを行うより効率的な方法があると今でも信じていますが、まだ見つけていません。