首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >安卓-在ListView中延迟点击

安卓-在ListView中延迟点击
EN

Stack Overflow用户
提问于 2012-01-11 14:27:38
回答 6查看 4K关注 0票数 18

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

带有ViewPager的FragmentActivity包含多个片段,由使用Android2.1兼容包的FragmentStatePagerAdapter管理

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

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2012-02-07 09:26:05

如果有人想知道我是怎么解决这个问题的。基本上我必须简化我的布局。似乎当你有复杂的嵌套结构时,事件冒泡的时间可能太长,如果你同时开始滚动列表,事件可能会触发错误的操作。我通过尽可能多地切换到RelativeLayout来调整布局,这似乎有很大帮助

票数 3
EN

Stack Overflow用户

发布于 2014-05-03 22:15:26

我也遇到过类似的问题,我花了两天的时间来调试和解决它。我有一个ListAdapter,它在一个LinearLayout中为每个列表项创建几个TextViews。每个TextView都有它自己的OnClickListener,因为我需要处理每个项目上的点击。

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

在我的特殊情况下,我用Java代码创建了所有的视图,而不是通过膨胀资源。关键点是,即使在重用视图时,我也设置了LinearLayout的LayoutParams (这似乎更安全,然后假设重用的视图具有正确的布局参数)。当我在重用时没有设置LayoutParams时,一切都可以正常工作!以下是关键代码:

代码语言:javascript
复制
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开发者做了一些事情,这可以被认为是一个肮脏的黑客行为。LayoutParams中的一个特殊标志用于确定必须在事件更改中注册视图。

现在我的问题是:通过在重用视图时重置LayoutParams,这个标志总是被重置的。因此,Android系统不会注册视图,事件也不会通过。

总而言之:在ListAdapter的getView中重用视图时,不要覆盖LayoutParams,因为它们保留了安卓系统的内部信息。

票数 9
EN

Stack Overflow用户

发布于 2012-03-23 20:36:25

我遇到了同样的问题,但在我的例子中,解决方案是不保留对视图的引用,这导致了ListView的视图缓存问题。在使用converView正确实现getView()方法后,丢失/意外单击调用的所有奇怪行为都消失了。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8815066

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档