Android – ListView中的延迟点击

我在我的应用程序中有以下结构:

FragmentActivity与ViewPager持有多个片段由FragmentStatePagerAdapterpipe理与Android 2.1的兼容性包

每个片段都包含ListViewListView中的每个元素都有一个带有两个TextViews和一个ButtonLinearLayoutLinearLayout和button有onClickListeners (分开)。 点击LinearLayout开始另一个Activity 。 我注意到,点击行为是非常不一致的:有时行动立即执行,但很多时候它被延迟,有时甚至被忽略,无论我点击多less次。 它变得更加怪异,因为我可以点击,只有当我开始滚动列表时才会执行该动作。 我尝试了setFocusable(false)setSelectable(true)各种组合,但似乎没有任何区别。 有任何想法吗? 我会很乐意提供更多的细节。

Solutions Collecting From Web of "Android – ListView中的延迟点击"

我有一个类似的问题,花了我2​​天来debugging和解决它。 我有一个ListAdapter,它为每个列表项在LinearLayout中创build几个TextView。 每个TextView都有自己的OnClickListener,因为我需要处理每个项目的点击。

当我更改实现,以便重用视图的OnClickListener停止正常工作。 在4.4.2上大多数的点击工作,但有时在我滚动列表中没有反应。 在2.3上,第一次点击将不起作用,然后在突发中处理所有的点击。

在我的特殊情况下,我创build了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源代码中进行了一些debugging和研究。 当android更新视图时,有两个重要的步骤onMeasure和onLayout。 ListAdapter的getView方法不仅被调用来绘制视图,而且在onMeasure期间也被调用。 在后面的例子中,视图被创build,但是它还没有在事件链中注册来处理点击事件。

当为onMeasure创build的视图稍后被重用以便在屏幕上进行抽取时,必须从Android系统注册以处理点击事件。 对于这个特殊情况,Android开发者已经做了一些事情,这可能被认为是一个肮脏的黑客。 LayoutParams中的特殊标志用于决定视图必须在事件更改中注册。

现在我的问题:通过重新设置LayoutParams当一个视图被重用,这个标志总是重置。 所以Android系统不会注册视图,事件不会通过。

总结一下:在ListView的getView中恢复视图时,不要覆盖LayoutParams,因为它们保留了android系统的内部信息。

我遇到了同样的问题,但在我的情况下,解决scheme是不保留对视图的引用,这导致ListView的视图caching问题。 在使用converView正确实现getView()方法之后,丢失/意外的点击呼叫的所有奇怪行为都消失了。

如果有人想知道我是如何解决这个问题的。 基本上我不得不简化我的布局。 看起来,当你有复杂的嵌套结构事件可能需要太长的时间来冒泡,如果你开始滚动列表在同一时间事件可以触发错误的行动。 我通过尽可能地切换到RelativeLayout来修剪布局,这似乎有很大的帮助

什么对我来说是通过setOnItemClickListener分配一个OnItemClickListenerListView ,而不是一个OnClickListener到单独的列表项。 显然,button仍然需要自己的OnClickListener ,但是我没有testing过这个场景。

不知道这是否有助于任何人,但我有一个类似的问题,而不是一个TableLayout。 上述解决scheme并没有解决我的问题。

对我来说问题是: android:animateLayoutChanges="true"

删除这个允许我的button点击我的TableLayout行以正常工作。 我不得不依靠上面的属性手动地animation我的视图。

看来你正在事件线程中执行一些阻塞过程(如调用webservices或打开文件),所以你的事件线程被阻止。 如果是这种情况,请将您的阻止代码处理到事件THread以外的另一个线程中。