我有一个LinearLayout,我想更改其中一个子视图(一个ImageButton)被单击时的背景颜色。我能够做到这一点,但不能立即做到 - 直到稍后才会在屏幕上发生更改(我认为在onResume调用期间)。我想知道在下一行代码执行之前,如何在设置背景后强制布局重绘。这是按钮的OnClickListener的onClick方法:
public void onClick(View v) {
LinearLayout parentLayout = (LinearLayout) v.getParent();
parentLayout.setBackgroundResource(R.color.my_color);
SystemClock.sleep(1000); //ms
}
睡眠命令用于测试重绘是在其之前还是之后发生。结果:之后。关于此主题的大多数问题(如here和here)都说在视图上使用invalidate()。我在后台和睡眠线之间使用了命令parentLayout.invalidate();
,parentLayout.postInvalidate();
和parentLayout.refreshDrawableState();
,但都无济于事。重写仍然发生在sleep命令之后。谁能告诉我如何立即实现它?
其他可能有用的信息:LinearLayout绑定到ListView的行,上面的OnClickListener位于扩展SimpleCursorAdapter的自定义类中,而不是活动本身。 (这样我就可以为ListView中的每一行设置一个监听器。)
答案 0 :(得分:3)
您可以在forceLayout()
之后立即致电draw(canvas)
。如果您未覆盖onLayout()
,onMeasure
,draw()
或onDraw()
,则会运行默认实施。唯一的问题是您必须获得Canvas或手动创建一个。
强烈建议不要采用这种方法,因为Android专门设计用于避免在正常更新之外进行绘制。虽然你是正确的invalidate()
没有立即发生,但它是鼓励重绘的最安全和最好的方法。如果你想处理更新之外的绘图,Android提供了一种方法来使用SurfaceHolder类。
答案 1 :(得分:2)
好的,我终于找到了解决这个问题的方法,而且很简单。似乎问题只是我在OnClickLIstener中执行可绘制的更改,而我应该在OnTouchListener中执行它。如果我为我的按钮设置一个OnTouchListener来查找ACTION_DOWN,然后在其父布局上运行setBackgroundColor,则会立即发生更改。
另一种不太健全的解决方案来自this post。您可以在xml中为父布局背景指定选择器,然后在上面提到的OnTouchListener中,在该布局上运行setPressed(true)。这不是一个很好的解决方案,因为选择器比直接在代码中直接更改视图的属性提供了更少的自由度。例如,您无法通过按其他按钮将布局背景设置为其他颜色。
感谢那些帮忙提出建议的人!
答案 2 :(得分:1)
进行更改并调用listview.invalidate();在UI上反映这些变化