场景
recyclerivew使用PagerSnapHelper,子布局中,使用scrollview,观察,scrollview内容
区域超过高度时,滑动失效。
原因
recyclerview的触摸事件,没有分发到scrollview中,导致了scrollview的触摸事件失效。
解决方法
(1)当scrollview不需要滑动的时候,无需处理
(2)当scrollview需要滑动的时候,需要捕获触摸事件。对于捕获的事件后,需要判断
scrollview是否已经处于顶部/底部,若是,则不再处理触摸事件,否则需要处理触摸事件。
实现
(1)判断scrollview是否满足滑动的条件,原理是计算scrollview的子类总高度,再对比当前
scrollview的高度,判断是否满足,核心代码如下:
/**
* 所有子布局高度
*/
private int getChildHeight() {
if (getChildCount() == 0) {
return 0;
}
int result = 0;
for (int i = 0; i < getChildCount(); i++) {
result = result + getChildAt(i).getMeasuredHeight();
}
return result;
}
/**
* 是否有超出内容
*/
private boolean outSide() {
return getChildHeight() > getMeasuredHeight();
}
(2)对scrollview进行滑动监听,初始化滑动到顶部/底部的变量,核心代码如下:
setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
@Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
try {
if (scrollY > oldScrollY) {
// 向下滑动
}
if (scrollY < oldScrollY) {
// 向上滑动
}
if (scrollY == 0) {
// 顶部
// LogUtil.d("PagerSnapScrollView onScrollChange top");
mIsTop = true;
} else {
// LogUtil.d("PagerSnapScrollView onScrollChange top2");
mIsTop = false;
}
if (scrollY == (v.getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight())) {
//底部
// LogUtil.d("PagerSnapScrollView onScrollChange bottom");
mIsBottom = true;
} else {
// LogUtil.d("PagerSnapScrollView onScrollChange bottom2");
mIsBottom = false;
}
} catch (Exception e) {
}
}
});
(3)最后,在scrollview的事件分发中,进行分发的处理,核心代码如下:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (outSide()) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownY = (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
int endY = (int) ev.getY();
if ((mIsBottom && (mDownY > endY))) {
setDisallowIntercept(false);
return super.dispatchTouchEvent(ev);
}
if ((mIsTop && mDownY < endY)) {
setDisallowIntercept(false);
return super.dispatchTouchEvent(ev);
}
setDisallowIntercept(true);
return super.dispatchTouchEvent(ev);
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
return super.dispatchTouchEvent(ev);
}
setDisallowIntercept(false);
return super.dispatchTouchEvent(ev);
} else {
return super.dispatchTouchEvent(ev);
}
}
that's all------------------------------------