当前位置: 首页 > 知识库问答 >
问题:

当子回收站视图滚动到最后一项时,禁用ViewPager分页

商柏
2023-03-14

我有一个视图寻呼机,在其中一个片段中,我有两个单独的片段,分别包含一个垂直和一个水平的回收视图。

当我将水平循环视图滚动到最后一个项目并尝试进一步滑动时,视图寻呼机滚动到下一页。我不想发生这种事。当我试图覆盖水平循环视图时,我想禁用viewpager的分页。

但是,当我在其他地方滑动时,我不想禁用viewpager的分页功能。例如,如果我在垂直recyclerview或父片段中的任何空白区域上滑动,仍然会导致viewpager换页。

我在这个SO问题中读到,如何禁用分页的分页。此外,这个SO问题也类似,因为有一个子视图页面管理器,但是我没有成功地尝试用水平回收视图复制它。

以下是一些结构:

允许我禁用分页的自定义viewpager(取自上面的第一个SO链接):

public class CustomViewPager extends ViewPager {

private boolean enabled;

public CustomViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.enabled = true;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (this.enabled) {
        return super.onTouchEvent(event);
    }

    return false;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    if (this.enabled) {
        return super.onInterceptTouchEvent(event);
    }

    return false;
}

public void setPagingEnabled(boolean enabled) {
    this.enabled = enabled;
} }

对于水平循环视图,我设置了一个ontouchlistener(类似于上面的第二个SO链接):

horizontalRecyclerView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch(event.getAction()){
                        case MotionEvent.ACTION_MOVE:
                            customViewPager.setPagingEnabled(false);
                            break;
                        case MotionEvent.ACTION_UP:
                            customViewPager.setPagingEnabled(true);
                            break;
                    }
                    return false;
                }
            });

额外观察:我注意到,有时如果我在滑动前长按水平循环视图,它就不会转到寻呼机的下一页。但是,如果我快速滑动,浏览器将转到下一页。

有人知道做这件事的正确方法吗?

任何帮助是值得赞赏的。

共有3个答案

皮弘博
2023-03-14

以防有人有和我一样的问题。

如果您的层次结构中有一个SwipeRefreLayout,并且它的子级确实为ViewCompat.isNestedScrollEnabled()返回true(在我的例子中是FrameLayout),这将不起作用,因为在它传递Request estDislowInterceptTouchEvent()之前在中进行了检查。

花了我一点时间进行调试,但这是来自滑动刷新布局的特定检查:

if ((VERSION.SDK_INT >= 21 || !(this.mTarget instanceof AbsListView)) && (this.mTarget == null || ViewCompat.isNestedScrollingEnabled(this.mTarget))) {
    super.requestDisallowInterceptTouchEvent(b);
}

通过删除FrameLayout,使SwipeRefreLayout的子级成为NestedScrollView,我能够让Shabbir Dangot的答案生效。

郭皓
2023-03-14

为了处理垂直滚动不再工作的问题,我这样做了:

为回收器视图项目创建触摸侦听器

mGestureDetector = new GestureDetector(itemView.getContext(), new GestureListener());

/**
 * Prevents the view pager from switching tabs when scrolling the carousel
 */
private class TouchListener implements RecyclerView.OnItemTouchListener {

  @Override
  public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
      mGestureDetector.onTouchEvent(e);
      return false;
  }
}

并实现一个在检测到水平滚动时禁止触摸事件的GestureListener:

private class GestureListener extends SimpleOnGestureListener {
    private final int Y_BUFFER = 10;

    @Override
    public boolean onDown(MotionEvent e) {
        // Prevent ViewPager from intercepting touch events as soon as a DOWN is detected.
        // If we don't do this the next MOVE event may trigger the ViewPager to switch
        // tabs before this view can intercept the event.
        mRecyclerView.requestDisallowInterceptTouchEvent(true);
        return super.onDown(e);
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        if (Math.abs(distanceX) > Math.abs(distanceY)) {
            // Detected a horizontal scroll, prevent the viewpager from switching tabs
            mRecyclerView.requestDisallowInterceptTouchEvent(true);
        } else if (Math.abs(distanceY) > Y_BUFFER) {
            // Detected a vertical scroll of large enough magnitude so allow the the event
            // to propagate to ancestor views to allow vertical scrolling.  Without the buffer
            // a tab swipe would be triggered while holding finger still while glow effect was
            // visible.
            mRecyclerView.requestDisallowInterceptTouchEvent(false);
        }
        return super.onScroll(e1, e2, distanceX, distanceY);
    }
}
邹宣
2023-03-14

这是解决方案

requestDisallowInterceptTouchEvent()

此方法不允许父级移动。它停止查看寻呼机触摸事件。

horizontalRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
            int action = e.getAction();
            switch (action) {
                case MotionEvent.ACTION_MOVE:
                    rv.getParent().requestDisallowInterceptTouchEvent(true);
                    break;
            }
            return false;
        }

        @Override
        public void onTouchEvent(RecyclerView rv, MotionEvent e) {

        }

        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

        }
    });
 类似资料:
  • 我有一个水平回收视图。每个子级包含一个TextView和一个垂直RecyclerView。垂直RecyclerView的子级仅包含TextView。 垂直滚动非常平滑,但水平滚动滞后很多。我已经尝试在onBindViewHolder中使用swapAdapter,而不是setAdapter,但这并没有解决问题。我也尝试过更改数据集并调用notifyDataSetChanged(),但这也没有帮助。

  • 我在ViewPager中的NestedScrollView中有一个水平的RecyclerView。现在当我尝试滚动RecyclerView时,有时它滚动,但有时只有ViewPager滚动。 这就是我的RecyclerView XML的样子: 到目前为止,我所尝试的,正如你所看到的,我写了一个自定义的viewpager。我尝试告诉ViewPager,如果滚动来自RecyclerView,它就不能滚动

  • 我有一个回收站视图,在右下顶部有一个FAB。 当滚动时,我希望允许用户进一步向上滚动,以使最后一项完全可见,并且不被FAB覆盖。允许在底部额外显示48像素的背景即可。 我尝试添加一个透明的页脚项目,这可以解决问题。但是,在向列表中添加排序后,透明页脚项在排序过程中会产生一些 UI 故障(分隔线显示在正常项的下方)。 我试着添加了一个边距,但是空间总是被浪费掉了。当用户在顶部查看第一个项目时,FAB

  • 我有一个endless Recycler视图,其中包含使用JSoup从一个在线论坛线程中提取的数据。recyclerview将不断填充自己,直到用户到达最后一页。我想膨胀一个“端视图”,一旦用户到达最后一页,滚动到最后一个可见的项目,但我无法检索它。 我尝试使用getItemCount()和findLastVisibleItemPotion()从回收器视图linearlayoutManager。它

  • 我正在开发一个消息应用程序,布局没有什么花哨的-布局顶部的,底部的和消息列表的,填充中间的空间。 我的问题是,当通过单击/按显示软键盘时,中最后一个可见项目的位置不会保持。例如,如果列表有20个项目,并且当软键盘未显示时最后一个可见的是项目12,当软键盘显示时,我仍然希望最后一个可见的是项目12。 我已经在清单和代码中尝试了adjustPan和adjustResize的组合,但没有解决问题。 有什

  • 向下和向上滚动后滚动回收器视图时遇到问题。这个想法是改变元素的颜色,但是当我向下滚动时,一切都很好,当滚动向上时——不应该着色的元素正在改变颜色。 这是我的适配器: