2

我正在尝试通过构建一个应用程序来学习 Android 应用程序编程以保持在 Hearts 中的得分。游戏本身的数据按以下层次排列:

  • Game代表整个游戏
    • VectorRound代表游戏中每手牌 的对象。
      • VectorBoxScore代表手中每个盒子分数的对象。

此数据ScoreTableActivity由 a 表示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 官方参考 "Dialogs",不幸的是我在发布这个问题后才阅读。

第 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这里是因为我的代码还捕获了触发对话框创建的点击。如果您使用内联内部类处理此问题,则不需要OnClickListenerin 您的implements子句。

第 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()andrequestLayout()方法仍然不够。我不得不removeAllViews()回忆一下重绘整个活动的方法。我仍然相信,当然,有一种更有效的方法可以做到这一点,但我还没有找到它。

4

0 回答 0