如何在具有可滚动ListItem的同时支持本机ListView项目单击

时间:2013-07-10 10:59:07

标签: android android-listview touch android-custom-view

问题

在滑动手势上为ListView项目开发某种“上下文操作”时,我对Android将MotionEvent分派给ViewGroup的孩子的方式感到有点困惑。

根据文档记录,所有内容都以ViewGroupd.dispatchTouchEvent(MotionEvent)方法调用开头。然后查看小组询问是否应截取特定的动作事件,或者我们是否可以将其发送给我们的孩子。这适用于所有类型的滚动,因此我们可以有效地解决垂直和水平滚动之间的冲突(例如ViewPager中的ListView)。

但是我无法通过这种方式成功处理列表视图中的简单点击事件。 运动事件调度跟踪看起来像这样

  1. ListView.dispatchTouchEvent(DOWN)
  2. ListView.onInterceptTouchEvent(DOWN) 返回false ;
  3. QuickActionView.dispatchTouchEvent(DOWN)
  4. QuickActionView.onTouchEvent(DOWN) 返回true ,因为MotionEvent.ACTION_DOWN指示手势的开始,它可能是水平滚动,在这种情况下我们应该向用户显示快速操作布局。如果我们从false处返回MotionEvent.ACTION_DOWN,则会阻止将其他触摸事件分派给ListView的这个子项。
  5. 由于第4步QuickActionView.dispatchTouchEvent(DOWN) 返回true
  6. 由于第5步ListView.dispatchTouchEvent(DOWN) 返回true
  7. 结果ListView记得触摸目标。所以下一条消息就像这样发送。

    1. ListView.dispatchTouchEvent(UP)
    2. ListView.onInterceptTouchEvent(UP) 返回false ;
    3. QuickActionView.dispatchTouchEvent(UP)
    4. QuickActionView.onTouchEvent(UP) 返回false ,因为我们现在看到手势已经结束,而且不是滚动或投掷等等。
    5. 由于第4步QuickActionView.dispatchTouchEvent(UP) 返回false
    6. 由于第5步ListView.dispatchTouchEvent(UP) 返回false
    7. 因此,ListView无法处理项目点击,因为在执行UP操作的步骤5之后,运动事件不会定向到ListView的onTouchEvent(MotionEvent)方法。

      我还尝试在ListView中“拦截”触摸事件与ACTION_UP,但是已经注意到拦截后根据Android文档只有进一步的动作事件将被定向到ViewGroup的onTouchEvent(MotionEvent)方法,并且当前获胜“T

      问题

      如何支持ListView的本机项目单击处理和将MotionEvent分派到ListItem视图的功能(它是水平可滚动的并具有图像按钮)?

      最好倾听那些在解决此类问题方面经验丰富的人,或者更深入地了解它如何与指定的冲突解决方案合作

1 个答案:

答案 0 :(得分:0)

目前我有两个解决这个问题的方法

  1. 将QuickActionView(实际上是ListView项目)分为两部分:
  2.  ____________________
    | clickable      |  |   
    |________________|__|
                       ^
                       |
                      scrollable
    

    因此,如果初始ACTION_DOWN运动事件从可点击区域开始,我无法滚动ListView项目,但列表视图处理项目本机点击。而且我无法单击可滚动区域内的列表项,而如果我的手势从可滚动区域开始,我可以滚动显示快速操作。

    1. 第二个解决方案相当hacky但避免了第一个解决方案的限制 在ListView中,我可以通过MotionEvent.obtain(MotionEvent)方法记住所有触摸事件。然后我等待ACTION_UP MotionEvent并询问listItem视图是否已处理手势。如果列表项表明手势尚未处理,则我调用私有方法ListView.cancelTouchTarget()并通过super.dispatchTouchEvent(MotionEvent)
    2. 将所有已保存的MotionEvent发布到listView