一、使用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);