解决scrollview嵌套布局带来的惯性丢失和不流畅问题

ScrollView 嵌套ViewPage,如果事件没有传递ViewPage在需要滑动的时候会遇到不流畅的问题,ScrollView 嵌套RecyclerView又会有一个惯性丢失的问题。

解决方法

对于以上两种情况,一个是ScrollView把不该处理的滑动方向处理了,这时候屏蔽一个方向下放到子view处理即可,对于嵌套RecyclerView的则应该完全交由ScrollView处理。单独的例子可以找到很多,这里贴一个自用的两种结合的例子。

需求:ScrollView同时嵌套了ViewPage和RecyclerView,对于左右事件完全交由子View处理,对于竖直事件完全交由ScrollView处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.ScrollView;

/**
* 屏蔽左右滑动事件&&解决滑动惯性丢失
*
* @author zhisheng created on 2016/3/11 0011.
*/
public class CustomScrollView extends ScrollView {
private GestureDetector mGestureDetector;
private float downY;
private float mTouchSlop;

public CustomScrollView(Context context) {
super(context);
mGestureDetector = new GestureDetector(context, new YScrollDetector());
setFadingEdgeLength(0);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}

public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureDetector = new GestureDetector(context, new YScrollDetector());
setFadingEdgeLength(0);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}

public CustomScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mGestureDetector = new GestureDetector(context, new YScrollDetector());
setFadingEdgeLength(0);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}

@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
int action = e.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
downY = e.getRawY();
break;
case MotionEvent.ACTION_MOVE:
float moveY = e.getRawY();
if ((Math.abs(moveY - downY) > mTouchSlop) && mGestureDetector.onTouchEvent(e)) {
return true;
}
break;
}

return super.onInterceptTouchEvent(e) && mGestureDetector.onTouchEvent(e);

}
//如果是左右滑动则返回false
class YScrollDetector extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return Math.abs(distanceY) > Math.abs(distanceX);
}
}
}