当前位置: 移动技术网 > 移动技术>移动开发>Android > Android 事件分发机制详解与实战剖析 | 开发者说·DTalk

Android 事件分发机制详解与实战剖析 | 开发者说·DTalk

2020年07月08日  | 移动技术网移动技术  | 我要评论

本文原作者: 门心叼龙,原文发布于: https://blog.csdn.net/geduo_83/article/details/86560896

本文为自己多年来在 Android 实战开发过程中总结归纳的一些常见问题,现在分享出来希望对初学者有所帮助。

事件分发是 Android 开发过程中的重点又是难点, 一张事件分发流程图,让你彻底搞明白。网上有很多文章写事件分发,感觉都没有讲明白,恭喜你,今天你看到好文章了,你彻底搞清楚…

目录

1.在 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 按照事件进行划分

640?wx_fmt=other

3.2 按照 View 进行划分

640?wx_fmt=other

结论: 无论是 View 还是 ViewGroup,不管他是 DispatchTouchEvent 还是 onTouchEvent 方法,方法返回 true、返回 false 的处理逻辑都是一样的,只是调用父类的同名方法的时候处理的逻辑有所不同,View 偏重消费、ViewGourp 偏重分发。

4.简述 View 的事件传递机制?

触摸事件的传递流程是从 dispatchTouchEvent 开始的,如果不进行人工干预,则事件将会依照 View 树的嵌套层次从外层向内层传递,到达最内层的 View 时,就由它的 onTouchVent 方法处理。

如果事件在传递过程中,进行了人工干预,事件分发函数返回 true 表示自行消费,返回父类的同名方法则该事件传递给自身的 onTouchEvent 进行处理,返回 false 表示该事件会回传给父 view 的 onTouchEvent 方法进行处理,此时后面的事件都接受不到了,最后由哪个 View 处理,以后的所有事件都交由它来处理。

如果事件在传递过程中,进行了人工干预,事件处理函数,返回 true 和调用同名方法表示该事件被消费,返回 false 则表示该事件回传给父类的同名方法进行处理。

事件触发是先触发 onTouch,再触发 onClick,如果 onTouch 方法返回 true,表示消费掉该事件,不在继续进行事件传递,onClick 也不会被调用,如果 onTouch 方法返回 false,则继续会事件传递,onClick 会被调用。


5.简述 ViewGroup 的事件传递机制?

触摸事件的传递顺序是由 Activity 到 ViewGroup,再由 ViewGroup 递归传递给他的子 View,ViewGroup 通过 onInterceptTouchEvent 方法对事件进行拦截,如果该方法返回 true,则事件不会继续往下传递给子 View,如果返回 false 或者是调用 super.onInterceptTouchEvent,则事件会继续会传递给子 View。

如果事件在传递过程中,进行了人工干预,事件分发函数返回 true 表示事件被自行消费,返回 false,则回传给父 View 的 onTouchEvent 进行处理,此时后面的事件都接受不到了,调用同名方法则继续传递。

如果事件在传递过程中,进行了人工干预,事件处理函数,返回 true 则表示该事件被消费,返回 false 和调用同名方法则表示该事件回传给父类的同名方法进行处理。

6.事件分发流程图

一张 Android 事件分发流程,让你彻底搞明白 Android 的事件分发机制。

640?wx_fmt=other


7.实战案例

实现效果如下,底部的行程详情可以往上拖动覆盖在地图之上,也可以往下拖动停止在屏幕的正中位置,地图相关操作: 放大、缩小、移动都能正常的响应,怎么实现?下面就是具体的源码实现过程。

640?wx_fmt=gif

7.1 事件分发处理

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

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

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 布局文件

<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>


"开发者说·DTalk" 面向中国开发者们征集 Google 640?wx_fmt=png移动应用 (apps & games) 相关的产品/技术内容。欢迎大家前来分享您对移动应用的行业洞察或见解、移动开发过程中的心得或新发现、以及应用出海的实战经验总结和相关产品的使用反馈等。我们由衷地希望可以给这些出众的中国开发者们提供更好展现自己、充分发挥自己特长的平台。我们将通过大家的技术内容着重选出优秀案例进行谷歌开发技术专家 (GDE) 的推荐。

640?wx_fmt=gif 点击屏末 |  | 了解更多 "开发者说·DTalk" 活动详情与参与方式

长按右侧二维码

报名参与

640?wx_fmt=png


640?wx_fmt=gif

本文地址:https://blog.csdn.net/jILRvRTrc/article/details/100135302

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网