我有一个类似的问题,花了我2天来调试和解决它。 我有一个ListAdapter为每个列表项在LinearLayout中创建几个TextView。 每个TextView都有它自己的OnClickListener,因为我需要处理每个项目的点击。
当我更改实现,以便重用Views时,OnClickListener停止正常工作。在4.4.2上,大多数点击都有效,但有时在我滚动列表之前没有任何反应。在2.3上,第一次点击将无法工作,然后在突发中处理所有点击。
在我的特殊情况下,我创建了Java代码中的所有视图,而不是通过膨胀资源。 关键的一点是,即使视图被重用(这似乎更安全,然后假定重用视图具有正确的布局参数),我仍然设置了LinearLayout的LayoutParams。 当我没有设置LayoutParams时,重用一切工作正常! 这里是关键代码:
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout tapeLine = null;
if (convertView != null && convertView instanceof LinearLayout && ((LinearLayout)convertView).getChildCount() == 4) tapeLine = (LinearLayout) convertView; // Reuse view
else tapeLine = new LinearLayout(activity);
if (convertView == null) { // Don't set LayoutParams when reusing view
ViewGroup.LayoutParams tapeLineLayoutParams = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
tapeLine.setLayoutParams(tapeLineLayoutParams);
}
ScrollingTape scrollingTape = calculatorHolder.getCalculator().getScrollingTape();
int tapeWidthPx = parent.getWidth();
TapeLineTextSizeInfo tapeLineTextSizeInfo = calculatorHolder.getTapeLineTextSizeHelper().createTapeLineTextSizeInfo(tapeWidthPx);
ScrollingTapeLine line = scrollingTape.getLine(position);
tapeLine.setOrientation(LinearLayout.HORIZONTAL);
int tapeBackgroundColor = getBackgroundColor(line);
tapeLine.setBackgroundColor(tapeBackgroundColor);
addColumnViews(tapeLine, line, tapeLineTextSizeInfo);
tapeLine.setTag(R.id.scrollingtapeadapter_viewtag_position, position);
tapeLine.setOnLongClickListener(longClickListener);
tapeLine.setOnClickListener(remainClickListener);
return tapeLine;
}
什么是列表视图的这种奇怪的行为的背景是什么? 我在Android源代码中进行了一些调试和研究。 当android更新视图时,onMeasure和onLayout有两个重要步骤。 ListAdapter的getView方法不仅被调用来绘制视图,而且在onMeasure期间也被调用。在后面这种情况下,视图被创建,但它尚未在事件链中注册以处理点击事件。
当为onMeasure创建的视图稍后被重新用于画面时,它必须从Android系统注册以处理点击事件。 对于这种特殊情况,Android开发者已经做了一些事情,这可能被认为是肮脏的黑客攻击。 LayoutParams中的特殊标志用于决定视图必须在事件更改中注册。
现在我的问题:通过重置LayoutParams还视图重用时,此标志始终重置。因此,Android系统不会注册视图,事件不会通过。
总结:当在ListView的getView中重新使用视图时,不要覆盖LayoutParams,因为它们保留了android系统的内部信息。
我使用Loaders特别是AsyncLoader来完成我所有的后台进程。但我会重新评估代码,谢谢你的提示! – Bostone 2012-01-11 16:19:26
毕竟不是理由。查看我的回答 – Bostone 2012-02-07 01:26:43