代码之家  ›  专栏  ›  技术社区  ›  Sira Lam

如何将单击事件传递给RecyclerView的项目?

  •  1
  • Sira Lam  · 技术社区  · 7 年前

    我有一个普通的 RecyclerView ,最上面是一个透明的 View 实现 GestureListener ,其大小基本上与 回收视图 .

    这个 手势监听器 将聆听滚动和投掷手势,并传递此信息 MotionEvent 回收视图 在它下面。

    我已经做了 回收视图 能够滚动和投掷。但是,我找不到将单击事件传递给 回收视图 项目

    我已经知道这是因为 ACTION_DOWN 手势监听器 . 事实上 手势监听器 有一个 onSingleTap() 方法,并且每当我执行单击时都会调用此方法。

    根据 this post ,我试图设置 OnTouchListener 转到我的项目视图并收听 ACTION_UP 事件。然而 onTouch() 从未调用方法。

    以下是我的做法:
    1、在透明的GestureListener中创建回调

       @Override
        public boolean onSingleTapUp(MotionEvent e) {
            if (scrollDetector == null) return false;
            scrollDetector.onSingleTap(e);
            return true;
        }
    
    1. 在活动中配置回调,并传递 MotionEvent运动事件 回收视图

      @Override
      public void onSingleTap(MotionEvent e) {
          mRecyclerView.onTouchEvent(e);
      }
      
    2. 设置 OnTouchListener 到适配器中的itemView:

      itemView.setOnTouchListener(new View.OnTouchListener() {
          @Override
          public boolean onTouch(View v, MotionEvent event) {
              if (event.getAction() == MotionEvent.ACTION_UP) {
                  v.performClick();
                  return true;
              }
              return false;
          }
      });
      

    使用调试器,我可以看到 mRecyclerView.onTouchEvent(e) 被称为;但是 onTouch() 未调用itemView的。

    所以如何正确通过 MotionEvent运动事件 到itemView?

    你可以问- “为什么要在RecyclerView上放置一个GestureListener?”
    这是因为我需要更改 回收视图 回收视图 已滚动。但是,如果我使用 回收视图 addOnScrollListener ,的值 dy 将在负值和正值之间波动,因为dy也受其高度的影响。并且波动也会反映到UI上。
    因此,我需要一个滚动检测器,滚动时不会改变其高度,只需将滚动和投掷值传递给 回收视图 通过编程调用 scrollBy() fling() .

    2 回复  |  直到 7 年前
        1
  •  0
  •   TangXianQiang    7 年前

    您应该知道recyclerview的事件。若在滚动视图时recyclerview可以移动,它将调用onInterceptTouchEvent()并返回true以拦截事件。因此无法获取ACTION\u MOVE事件。也许您应该重写recyclerview的onInterceptTouchEvent()并返回false。然后可以在itemView的方法中获取所有事件。

        2
  •  0
  •   Sira Lam    7 年前

    愚蠢的我。我应该使用 dispatchTouchEvent(MotionEvent e) 而不是 onTouchEvent(MotionEvent e) .

    然而,这还不够。
    只需呼叫 dispatchTouchEvent(e) 使用GestureListener中的MotionEvent不起作用,因为 e 是一个 ACTION_UP 事件

    要模拟单击,您需要两者 ACTION_DOWN 动作\u向上 .

    和itemView不需要设置 OnTouchListener 因为您已经模拟了

    代码:

            @Override
            public void onSingleTap(MotionEvent e) {
                long downTime = SystemClock.uptimeMillis();
                long upTime = downTime + 100;
                MotionEvent downEvent = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN,
                        e.getX(), e.getY(), 0);
                mRecyclerView.dispatchTouchEvent(downEvent);
                MotionEvent upEvent = MotionEvent.obtain(upTime, upTime, MotionEvent.ACTION_UP,
                        e.getX(), e.getY(), 0);
                mRecyclerView.dispatchTouchEvent(upEvent);
                downEvent.recycle();
                upEvent.recycle();
            }