碰到了一个需求,在recycleview中嵌套地图作为头布局。跟列表一起滑动,当然很简单就可以套进去,但是当滑动地图的时候,列表也会跟着滑动.emm…滑动冲突
1、先了下解安卓事件分发机制?
不了解,不懂事件分发,没关系看下面的图就行了。
列出几个重要的记忆点
1、activity和view都是没有 onInterceptTouchEvent()这个方法的
2、dispatchTouchEvent() 的返回值,true都是消费掉,false则返回上一级的onTouchEvent()做处理,如果是activity层,则交给自身的onTouchEvent()处理
3、 onInterceptTouchEvent()的返回值,true交给自己的onTouchEvent()做处理,false给下一级dispatchTouchEvent()做分发
4、onTouchEvent()的返回值,true让事件消费掉不再传递,false传递回上级的onTouchEvent()
2、知道了流程该如何处理?
Recycleview继承了ViewGroup,肯定是onInterceptTouchEvent()里进行了事件的判断并且拦截,然后给自身的onTouchEvent()处理进行滑动和消费,子view就拿的滑动事件就是断断续续的了,造成的冲突。
对,我们就可以在onInterceptTouchEvent()这里动刀子,如果down在了地图的view上面,或者说在第一个item上面,就可以直接返回false,不让recycleview拦截,否则的话就按recycleview的原来的流程走。
public class MapRecycler extends AutoLoadRecyclerView {
public MapRecycler(@NonNull Context context) {
super(context);
}
public MapRecycler(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MapRecycler(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
int x = (int) e.getX();
int y = (int) e.getY();
int point = pointToPosition(x, y);
//如果点 的是地图,这里我的地图是在第二个item里面所以是1
if (point ==1) {
ViewGroup view = (ViewGroup) getChildAt(point);
if (view != null) {
return false;
}
}
return super.onInterceptTouchEvent(e);
}
private static final int INVALID_POSITION = -1; // 触摸到的点不在子View范围内
private Rect mTouchFrame; // 子View所在的矩形范围
public int pointToPosition(int x, int y) {
int firstPosition = ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
Rect frame = mTouchFrame;
if (frame == null) {
mTouchFrame = new Rect();
frame = mTouchFrame;
}
final int count = getChildCount();
for (int i = count - 1; i >= 0; i--) {
final View child = getChildAt(i);
if (child.getVisibility() == View.VISIBLE) {
child.getHitRect(frame);
if (frame.contains(x, y)) {
return firstPosition + i;
}
}
}
return INVALID_POSITION;
}
}