本文为自己多年来在 Android 实战开发过程中总结归纳的一些常见问题,现在分享出来希望对初学者有所帮助。
事件分发是 Android 开发过程中的重点又是难点, 一张事件分发流程图,让你彻底搞明白。网上有很多文章写事件分发,感觉都没有讲明白,恭喜你,今天你看到好文章了,你彻底搞清楚…
目录
2.触摸事件的类型?
3.事件传递的三个阶段?
4.简述 View 的事件传递机制?
5.简述 ViewGroup 的事件传递机制?
6.事件分发流程图
7.实战案例
1.在 Android 操作系统中,拥有事件传递功能的类都有哪些?
-
Activity: 拥有 dispathTouchEvent 和 onTouchEvent 方法 -
View: 拥有 dispathTouchEvent 和 onTouchEvent 方法 -
ViewGroup: 拥有 dispatchTouchEvent、onTouchEvent、onInterceptTouchEvent
2.触摸事件的类型?
-
ACTION_DOWN: 手指的按下操作 -
ACTION_MOVE: 手指按下后,松开手之前,轻微移动所触发的事件 -
ACTION_UP: 手指离开屏幕的操作
3.事件传递的三个阶段?
3.1 按照事件进行划分
3.2 按照 View 进行划分
结论: 无论是 View 还是 ViewGroup,不管他是 DispatchTouchEvent 还是 onTouchEvent 方法,方法返回 true、返回 false 的处理逻辑都是一样的,只是调用父类的同名方法的时候处理的逻辑有所不同,View 偏重消费、ViewGourp 偏重分发。
4.简述 View 的事件传递机制?
触摸事件的传递流程是从 dispatchTouchEvent 开始的,如果不进行人工干预,则事件将会依照 View 树的嵌套层次从外层向内层传递,到达最内层的 View 时,就由它的 onTouchVent 方法处理。
5.简述 ViewGroup 的事件传递机制?
触摸事件的传递顺序是由 Activity 到 ViewGroup,再由 ViewGroup 递归传递给他的子 View,ViewGroup 通过 onInterceptTouchEvent 方法对事件进行拦截,如果该方法返回 true,则事件不会继续往下传递给子 View,如果返回 false 或者是调用 super.onInterceptTouchEvent,则事件会继续会传递给子 View。
6.事件分发流程图
一张 Android 事件分发流程,让你彻底搞明白 Android 的事件分发机制。
7.实战案例
实现效果如下,底部的行程详情可以往上拖动覆盖在地图之上,也可以往下拖动停止在屏幕的正中位置,地图相关操作: 放大、缩小、移动都能正常的响应,怎么实现?下面就是具体的源码实现过程。
7.1 事件分发处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
mTransparentView = findViewById(R.id.view_tansparent); mTransparentView.setListener(new TransparentView.TouchEventListener() { @Override public boolean dispatchTouchEvent(MotionEvent event) { return mMapView.dispatchTouchEvent(event); } }); mScrollView = findViewById(R.id.view_scrollview); mScrollView.setListener(new TransparentView.TouchEventListener() { @Override public boolean dispatchTouchEvent(MotionEvent event) { Rect rect = new Rect(); mTransparentView.getLocalVisibleRect(rect); if(rect.contains((int)event.getX(),(int)event.getY())){ return true; }else{ return false; } } }); |
7.2 自定义 ViewTransparentView
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class TransparentView extends View { TouchEventListener mListener; public interface TouchEventListener{ boolean dispatchTouchEvent(MotionEvent event); } public TransparentView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent event) { if(mListener != null){ return mListener.dispatchTouchEvent(event); }else{ return super.dispatchTouchEvent(event); } } public void setListener(TouchEventListener listener) { mListener = listener; } } |
7.3 自定义 TransScrollView
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class TransScrollView extends NestedScrollView { public TransparentView.TouchEventListener mListener; public TransScrollView(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (mListener != null && mListener.dispatchTouchEvent(ev)) { return false; } return super.onInterceptTouchEvent(ev); } public void setListener(TransparentView.TouchEventListener listener) { mListener = listener; } } |
7.4 布局文件
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 |
<FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" > <com.amap.api.maps.MapView android:id="@+id/map" android:layout_width="match_parent" android:layout_height="250dp" /> <com.zhijiaxing.travel.trip.record.view.TransScrollView android:id="@+id/view_scrollview" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <com.zhijiaxing.travel.trip.record.view.TransparentView android:id="@+id/view_tansparent" android:layout_width="match_parent" android:layout_height="250dp" android:background="#00000000" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ffffff" android:orientation="vertical" > </LinearLayout> </LinearLayout> </com.zhijiaxing.travel.trip.record.view.TransScrollView> </FrameLayout> |