我正在尝试通过构建一个应用程序来学习 Android 应用程序编程以保持在 Hearts 中的得分。游戏本身的数据按以下层次排列:
Game
代表整个游戏Vector
Round
代表游戏中每手牌 的对象。Vector
BoxScore
代表手中每个盒子分数的对象。
此数据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
这里是因为我的代码还捕获了触发对话框创建的点击。如果您使用内联内部类处理此问题,则不需要OnClickListener
in 您的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()
回忆一下重绘整个活动的方法。我仍然相信,当然,有一种更有效的方法可以做到这一点,但我还没有找到它。