Viewpager2禁止滑动的多个方面分析

发布时间:2023-05-20

Viewpager2是Android端的一个强大的滑动组件,可以轻松地实现左右滑动浏览、以及无限滑动等功能。但是,在实际应用中,有时也需要禁止Viewpager2的滑动功能,比如在某些情况下需要将Viewpager2嵌套在ScrollView中,这时如果不禁止Viewpager2的滑动,则Scrollview和Viewpager2的滑动会相互干扰,造成用户操作体验的下降。本文将从多个方面对Viewpager2的禁止滑动进行详细的阐述。

一、Viewpager2滑动监听

在Viewpager2上禁止滑动,可以通过自定义OnPageChangeCallback类来实现滑动监听并且在滑动操作时禁止轮播。具体实现如下:

private class NoScrollOnPageChangeCallback extends ViewPager2.OnPageChangeCallback {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        // 禁止滑动
    }
    @Override
    public void onPageSelected(int position) {}
    @Override
    public void onPageScrollStateChanged(int state) {}
}

在该类中,onPageScrolled()方法会被调用,只要用户在Viewpager2上左右滑动,该方法就会被调用,接下来只需要在该方法中实现禁止滑动功能即可,代码如下:

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    // 禁止滑动
    viewPager2.stopScroll();
}

利用该方法,我们可以在Viewpager2上轻松实现禁止滑动,保证用户在ScrollView中正常滑动。

二、Viewpager2上下滑动

有时候,需要在Viewpager2中添加纵向滑动的功能,此时便需要禁止Viewpager2的左右滑动,而允许上下滑动。实现方式如下:

public class CustomViewPager2 extends ViewPager2 {
    private boolean isPagingEnabled = true;
    public CustomViewPager2(@NonNull Context context) {
        super(context);
    }
    public CustomViewPager2(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
    public void setPagingEnabled(boolean pagingEnabled) {
        isPagingEnabled = pagingEnabled;
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return isPagingEnabled && super.onTouchEvent(event);
    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return isPagingEnabled && super.onInterceptTouchEvent(event);
    }
}

在该类中,重写onTouchEvent()方法和onInterceptTouchEvent()方法,在需要禁止Viewpager2滑动时,将isPagingEnabled属性设置为false即可。接下来,在ScrollView中嵌套该CustomViewPager2即可实现上下滑动,而禁止左右滑动。

三、Viewpager2太容易左右滑动

有时候,用户可能会在很轻松的情况下误触Viewpager2而造成页面的切换,这时需要增加Viewpager2的敏感度,避免用户误触。我们可以通过设置ViewPager2的滑动阈值来解决该问题,代码如下:

private final int TOUCH_THRESHOLD = 20;
private float mTouchDownX;
private class TouchController implements View.OnTouchListener {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mTouchDownX = event.getX(0);
                break;
            case MotionEvent.ACTION_MOVE:
                float moveX = event.getX(0);
                if (Math.abs(moveX - mTouchDownX) > TOUCH_THRESHOLD) {
                    // 如果滑动距离大于阈值,禁止滑动
                    viewPager2.stopScroll();
                }
                break;
            default:
                break;
        }
        return false;
    }
}

该方法中,通过onTouch()方法监听Viewpager2上的滑动事件,在用户移动手指时,判断移动距离是否大于指定的阈值,如果大于,则禁止滑动。需要注意的是,该方法只有在监听到的ACTION_MOVE事件中进行判断,防止误判。

四、Viewpager2无限滑动

Viewpager2本身带有无限滑动的功能,即当用户滑动到最后一页时,再次滑动将会回到第一页。如果需要禁止上述功能,可以在Adapter中的getItemCount()方法中返回真实的Item个数,进而禁止无限滑动。代码如下:

@Override
public int getItemCount() {
    return realList.size();
}

其中,realList为Viewpager2的真实Item列表。

五、Viewpager2禁止滑动完整代码示例

视不同功能需求,Viewpager2禁止滑动的代码实现可能有所不同,下面是一个完整的实现示例:

public class MainActivity extends AppCompatActivity {
    private CustomViewPager2 viewPager2;
    private List<String> dataList;
    private TouchController touchController;
    private NoScrollOnPageChangeCallback noScrollOnPageChangeCallback;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewPager2 = findViewById(R.id.viewPager2);
        dataList = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            dataList.add(i + "");
        }
        viewPager2.setAdapter(new MyAdapter(dataList));
        // Viewpager2上下滑动
        touchController = new TouchController();
        viewPager2.setOnTouchListener(touchController);
        // Viewpager2滑动监听
        noScrollOnPageChangeCallback = new NoScrollOnPageChangeCallback();
        viewPager2.registerOnPageChangeCallback(noScrollOnPageChangeCallback);
    }
    class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
        private List<String> list;
        public MyAdapter(List<String> list) {
            this.list = list;
        }
        @NonNull
        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            TextView textView = new TextView(parent.getContext());
            textView.setTextSize(30);
            return new ViewHolder(textView);
        }
        @Override
        public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
            holder.textView.setText(list.get(position));
        }
        @Override
        public int getItemCount() {
            return list.size();
        }
        class ViewHolder extends RecyclerView.ViewHolder {
            public TextView textView;
            public ViewHolder(@NonNull View itemView) {
                super(itemView);
                textView = (TextView) itemView;
            }
        }
    }
    private class NoScrollOnPageChangeCallback extends ViewPager2.OnPageChangeCallback {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            // 禁止滑动
            viewPager2.stopScroll();
        }
        @Override
        public void onPageSelected(int position) {}
        @Override
        public void onPageScrollStateChanged(int state) {}
    }
    public class CustomViewPager2 extends ViewPager2 {
        private boolean isPagingEnabled = true;
        public CustomViewPager2(@NonNull Context context) {
            super(context);
        }
        public CustomViewPager2(@NonNull Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
        }
        public void setPagingEnabled(boolean pagingEnabled) {
            isPagingEnabled = pagingEnabled;
        }
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            return isPagingEnabled && super.onTouchEvent(event);
        }
        @Override
        public boolean onInterceptTouchEvent(MotionEvent event) {
            return isPagingEnabled && super.onInterceptTouchEvent(event);
        }
    }
    private final int TOUCH_THRESHOLD = 20;
    private float mTouchDownX;
    private class TouchController implements View.OnTouchListener {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mTouchDownX = event.getX(0);
                    break;
                case MotionEvent.ACTION_MOVE:
                    float moveX = event.getX(0);
                    if (Math.abs(moveX - mTouchDownX) > TOUCH_THRESHOLD) {
                        // 如果滑动距离大于阈值,禁止滑动
                        viewPager2.stopScroll();
                    }
                    break;
                default:
                    break;
            }
            return false;
        }
    }
}

六、总结

本文从多个方面对Viewpager2的禁止滑动进行了详细的阐述,通过自定义OnPageChangeCallback类对Viewpager2上的滑动进行监听,通过自定义CustomViewPager2类实现上下滑动和禁止左右滑动,通过设置滑动阈值和禁止无限滑动实现Viewpager2的各种功能。以上方法可以帮助开发者在需要禁止Viewpager2滑动时,保证用户体验,提高应用质量。