博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
点击图片大图预览,RecyclerView + PhotoView 滑动冲突,RecyclerView不回调SCROLL_STATE_IDLE...
阅读量:5945 次
发布时间:2019-06-19

本文共 4365 字,大约阅读时间需要 14 分钟。

背景

最近项目需要集成一个点击图片大图预览的功能。网上很多都是ViewPager + PhotoView的形式;这次想换个姿势,使用了 RecyclerView + PhotoView的方式,其中主要是RecyclerView的PagerSnapHelper来实现模拟ViewPager的翻页效果。

问题

开发过程中,其他的倒是一切正常,主要遇到以下两个问题:

  1. PhotoView双指放大 和 RecyclerView左右滑动 冲突,本来是想双指放大PhotoView,结果RecyclerView滑动了;
  2. 为实现ViewPager的onPageSelected监听效果,给RecyclerView增加onScrollStateChanged监听来判断当前显示的item,使用中发现当快速滚动到第一个时,SCROLL_STATE_IDLE状态不会被回调。

解决

1. 针对第一个问题,目前的思路是自定义RecyclerView

判断是否是多点触控,是的话就放行给子PhotoView处理,不是就RecyclerView处理。但是这样会有一个问题,就是两个或者三个或更多手指在屏幕上时就没办法左右滑动RecyclerView了。但是我也觉得无所谓,毕竟应该没有人用多个手指去左右翻页。。。

代码如下:

/** * 图片预览 RecyclerView * Create By lishilin On 2019/3/25 */public class PreviewRecyclerView extends RecyclerView {    private boolean isLock;// 是否锁住 RecyclerView ,避免和 PhotoView 双指放大缩小操作冲突    public PreviewRecyclerView(@NonNull Context context) {        super(context);    }    public PreviewRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {        super(context, attrs);    }    public PreviewRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    @Override    public boolean onInterceptTouchEvent(MotionEvent event) {        switch (event.getActionMasked()) {            case MotionEvent.ACTION_POINTER_DOWN:// 非第一个触点按下                isLock = true;                break;            case MotionEvent.ACTION_UP:// 最后一个触点抬起                isLock = false;                break;        }        if (isLock) {            return false;// 不拦截,交给子View处理        }        return super.onInterceptTouchEvent(event);    }    @Override    public boolean dispatchTouchEvent(MotionEvent event) {        switch (event.getActionMasked()) {            case MotionEvent.ACTION_POINTER_DOWN:// 非第一个触点按下                isLock = true;                break;            case MotionEvent.ACTION_UP:// 最后一个触点抬起                isLock = false;                break;        }        return super.dispatchTouchEvent(event);    }}复制代码

2. 针对第二个问题,暂时发现两种解决办法。

  1. 在onScrollStateChanged回调中不判断state状态,这样就绕过了SCROLL_STATE_IDLE的问题,但是会一直执行代码,需要注意效率问题,特别是耗时操作,避免卡顿。
    代码如下:
rv_photo.addOnScrollListener(new RecyclerView.OnScrollListener() {            @Override            public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {                super.onScrollStateChanged(recyclerView, newState);                View view = snapHelper.findSnapView(layoutManager);                if (view == null) {                    return;                }                int position = layoutManager.getPosition(view);                if (lastPosition == position) {                    return;                }                lastPosition = position;                refreshCountTips(lastPosition);                PhotoPreviewRecyclerAdapter.ViewHolder holder = (PhotoPreviewRecyclerAdapter.ViewHolder) rv_photo.getChildViewHolder(view);                if (holder == null || holder.img_content == null) {                    return;                }                if (holder.img_content.getScale() != 1f) {                    holder.img_content.setScale(1f, true);                }            }        });复制代码
  1. 在上面的回调中正常加入SCROLL_STATE_IDLE的判断,但是需要手动调用recyclerView.stopScroll()方法。
if (newState != RecyclerView.SCROLL_STATE_IDLE) {                    return;                }复制代码
rv_photo.setOnTouchListener(new View.OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                switch (event.getActionMasked()) {                    case MotionEvent.ACTION_UP:                        if (rv_photo.getScrollState() == RecyclerView.SCROLL_STATE_IDLE) {                            break;                        }                        View view = snapHelper.findSnapView(layoutManager);                        if (view == null) {                            break;                        }                        int position = layoutManager.getPosition(view);                        if (position != 0) {                            break;                        }                        if (rv_photo.getChildAt(0).getX() == 0 && rv_photo.canScrollHorizontally(1)) {                            rv_photo.stopScroll();                        }                        break;                }                return false;            }        });复制代码

转载于:https://juejin.im/post/5c99b55f6fb9a070cd56a8d3

你可能感兴趣的文章
obj-c 定义一个类
查看>>
电脑APK
查看>>
HDU-4335 What is N? 欧拉函数,欧拉定理
查看>>
HDU 1044 Collect More Jewels(搜索,先bfs再dfs)
查看>>
使用RabbitMQ过程中遇到的一个问题(队列为空,但内存暴涨)以及与开发者的邮件沟通...
查看>>
C++/C学习笔记(九)
查看>>
ASP.net MVC 中Security.FormsAuthentication验证用户的状态(匿名|已登录)
查看>>
《C++ Primer》 Part III(Classes and Data Abstraction)
查看>>
FriendlyUrls——在ASP.NET Web表单中使用更友好的URL
查看>>
【javascript】字符串对象常用 api
查看>>
对PostgreSQL中 index only scan 的初步理解
查看>>
poj 2337 Catenyms
查看>>
第46周星期二
查看>>
hdu1231-最大连续子序列
查看>>
TMG阵列部署选择
查看>>
Repeater 控件 当数据源没有数据的时候显示 暂无数据 的两种方式
查看>>
大型网站的架构设计图分享-转
查看>>
9.15游戏化体验的原则初探
查看>>
(function(){...}())与(function(){...})()
查看>>
css实现气泡框效果
查看>>