我有一个ListAdapter,为每个列表项在LinearLayout中创建几个TextViews。每个TextView都有自己的OnClickListener,因为我需要处理每个项目上的点击事件。当我更改实现方式以便重用视图时,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;
else tapeLine = new LinearLayout(activity);
if (convertView == null) {
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 系统将不会注册视图,事件也不会传递。
总之,在 ListAdapter 的 getView 中重用视图时,请勿覆盖 LayoutParams,因为它们保留了 Android 系统的内部信息。