android - 在 ScrollView 中传播触摸事件

标签 android

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

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

此时我遇到的问题是从未调用项目的 ACTION_UP。我一定已经尝试了在两个 onTouchListener 中返回 true/false 的所有组合,但我无法让 ACTION_UP 工作,或者如果我确实让它工作,那么 scrollview 的 onTouchListener 中的某些东西不再工作。

我还尝试在 ScrollView 的 onTouchHandler 中添加 dispatchTouchEvent,但发现我得到了无休止的递归调用。

有没有办法让 ScrollView 及其子项接收 ACTION_UP/ACTION_DOWN?

最佳答案

要让 ScrollView 中的项目响应 onClick,但也知道用户何时向下或向上点击手指,需要一些棘手的编码。此处的解决方案适用于 API 15+。需要注意的关键是 ScrollView 实际上没有使用 onTouchListener。相反,使用 OnSimpleGestureListener 在项目上检测事件。但是,有趣的是,即使有 onDown 方法,OnSimpleGestureListener 也不存在 onUp 方法(见图)。为了解决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);
  }
}

我在这个解决方案中看到的唯一问题是 ScrollView 是否有太少的项目无法滚动。如果项目太少并且用户按下 ScrollView 上某处而不是项目,则不会检测到向上/向下事件。这在您的应用程序中是否重要是您必须决定的事情。如果需要,则可能还需要为 ScrollView 包含一个 onTouchListener。

关于android - 在 ScrollView 中传播触摸事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30340095/

相关文章:

java - GridView 将最后一个项目显示为一半项目,有些经常不展开

android - Android 上的硬件层和硬件加速

android - 如何设置BottomBar的背景颜色?

android - 从 View 模型类中获取 Activity 的上下文

android - 安装新软件时的Eclipse问题

Android Studio 部分文件处理失败,详情请查看日志

java - View 被推到水平约束布局之外

android - 试图实例化一个不是 Fragment 的类 androidx.navigation.fragment.NavHostFragment

java - Android JNI C++ 代码始终获取 2 个不同 SurfaceView 对象的 "same"jobject 值

android - Linux USB : how to let's the bNumConfigurations value is 0x01?