【问题标题】:ViewPager stealing Horizontal Touch Events from Child FragmentsViewPager 从子片段中窃取水平触摸事件
【发布时间】:2017-03-19 06:20:18
【问题描述】:

所以我有一个ViewPagerViewPager 包含两个选项卡,每个选项卡包含一个RecyclerView,可以从每个RecyclerView 添加和删除卡片。每个RecyclerView 都包含在Fragment 中。每个RecyclerView使用ItemTouchHelper 来管理onSwiped() 事件。 RecyclerView 中的卡片有几种行为:

  • 向右滑动可打开卡片的编辑器
  • 向左滑动删除卡片
  • 按住卡片并垂直向上或向下拖动可重新定位卡片。

我的问题是ViewPager 正在拦截每个RecyclerViewonSwiped() 方法,但是,每个RecyclerView 仍然可以正确接收垂直触摸事件。显然,这归结为触摸冲突问题。 ViewPager 想要水平触摸事件来改变标签,RecyclerView 想要水平触摸事件来刷卡。然而,ViewPager 正在窃取所有的触摸事件。我在ViewPager 上禁用了水平滑动(用户可以更改选项卡的唯一方法是点击选项卡指示器),但RecyclerView 仍然不会收到任何水平触摸事件。

这是禁用滑动的ViewPager

public class NoSwipePager extends ViewPager {

public NoSwipePager(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    return false;
}
}

这是一个片段类:

@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    view = inflater.inflate(R.layout.pit_tab, container, false);
    container.getParent().requestDisallowInterceptTouchEvent(true);
    RecyclerView rv = (RecyclerView) view.findViewById(R.id.movie_recycler_view);

    return view;
}

这是管理RecyclerView的类:

    public EditManager(RecyclerView rv, Context act, EditListener listener, ArrayList<Element> elements, boolean editing, boolean pit) {
    //rv = (RecyclerView) act.findViewById(R.id.movie_recycler_view);
    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(act);
    linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    rv.setLayoutManager(linearLayoutManager);
    ((SimpleItemAnimator) rv.getItemAnimator()).setSupportsChangeAnimations(false);

    if(elements != null) elementsAdapter = new ElementsAdapter(listener, act, new LinkedList<>(elements), editing);
    else elementsAdapter = new ElementsAdapter(listener, act, null, editing);
    rv.setAdapter(elementsAdapter);

    ItemTouchHelper.Callback callback = new ElementTouchHelper(elementsAdapter);
    ItemTouchHelper helper = new ItemTouchHelper(callback);
    helper.attachToRecyclerView(rv);
}

最后,这是应该被调用的方法,但不是:

    @Override
public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) {
    if(direction == ItemTouchHelper.RIGHT) {
        mElementsAdapter.postEdit(mElementsAdapter.getElement(viewHolder.getAdapterPosition()));
        return;
    }
}

【问题讨论】:

    标签: java android android-fragments


    【解决方案1】:

    尝试用这个替换你的NoSwipePager

    public class NoSwipePager extends ViewPager {
      public NoSwipePager(Context context, AttributeSet attrs) {
        super(context, attrs);
      }
    
      @Override
      protected boolean canScroll(View v, boolean checkV, int dx, int x,
                                  int y) {
        if (v instanceof RecyclerView) {
          return(true);
        }
    
        return(super.canScroll(v, checkV, dx, x, y));
      }
    }
    

    我已经成功地将这种方法用于页面中带有地图的ViewPager(将SurfaceView 替换为RecyclerView)。我的猜测是您需要用更复杂的东西(并且为您的应用程序定制)替换 v instanceof RecyclerView 测试。但我认为canScroll() 比阻止onInterceptTouchEvent() 更有可能给你想要的东西。

    【讨论】:

    • 好的,所以我用你的代码替换了ViewPager,但它仍然不起作用。如果在屏幕边缘附近开始滑动,现在可以通过滑动来更改选项卡,但 RecyclerView 中的卡片仍然不会移动。还有其他想法吗? @CommonsWare
    • @wdavies973:你在if() 测试中使用了什么,而我有v instanceof RecyclerView
    • 嗯,目前它是一样的 (v instanceof RecyclerView) 但我不认为 canScroll()RecylerViews 接收 onSwiped() 有影响,你有什么建议吗?我可以检查 View ID,但我不确定。
    • 垂直滚动在RecyclerView 上仍然可以正常工作,只是左右滑动卡片不起作用。 @CommonsWare
    • @wdavies973:添加|| v instanceof CardView(或任何您的卡片),看看会发生什么。基本上,您希望 canScroll() 返回 true 用于您希望自己滚动/滑动的任何小部件,否则 false
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-23
    • 1970-01-01
    • 1970-01-01
    • 2011-06-05
    • 1970-01-01
    相关资源
    最近更新 更多