【问题标题】:Propagating touch events in a ScrollView在 ScrollView 中传播触摸事件
【发布时间】:2015-05-20 04:07:38
【问题描述】:

我在我的 Android 应用中传播触摸事件时遇到了困难。我有一个 ScrollView,其中包含一个充当项目的视图。当您点击该项目时,我想处理一个 onclick 事件。这可以通过对项目使用 setOnClickListener 来完成。但我还需要拦截滚动视图的 ACTION_UP 和 ACTION_DOWN 事件。我使用滚动视图的 setOnTouchListener 来做到这一点。

没有收到滚动视图的 ACTION_UP 和 ACTION_DOWN。然后我决定对 setOnClickListener 的项目使用 setOnTouchListener。这改善了事情。当您按下该项目时,该项目的 onTouchListener 会为 ACTION_DOWN 调用。退出项目的 onTouchListener 时返回 false。然后调用滚动视图的 onTouchListener 并接收 ACTION_DOWN。事情似乎进展顺利。尽管为什么首先调用项目的 onTouchListener 而不是滚动视图,但它确实让我感到困惑。退出滚动视图的 onTouchListener 时返回 false。现在,当我松开手指时,会调用滚动视图的 ACTION_UP 并返回 false。

此时我遇到的问题是该项目的 ACTION_UP 从未被调用。我必须尝试在 onTouchListener 中返回 true/false 的所有组合,但无法让 ACTION_UP 工作,或者如果我确实让它工作,那么滚动视图的 onTouchListener 中的某些东西不再起作用。

我也尝试在滚动视图的 onTouchHandler 中添加 dispatchTouchEvent,但发现我得到了一个无休止的递归调用。

有没有办法让滚动视图及其子项接收 ACTION_UP / ACTION_DOWN?

【问题讨论】:

    标签: android


    【解决方案1】:

    要让滚动视图中的项目响应 onClick 并知道用户何时向下或向上点击了手指,需要一些棘手的编码。此处的解决方案适用于 API 15+。需要注意的关键是滚动视图实际上没有使用 onTouchListener。相反,使用 OnSimpleGestureListener 在项目上检测事件。然而,有趣的是,OnSimpleGestureListener 不存在 onUp 方法,即使 onDown 存在(见图)。要解决onUp,你必须测试onTouchEvent的返回值:

    GestureDetector gestureDetector = new GestureDetector(context, new GestureDetectorListItem());
    
    listItem.setOnTouchListener(this.onTouchArticleItem);
    
    private View.OnTouchListener onTouchArticleItem = new View.OnTouchListener()
    {
      @Override
      public boolean onTouch(View v, MotionEvent event)
      {
        try
        {
    
          boolean state = gestureDetector.onTouchEvent(event);
    
          if ((event.getAction() == android.view.MotionEvent.ACTION_UP) && !state)
          {
            // Handle up event here.
            return true;
          }
          else if ((event.getAction() == android.view.MotionEvent.ACTION_DOWN) && state)
          {
            // Handle down event here.
            return true;
          }
          else
            return state;
    
    
        }
        catch (Exception ex)
        {
          Logger.Log(context, ex.getMessage(), Log.ERROR);
          return false;
        }
      }
    };
    
    
    private class GestureDetectorListItem extends GestureDetector.SimpleOnGestureListener
    {
      public boolean onSingleTapUp(MotionEvent e)
      {
        return true;
      }
    
      public void onLongPress(MotionEvent e)
      {
      }
    
      public boolean onDoubleTap(MotionEvent e)
      {
        return false;
      }
    
      public boolean onDoubleTapEvent(MotionEvent e)
      {
        return false;
      }
    
      public boolean onSingleTapConfirmed(MotionEvent e)
      {
        return false;
    
      }
    
      public void onShowPress(MotionEvent e)
      {
      }
    
      public boolean onDown(MotionEvent e)
      {
        return true;
      }
    
    
      public boolean onScroll(MotionEvent e1, MotionEvent e2, final float distanceX, float distanceY)
      {
        return super.onScroll(e1, e2, distanceX, distanceY);
      }
    
      @Override
      public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
      {
        return super.onFling(e1, e2, velocityX, velocityY);
      }
    }
    

    我在这个解决方案中看到的唯一问题是滚动视图中滚动的项目是否太少。如果项目太少并且用户在滚动视图上按下项目以外的某个位置,则不会检测到向上/向下事件。这在您的应用程序中是否重要是您必须决定的事情。如果需要,那么可能还需要为滚动视图添加一个 onTouchListener。

    【讨论】:

      猜你喜欢
      • 2014-01-18
      • 2011-08-26
      • 2012-10-12
      • 2011-04-05
      • 1970-01-01
      • 1970-01-01
      • 2015-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多