日常开发之RecycleView滑动

一、使用recyclerview.scrollToPosition(index)滑动布局,结果定位不准确

解决办法:

//使用LayoutManager滑动位置并设置offset为0,可以保证滑动的位置正确
mLayoutManager.scrollToPositionWithOffset(index, 0);

二、区分手动滑动和代码滑动

/**
 * @author : zhn
 * @date : 2022/7/1 18:02
 * description :滑动监听,判断是不是用户自己手动滑动
 */
public class ScrollListenerRecyclerView extends RecyclerView {

    //用户触发的滑动含filling状态
    private boolean userScroll;

    //用户拖动
    private boolean userTouch;

    public ScrollListenerRecyclerView(@NonNull Context context) {
        super(context);
    }

    public ScrollListenerRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public ScrollListenerRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mListener != null) {
            mListener.onScrollChanged(userScroll, l, t, oldl, oldt);
        }
    }

    @Override
    public void onScrollStateChanged(int state) {
        super.onScrollStateChanged(state);
        if (state == SCROLL_STATE_IDLE && !userTouch) {
            userScroll = false;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        if (e.getAction() == MotionEvent.ACTION_MOVE) {
            userTouch = true;
            userScroll = true;
        } else if (e.getAction() == MotionEvent.ACTION_UP) {
            userTouch = false;
        }
        return super.onTouchEvent(e);
    }

    public interface ScrollChangeListener {

        void onScrollChanged(boolean fromUser, int l, int t, int oldl, int oldt);
    }

    private ScrollChangeListener mListener;

    public void setListener(ScrollChangeListener listener) {
        mListener = listener;
    }
}

用法:

mBinding.rlvCourseDetail.setListener(new ScrollListenerRecyclerView.ScrollChangeListener() {
    @Override
    public void onScrollChanged(boolean fromUser, int l, int t, int oldl, int oldt) {
        if (fromUser) {
            scrollSwitchTab();
        }
    }
});

三、RecyclerView嵌套WebView滑动冲突解决

 原则上WebView不应该作为RecyclerView中的一个Item,因为会有滑动冲突。如果有这样的需求必须这么处理,那么就需要解决滑动冲突了,以竖直方向上的普通列表为例。

3.1 竖直方向上滑动冲突解决

一般方案是,让webView在竖直方向上不能滑动,通过js跟原生交互,动态设置Webview的高度正好是内容的高度。

3.2 水平方向上的滑动冲突解决

水平方向和RecycleView滑动方向不同,所以原则上我们应该允许webView水平滑动,但是实际操作中会发现水平滑动十分不流畅,原因是水平滑动事件有时被RecyclerView处理了。为了解决这个问题,我们让水平滑动时RecyclerView始终不处理touch事件。

private float startX;
private float startY;
private float offsetX;
private float offsetY;

webView.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //父布局(RecyclerView)不消费点击事件
                getParent().requestDisallowInterceptTouchEvent(true);
                startX = event.getX();
                startY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                offsetX = Math.abs(event.getX() - startX);
                offsetY = Math.abs(event.getY() - startY);
                if (offsetX > offsetY) {
                    //父布局(RecyclerView)不消费水平滑动事件
                    getParent().requestDisallowInterceptTouchEvent(true);
                } else {
                    //竖直方向上的滑动事件,正常分发
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
                break;
            default:
                break;
       }
       return false;
    }
});

四、RecyclerView以WebView作为item时,列表位置跳动

原因是webview焦点变化,导致RecyclerView默认定位到焦点位置了。可以设置webview不获取焦点。

webView.setFocusable(enabled);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值