哪一个平阳网站建设,有口碑的盐城网站开发,宣传片拍摄方案范本,wordpress 页面内存大事件的传递主要有三个方法#xff1a;dispatchTouchEvent(事件分发)、onInterceptTouchEvent(事件拦截)、onTouchEvent(事件消费)。如下图#xff1a; 仔细看的话#xff0c;图分为3层#xff0c;从上往下依次是Activity、ViewGroup、View事件从左上角那个白色箭头开始dispatchTouchEvent(事件分发)、onInterceptTouchEvent(事件拦截)、onTouchEvent(事件消费)。如下图 仔细看的话图分为3层从上往下依次是Activity、ViewGroup、View事件从左上角那个白色箭头开始由Activity的dispatchTouchEvent做分发箭头的上面字代表方法返回值return true、return false、return super.xxxxx(),super 的意思是调用父类实现。dispatchTouchEvent和 onTouchEvent的框里有个【true----消费】的字表示的意思是如果方法返回true那么代表事件就此消费不会继续往别的地方传了事件终止。 事件分成好几种类型我们常用的就三种从手指按下移动到抬起依次为ACTION_DOWN(按下)、ACTION_MOVE(移动)、ACTION_UP(抬起)。之前图中的Activity 的dispatchTouchEvent 有误图已修复只有return super.dispatchTouchEvent(ev) 才是往下走返回true 或者 false 事件就被消费了终止传递
事件的传递过程 事件的传递在我们手指按下(ACTION_DOWN)的瞬间发生了,如果手指有移动会触发若干个移动事件(ACTION_MOVE),当你手指抬起时会触发ACTION_UP事件这样为一个事件序列。我们先来看看单个事件时怎么传递的。 Activity代码如下 Overridepublic boolean onTouchEvent(MotionEvent event) {Log.d(MainActivity,onTouchEvent:);switch (event.getAction()) {case MotionEvent.ACTION_DOWN: //按下的动作Log.d(MainActivity, View onTouchEvent ACTION_DOWN);break;case MotionEvent.ACTION_MOVE: //滑动的动作Log.d(MainActivity, View onTouchEvent ACTION_MOVE);break;case MotionEvent.ACTION_UP: //离开的动作Log.d(MainActivity, View onTouchEvent ACTION_UP);break;}return super.onTouchEvent(event);}Overridepublic boolean dispatchTouchEvent(MotionEvent event) {Log.d(MainActivity,dispatchTouchEvent:);switch (event.getAction()) {case MotionEvent.ACTION_DOWN: //按下的动作Log.d(MainActivity, View dispatchTouchEvent ACTION_DOWN);break;case MotionEvent.ACTION_MOVE: //滑动的动作Log.d(MainActivity, View dispatchTouchEvent ACTION_MOVE);break;case MotionEvent.ACTION_UP: //离开的动作Log.d(MainActivity, View dispatchTouchEvent ACTION_UP);break;}return super.dispatchTouchEvent(event);}
布局文件如下
?xml version1.0 encodingutf-8?
layout xmlns:androidhttp://schemas.android.com/apk/res/androidandroidx.drawerlayout.widget.DrawerLayout xmlns:apphttp://schemas.android.com/apk/res-autoxmlns:toolshttp://schemas.android.com/toolsandroid:idid/drawer_layoutandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid:fitsSystemWindowstruetools:context.ui.MainActivityincludeandroid:idid/includelayoutlayout/app_bar_mainandroid:layout_widthmatch_parentandroid:layout_heightmatch_parent /........!--app:headerLayoutlayout/nav_header_main--!--app:menumenu/activity_main_drawer--/androidx.drawerlayout.widget.DrawerLayout
/layout
app_bar_main.xml 布局如下
?xml version1.0 encodingutf-8?
layout xmlns:androidhttp://schemas.android.com/apk/res/androidLinearLayout xmlns:apphttp://schemas.android.com/apk/res-autoxmlns:toolshttp://schemas.android.com/toolsandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid:fitsSystemWindowstrueandroid:orientationverticaltools:contextcom.example.jingbin.cloudreader.ui.MainActivity!--状态栏--Viewandroid:idid/view_statusandroid:layout_widthmatch_parentandroid:layout_height24dpandroid:backgroundcolor/colorHomeToolBarandroid:visibilitygone /androidx.appcompat.widget.Toolbarandroid:idid/toolbarandroid:layout_widthmatch_parentandroid:layout_height?attr/actionBarSizeandroid:backgroundcolor/colorHomeToolBarapp:contentInsetStart0.0dpapp:popupThemestyle/ThemeOverlay.AppCompat.ActionBarapp:themestyle/ToolbarStyleFrameLayoutandroid:idid/ll_title_menuandroid:layout_widthwrap_contentandroid:layout_heightmatch_parentandroid:background?attr/selectableItemBackgroundBorderlessandroid:paddingLeft15dpandroid:paddingRight15dpImageViewandroid:idid/iv_title_menuandroid:layout_width23dpandroid:layout_heightwrap_contentandroid:layout_gravitycenterandroid:srcdrawable/titlebar_menu //FrameLayoutHorizontalScrollViewandroid:layout_widthwrap_contentandroid:layout_heightmatch_parentandroid:layout_gravitycenterLinearLayoutandroid:layout_widthwrap_contentandroid:layout_heightmatch_parentandroid:background?attr/selectableItemBackgroundapp:themestyle/AppThemeImageViewandroid:idid/iv_title_oneandroid:layout_width55dpandroid:layout_heightwrap_contentandroid:layout_gravitycenterandroid:background?attr/selectableItemBackgroundBorderlessandroid:srcdrawable/titlebar_music /ImageViewandroid:idid/iv_title_twoandroid:layout_width55dpandroid:layout_heightmatch_parentandroid:background?attr/selectableItemBackgroundBorderlessandroid:srcdrawable/titlebar_disco /ImageViewandroid:idid/iv_title_threeandroid:layout_width55dpandroid:layout_heightmatch_parentandroid:background?attr/selectableItemBackgroundBorderlessandroid:srcdrawable/titlebar_friends //LinearLayout/HorizontalScrollView/androidx.appcompat.widget.Toolbarcom.example.jingbin.cloudreader.view.ViewPagerFixedandroid:idid/vp_contentandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid:descendantFocusabilityblocksDescendants //LinearLayout
/layout
控件 ViewPagerFixed 中代码如下 override fun onTouchEvent(ev: MotionEvent): Boolean {try {Log.d(ViewPagerFixed,onTouchEvent:)when (ev?.action) {MotionEvent.ACTION_DOWN - Log.d(ViewPagerFixed, View onTouchEvent ACTION_DOWN)MotionEvent.ACTION_MOVE - Log.d(ViewPagerFixed, View onTouchEvent ACTION_MOVE)MotionEvent.ACTION_UP - Log.d(ViewPagerFixed, View onTouchEvent ACTION_UP)}return super.onTouchEvent(ev)} catch (ex: IllegalArgumentException) {ex.printStackTrace()}return false}override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {try {Log.d(ViewPagerFixed,onInterceptTouchEvent:)when (ev?.action) {MotionEvent.ACTION_DOWN - Log.d(ViewPagerFixed, View onInterceptTouchEvent ACTION_DOWN)MotionEvent.ACTION_MOVE - Log.d(ViewPagerFixed, View onInterceptTouchEvent ACTION_MOVE)MotionEvent.ACTION_UP - Log.d(ViewPagerFixed, View onInterceptTouchEvent ACTION_UP)}return super.onInterceptTouchEvent(ev)} catch (ex: IllegalArgumentException) {ex.printStackTrace()}return false}override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {Log.d(ViewPagerFixed,dispatchTouchEvent:)when (ev?.action) {MotionEvent.ACTION_DOWN - Log.d(ViewPagerFixed, View dispatchTouchEvent ACTION_DOWN)MotionEvent.ACTION_MOVE - Log.d(ViewPagerFixed, View dispatchTouchEvent ACTION_MOVE)MotionEvent.ACTION_UP - Log.d(ViewPagerFixed, View dispatchTouchEvent ACTION_UP)}return super.dispatchTouchEvent(ev)}效果图如下 我们运行app,点击红色状态栏中 剧中的三个白色图标看到日志如下 首先我们知道一次点击会触发一次ACTION_DOWN、若干个ACTION_MOVE、一次ACTION_UP事件而一次事件的传递是由上往下传递的也就是依次通过Activity、ViewGroup、View。按下的瞬间ACTION_DOWN触发Activity的dispatchTouchEvent(事件分发)会先调用这个跟我们的第一行的日志不谋而合。 Activity中的dispatchTouchEvent会调用ViewGroup或者View的dispatchTouchEvent的方法而当ViewGroup或者View返回false时才会调用本身的onTouchEvent方法。第一行日就容易理解了是执行Activity的dispatchTouchEvent打印出来的后面执行了多个ACTION_MOVE,一次ACTION_UP事件最后Activity中这个事件被onClick2消费了。
这里有个知识点就是ViewGroup的dispatchTouchEvent方法会调用自身的onInterceptTouchEvent事件拦截方法这一点跟Activity中的有点不一样因为Activity中并没有事件拦截方法如果ViewGroup的onInterceptTouchEvent事件拦截方法返回true那么View中的dispatchTouchEvent方法不会被调用反而会执行ViewGroup的onTouchEvent方法那么事件传递结束。
如果返回的是false默认就是返回false那么View 中的dispatchTouchEvent方法会被调用因为View是最底层的控件事件无法继续再往下传递只能自身消费所以dispatchTouchEvent又会调用onTouchEvent方法。在我们这个例子中点击的是iv_title_two 这里我们会想onClick 和 onTouchEvent 到底啥关系呢下一篇我会具体的分析。
我们知道事件的传递是从上往下传递的那么当事件传递到最底层的View并且该事件没有被消费又该如何呢其实上面的日志已经告诉我们了当最底层的View并没有消费该事件时该事件会一层层往上抛接下来会执行ViewGroup的onTouchEvent方法如果返回true的话事件传递停止如果还是一样返回默认值false的话Activity的onTouchEvent方法会被调用到此ACTION_DOWN事件的传递结束这就是一次完整的事件传递过程。 细心同学又会问了为什么Activity的dispatchTouchEvent被执行了多次呢日志打印出来的
没错确实是执行了刚才我们说过了手指按下移动到抬起会执行一次ACTION_DOWN(按下)、若干次ACTION_MOVE(移动)和一次ACTION_UP(抬起)被执行了多次是因为执行了一次ACTION_MOVE一次是偶然的如果你手指多滑动会执行多次的和一次ACTION_UP事件也就是还有多次完整的事件传递过程但是我们发现后面这两次跟ACTION_DOWN不一样只调用两次Activity的dispatchTouchEvent、onTouchEvent方法这是为什么呢
因为Android本身的事件传递机制就是这样的我们把手指按下抬起所发生的事件传递称为一个事件序列看似3个或3个以上独立的事件组成其实不然它们还是有联系的因为当dispatchTouchEvent在进行事件分发的时候只有前一个action返回true才会触发下一个action什么意思呢刚才的例子Activity的dispatchTouchEvent的方法中viewGroup或者view.dispatchTouchEvent(ev)返回的是默认值false接下来ACTION_MOVE、ACTION_UP两个事件并不会触发ViewGroup的dispatchTouchEvent方法因为你前一个action【ACTION_UDOWN】返回的false反而是直接执行自身的onTouchEvent的方法。所以打印出来的日志就是这样的。这告诉我们如果一个事件序列的ACTION_DOWN事件你没消费掉那么该事件序列的ACTION_MOVE、ACTION_UP并不会在被执行了。 接下来我们滑动下面的viewpager,三个tab 玩安卓,广场,问答的那个
看下日志截图 viewpager 拦截了 ACTION_UDOWN 事件。 viewpager拦截了 ACTION_MOVE 事件 ACTION_UP事件被消费了
至此一个完整的事件流程结束了。