Android查缺补漏(View篇)–事件分发机制

事件分发机制是Android中甚重要的一个知识点,同时也是难关,相信到目前为止很多Android开发者对事件分发机制并没一个老系统的认,当然为包罗博主个人在内。可能以平常之开工作中我们连没发觉及事件分发机制起至的企图,其实它们是时刻存在的只是我们无晓得而已,就像有滑冲突、点击事件之间的撞等等大多是坐事件分发处理不当导致的。想起了博主大学时开了一个粗类,里面就涌出了滑动冲突之题目,虽然最后当网上一步步拘禁在人家的学科也糊里糊涂的化解了,但说到底不知其所以然,那么今天即使被我们并来深切的追一下事件分发机制吧。

关联旅游有关的网红,很容易使人回首“直播+旅游”,从之前“带在微博去旅行”那3亿口到场,1.3亿丁内容创造量,与统计到之门票增幅61%的结果虽看到其的潜力。然而,网红和直播行业曾经于境内以外都持续了6年之久,旅游业的下还才是中有些。在MCN旅游网红与旅游文化网红的渗入后,在2018年行业将时有发生双重甚之悲喜。

哎呀是事件分发机制?

说了半天的轩然大波分发机制那究竟是只底东西吧?我们绝不管其想象的那强深莫测,不要当思维上被自己假如上阻碍,其实十分爱懂,博主的知情是:简单的话,事件分发机制就是Android系统对事件传递过程规定之等同栽事件传递规则,事件还见面按照这规则进行分发传递。

于研事件分发机制之前,我们事先来确定一下分析的步子,化整为零,各个击破:

  • 折腾明白分析目标:MotionEvent。
  • 询问三独方式:dispatchTouchEvent(MotionEvent
    event)、onInterceptTouchEvent(Motion
    event)、onTouchEvent(MotionEvent event)。
  • MotionEvent事件之传递过程
  • 小结

MCN(Multi-Channel
Network)是进口商品,是发源国外成熟之网红经济运行,其实质是一个大抵频道网络的活形象,将PGC(专业内容生产)内容并起来,在本的强大支撑下,保障内容的不断输出,从而最终促成商业的安宁表现。

MotionEvent

事实上点击事件之散发过程就是是本着MotionEvent事件之分发过程,当用户点击操作以下后,MotionEvent事件随后发生并由此一定之平整传递至指定的View上,这个传递的经过以及规则就是是事件分发机制。

比方点击操作触发MotionEvent事件是一个风波流或说是一个波序列,其至高无上的波类有如下三种植:

  • MotionEvent.ACTION_DOWN:手指刚点下屏幕时点此类型。
  • MotionEvent.ACTION_MOVE:手指在屏幕及走时会见一再沾此类型。
  • MotionEvent.ACTION_UP:手指在屏幕上抬起时接触此类型。

如若特别注意的是,通常情况下一个MotionEvent事件序列包含一个 ACTION_DOWN
若干个 ACTION_MOVE 和 ACTION_UP
是一个完的风波序列。(点下来就抬起指头时,会只来 ACTION_DOWN 和
ACTION_UP,这也是一个总体的波序列)

“知识付费”的赶到,让不少“知识网红”异军突起。他们是新媒体知识传播变革中的弄潮儿,自身持有扎实功力与网知识,精通个人IP包装和运营,能够规范把握受众需求兴奋点,在起的互联网时代汇聚优质用户资源。

dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent

  • boolean dispatchTouchEvent (MotionEvent event):

分发事件,只要事件会传递至眼前View就必定会调用此道,其回到回值是一个布尔型表示是否消耗事件。返回true代表吃事件,事件流的存续有还会见跟着传递过来;返回false代表不吃事件,事件流的延续有就不再传递给之。

  • boolean onInterceptTouchEvent (MotionEvent ev):

这个道表示是否拦截MotionEvent事件,只有ViewGroup类型的控件才发出之方法。如果此办法返回true表示拦截事件,事件将传递让当下View的onTouchEvent()方法,而不再向其麾下的View传递。如果是方法返回false表示未阻碍事件,事件将传递让下级View的dispatchTouchEvent()。

  • boolean onTouchEvent (MotionEvent event):

以此方用来拍卖MotionEvent,返回值表示是否消耗事件。返回true表示耗事件,那么事件流的接轨有还见面传送过来;返回false表示不吃事件,事件将付出上级View的onTouchEvent()处理,如果上级View的onTouchEvent()仍然返回false,那么事件将再交给上级的顶头上司处理,以此类推,如果各View的onTouchEvent()都非吃事件,那么事件最终将交由Activity的onTouchEvent()处理。

上文说了这般多还是勿足够具体,先用流程图大体说明一个以上三个措施的关联,及调用流程,下文还见面做实际示例详细说明当事变分发传递着逐条艺术的调用规则。

三者关系约如下图:

那么,当就片种新兴内容形式以及旅游行业整合起来后,能够唤起什么的家业升级换代也?

MotionEvent事件传递过程

当手指点击屏幕来一个Touch事件后,事件仍Activity->Window->View的各个依次传递。

首先会传送给Activity的dispatchTouchEvent(),在这个办法中会将出于Window处理,接着事件会传送给根View,根View接收到事件后便会以事件分发机制去处理事件。

根View在此虽是一个ViewGroup,它当接受到事件后会调用dispatchTouchEvent(),在是方中会通过onInterceptTouchEvent()方法判断是否拦截事件,如果onInterceptTouchEvent()返回true就表示它如果阻止事件,事件将传递让当下ViewGroup的onTouchEvent()。如果onInterceptTouchEvent()放回false就表示她不遮事件,事件将污染于其下属的View,调用下级View的dispatchTouchEvent()。

根View的属下View可能又是一个ViewGroup,如果这样的话其传递流程与根View一样。无论根View的手下人View是不是ViewGroup,如果未挡事件,最终事件会传送及一个纯View的控件上。

当一个View(纯View控件)接收及事件后,也会见调用其dispatchTouchEvent(),然后在斯办法中会调用当前View的onTouchEvent(),如果onTouchEvent()返回true则意味着如果处理这个事件。如果回去false表示未吃事件,其上司View的onTouchEvent()将受调用,则事件流的接续有不再传递至手上View,在一个事变流中也非见面再次调用当前View的dispatchTouchEvent()。

紧接下去通过切实示例来查事件传递的流水线:

案例:华南某部旅游网在广州召开“七夕节预售特卖惠”会员活动,主打七夕节特惠旅游产品线路,派出情感网红Kristen吴,和恋爱心理网willam先生前失去呢那“幸福游轮”站台,并且经过直播把立即会活动流传到了网上,引起70万人关注。

示例一,默认情况下的事件传递流程

缔造3独八九不离十,一个Activity、一个后续自LinearLayout的View,一个连续自Button的View,并还写他们之dispatchTouchEvent()、onIntercepteTouchEvent()、onTouchEvent(),三只八九不离十及布局文件的代码如下:

  • EventDispatchActivity

/**
 * 事件分发机制测试Activity
 * Created by liuwei on 18/1/5.
 */
public class EventDispatchActivity extends AppCompatActivity {

    private final static String TAG = "Activity";//EventDispatchActivity.class.getSimpleName();

    private EventDispatchTestView edtv_test;
    private EventDispatchLinearLayout edll_test;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_event_dispatch);
        edtv_test = ViewUtils.find(this, R.id.edtv_test);
        edll_test = ViewUtils.find(this, R.id.edll_test);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {

        // 被调用时输出log,event.getAction表示事件的类型,0:ACTION_DOWN,1:ACTION_UP,2:ACTION_MOVE。

        Log.i(TAG, "dispatchTouchEvent: " + event.getAction() + " | 分发事件");
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "onTouchEvent: " + event.getAction() + " | 是否消耗事件:" + true);
        return super.onTouchEvent(event);
    }
}
  • EventDispatchLinearLayout

/**
 * 事件分发机制测试 ViewGroup
 * Created by liuwei on 18/1/5.
 */
public class EventDispatchLinearLayout extends LinearLayout {

    private final static String TAG = "——Layout";//EventDispatchLinearLayout.class.getSimpleName();


    public EventDispatchLinearLayout(Context context) {
        super(context);
    }

    public EventDispatchLinearLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.i(TAG, "dispatchTouchEvent: " + event.getAction() + " | 分发事件");
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        Log.i(TAG, "onInterceptTouchEvent: " + event.getAction() + " | 是否拦截:" + false);
        return super.onInterceptTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "onTouchEvent: " + event.getAction() + " | 是否消耗事件:" + false);
        return super.onTouchEvent(event);
    }
}
  • EventDispatchTestView

/**
 * 事件分发机制测试 View
 * Created by liuwei on 18/1/5.
 */
public class EventDispatchTestView extends Button {

    private final static String TAG = "————View";//EventDistpatchTestView.class.getSimpleName();

    public EventDispatchTestView(Context context) {
        super(context);
    }

    public EventDispatchTestView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.i(TAG, "dispatchTouchEvent: " + event.getAction() + " | 分发事件");
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "onTouchEvent: " + event.getAction() + " | 是否消耗事件:" + true);
        return super.onTouchEvent(event);
    }
}
  • 布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="cn.codingblock.view.event_dispatch.EventDispatchActivity">

    <cn.codingblock.view.event_dispatch.EventDispatchLinearLayout
        android:id="@+id/edll_test"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#cccccc">

        <cn.codingblock.view.event_dispatch.EventDispatchTestView
            android:id="@+id/edtv_test"
            android:layout_width="300dp"
            android:layout_height="300dp"
            android:layout_margin="10dp"
            android:background="#000000"/>

    </cn.codingblock.view.event_dispatch.EventDispatchLinearLayout>

</LinearLayout>

运作代码,点击EventDispatchTestView(黑色区域),log输出如下(log中之数字代表事件之项目,0:ACTION_DOWN,1:ACTION_UP,2:ACTION_MOVE):

01-05 16:58:05.574 23295-23295/cn.codingblock.view I/Activity: dispatchTouchEvent: 0 | 分发事件
01-05 16:58:05.574 23295-23295/cn.codingblock.view I/——Layout: dispatchTouchEvent: 0 | 分发事件
01-05 16:58:05.574 23295-23295/cn.codingblock.view I/——Layout: onInterceptTouchEvent: 0 | 是否拦截:false
01-05 16:58:05.574 23295-23295/cn.codingblock.view I/————View: dispatchTouchEvent: 0 | 分发事件
01-05 16:58:05.574 23295-23295/cn.codingblock.view I/————View: onTouchEvent: 0 | 是否消耗事件:true

01-05 16:58:05.611 23295-23295/cn.codingblock.view I/Activity: dispatchTouchEvent: 2 | 分发事件
01-05 16:58:05.611 23295-23295/cn.codingblock.view I/——Layout: dispatchTouchEvent: 2 | 分发事件
01-05 16:58:05.611 23295-23295/cn.codingblock.view I/——Layout: onInterceptTouchEvent: 2 | 是否拦截:false
01-05 16:58:05.611 23295-23295/cn.codingblock.view I/————View: dispatchTouchEvent: 2 | 分发事件
01-05 16:58:05.611 23295-23295/cn.codingblock.view I/————View: onTouchEvent: 2 | 是否消耗事件:true

01-05 16:58:05.619 23295-23295/cn.codingblock.view I/Activity: dispatchTouchEvent: 1 | 分发事件
01-05 16:58:05.619 23295-23295/cn.codingblock.view I/——Layout: dispatchTouchEvent: 1 | 分发事件
01-05 16:58:05.619 23295-23295/cn.codingblock.view I/——Layout: onInterceptTouchEvent: 1 | 是否拦截:false
01-05 16:58:05.620 23295-23295/cn.codingblock.view I/————View: dispatchTouchEvent: 1 | 分发事件
01-05 16:58:05.620 23295-23295/cn.codingblock.view I/————View: onTouchEvent: 1 | 是否消耗事件:true

由log可以观看ViewGroup的onInterceptTouchEvent方法默认是休阻止事件之,View的onTouchEvent方法默认消耗事件。事件流的ACTION_DOWN类型Motion
Event率先到达View的onTouchEvent方法中,此时onTouchEvent方法返回true,表示只要处理事件,所以事件流的连续有还通过log中的流水线到达了View的onTouchEvent方法吃。

一头,Kristen吴是华南某某旅游网委派的MCN网红孵化机构培育的情感类网红,半年工夫成功了由招生她,培养她,到连片各种营销活动,此刻它们的企图就运用好的人气以及颜值,在全国限制外流传这会活动。而相恋心理网的willam先生,也于这家旅游网站的MCN网红孵化机构内,不过当下号该貌不扬的男网红,却不失为因才华在用。旅游网站一律摆设游轮票是299初,打来底凡广告“买299送299”,送出的299难为这号男性网红的相恋心理课程。这简单各类网红的合并威力,让本“幸福游轮”的老三龙外贩卖起12056不必要摆放票,比预测大出182%。

示例二、在示例一的功底及,让View的onTouchEvent不吃事件不时之传递流程

连片下吃地方的EventDispatchTestView的onTouchEvent返回false:

@Override
public boolean onTouchEvent(MotionEvent event) {
    Log.i(TAG, "onTouchEvent: " + event.getAction() + " | 是否消耗事件:" + false);
    return false;//super.onTouchEvent(event);
}

测试log如下:

01-05 18:18:52.545 10771-10771/cn.codingblock.view I/Activity: dispatchTouchEvent: 0 | 分发事件
01-05 18:18:52.545 10771-10771/cn.codingblock.view I/——Layout: dispatchTouchEvent: 0 | 分发事件
01-05 18:18:52.546 10771-10771/cn.codingblock.view I/——Layout: onInterceptTouchEvent: 0 | 是否拦截:false
01-05 18:18:52.546 10771-10771/cn.codingblock.view I/————View: dispatchTouchEvent: 0 | 分发事件
01-05 18:18:52.546 10771-10771/cn.codingblock.view I/————View: onTouchEvent: 0 | 是否消耗事件:false
01-05 18:18:52.546 10771-10771/cn.codingblock.view I/——Layout: onTouchEvent: 0 | 是否消耗事件:false
01-05 18:18:52.547 10771-10771/cn.codingblock.view I/Activity: onTouchEvent: 0 | 是否消耗事件:true

01-05 18:18:52.629 10771-10771/cn.codingblock.view I/Activity: dispatchTouchEvent: 2 | 分发事件
01-05 18:18:52.629 10771-10771/cn.codingblock.view I/Activity: onTouchEvent: 2 | 是否消耗事件:true

01-05 18:18:52.630 10771-10771/cn.codingblock.view I/Activity: dispatchTouchEvent: 1 | 分发事件
01-05 18:18:52.630 10771-10771/cn.codingblock.view I/Activity: onTouchEvent: 1 | 是否消耗事件:true

当View的onTouchEvent不吃事件频仍,事件会交到ViewGroup的onTouchEvent方法处理,而打log可以看来ViewGroup的onTouchEvent默认为未吃事件,所以事件由提交Activity的onTouchEvent方法处理,最终事件流的累有不再传递让ViewGroup和View,而是直接传送给Activity的onTouchEvent处理。

此MCN旅游网红与旅游文化网红的矩阵营销案例正式直播+旅游+网购的超人写照,那么除了她以外,还有以下三种植。

示例三、在示例二的基本功及受ViewGroup消耗事件

修改EventDispatchLinearLayout的onTouchEvent(),让该回到true。

@Override
public boolean onTouchEvent(MotionEvent event) {
    Log.i(TAG, "onTouchEvent: " + event.getAction() + " | 是否消耗事件:" + true);
    return true;//super.onTouchEvent(event);
}

测试log如下:

01-05 18:34:53.409 21169-21169/cn.codingblock.view I/Activity: dispatchTouchEvent: 0 | 分发事件
01-05 18:34:53.409 21169-21169/cn.codingblock.view I/——Layout: dispatchTouchEvent: 0 | 分发事件
01-05 18:34:53.409 21169-21169/cn.codingblock.view I/——Layout: onInterceptTouchEvent: 0 | 是否拦截:false
01-05 18:34:53.409 21169-21169/cn.codingblock.view I/————View: dispatchTouchEvent: 0 | 分发事件
01-05 18:34:53.410 21169-21169/cn.codingblock.view I/————View: onTouchEvent: 0 | 是否消耗事件:false
01-05 18:34:53.410 21169-21169/cn.codingblock.view I/——Layout: onTouchEvent: 0 | 是否消耗事件:true

01-05 18:34:53.420 21169-21169/cn.codingblock.view I/Activity: dispatchTouchEvent: 2 | 分发事件
01-05 18:34:53.420 21169-21169/cn.codingblock.view I/——Layout: dispatchTouchEvent: 2 | 分发事件
01-05 18:34:53.420 21169-21169/cn.codingblock.view I/——Layout: onTouchEvent: 2 | 是否消耗事件:true

01-05 18:34:53.470 21169-21169/cn.codingblock.view I/Activity: dispatchTouchEvent: 1 | 分发事件
01-05 18:34:53.470 21169-21169/cn.codingblock.view I/——Layout: dispatchTouchEvent: 1 | 分发事件
01-05 18:34:53.470 21169-21169/cn.codingblock.view I/——Layout: onTouchEvent: 1 | 是否消耗事件:true

是种植情景下,事件流的ACTION_DOWN先到达View的onTouchEvent,发现它们不吃事件,继而返回上级的ViewGroup的onTouchEvent中,发现它使消耗事件,事件流的连续有即使不以传递让View,也未以调用ViewGroup的onInterceptTouchEvent方法,因为早已明白View不处理事件,所以并未必要再经过onInterceptTouchEvent方法来判断了。

一、MCN导向:直播+旅游+网红

示例四、如果当ViewGroup的onInterceptTouchEvent中归了true拦截了风波,整个事件将不再传递让View而是直接到由ViewGroup的onTouchEvent处理。

修改EventDispatchLinearLayout的onInterceptTouchEvent(),让其回来true。

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    Log.i(TAG, "onInterceptTouchEvent: " + event.getAction() + " | 是否拦截:" + true);
    return true;//super.onInterceptTouchEvent(event);
}

测试log如下:

01-05 19:03:21.788 9733-9733/cn.codingblock.view I/Activity: dispatchTouchEvent: 0 | 分发事件
01-05 19:03:21.789 9733-9733/cn.codingblock.view I/——Layout: dispatchTouchEvent: 0 | 分发事件
01-05 19:03:21.789 9733-9733/cn.codingblock.view I/——Layout: onInterceptTouchEvent: 0 | 是否拦截:true
01-05 19:03:21.789 9733-9733/cn.codingblock.view I/——Layout: onTouchEvent: 0 | 是否消耗事件:true
01-05 19:03:21.819 9733-9733/cn.codingblock.view I/Activity: dispatchTouchEvent: 2 | 分发事件
01-05 19:03:21.819 9733-9733/cn.codingblock.view I/——Layout: dispatchTouchEvent: 2 | 分发事件
01-05 19:03:21.819 9733-9733/cn.codingblock.view I/——Layout: onTouchEvent: 2 | 是否消耗事件:true
01-05 19:03:21.877 9733-9733/cn.codingblock.view I/Activity: dispatchTouchEvent: 1 | 分发事件
01-05 19:03:21.877 9733-9733/cn.codingblock.view I/——Layout: dispatchTouchEvent: 1 | 分发事件
01-05 19:03:21.877 9733-9733/cn.codingblock.view I/——Layout: onTouchEvent: 1 | 是否消耗事件:true

各大在线旅游合作社(OTA)都见到了网红直播这种新的营销方法后,纷纷决定试水,如有旅游APP与有直播平台联手做出同样层层“旅游直播”节目。当时,40不必要叫作网红主播赶赴澳门氹仔、武汉九黄鹤楼、四川都江堰、上海迪士尼以及韩国济州岛、马尔代夫等八杀热点景区风光直播。

示例五、给View绑定OnTouchListener和OnClickListener监听器。

当EventDispatchActivity的onCreate()方法中长如下代码,并以EventDispatchLinearLayout和EventDispatchTestView的各艺术的归值都还原成示例一蒙受的状态。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_event_dispatch);
    edtv_test = ViewUtils.find(this, R.id.edtv_test);
    edll_test = ViewUtils.find(this, R.id.edll_test);

    edtv_test.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // 为了log显示的层次更加清晰,这里的TAG使用View的TAG
            Log.i("————View", "onTouch: 返回 " + false);
            return false;
        }
    });

    edtv_test.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // 为了log显示的层次更加清晰,这里的TAG使用View的TAG
            Log.i("————View", "onClick: ");
        }
    });
}

测试log如下:

01-06 19:35:07.563 6737-6737/cn.codingblock.view I/Activity: dispatchTouchEvent: 0 | 分发事件
01-06 19:35:07.563 6737-6737/cn.codingblock.view I/——Layout: dispatchTouchEvent: 0 | 分发事件
01-06 19:35:07.563 6737-6737/cn.codingblock.view I/——Layout: onInterceptTouchEvent: 0 | 是否拦截:false
01-06 19:35:07.563 6737-6737/cn.codingblock.view I/————View: dispatchTouchEvent: 0 | 分发事件
01-06 19:35:07.563 6737-6737/cn.codingblock.view I/————View: onTouch: 返回 false
01-06 19:35:07.563 6737-6737/cn.codingblock.view I/————View: onTouchEvent: 0 | 是否消耗事件:true

01-06 19:35:07.573 6737-6737/cn.codingblock.view I/Activity: dispatchTouchEvent: 2 | 分发事件
01-06 19:35:07.573 6737-6737/cn.codingblock.view I/——Layout: dispatchTouchEvent: 2 | 分发事件
01-06 19:35:07.573 6737-6737/cn.codingblock.view I/——Layout: onInterceptTouchEvent: 2 | 是否拦截:false
01-06 19:35:07.573 6737-6737/cn.codingblock.view I/————View: dispatchTouchEvent: 2 | 分发事件
01-06 19:35:07.574 6737-6737/cn.codingblock.view I/————View: onTouch: 返回 false
01-06 19:35:07.574 6737-6737/cn.codingblock.view I/————View: onTouchEvent: 2 | 是否消耗事件:true

01-06 19:35:07.673 6737-6737/cn.codingblock.view I/Activity: dispatchTouchEvent: 1 | 分发事件
01-06 19:35:07.674 6737-6737/cn.codingblock.view I/——Layout: dispatchTouchEvent: 1 | 分发事件
01-06 19:35:07.674 6737-6737/cn.codingblock.view I/——Layout: onInterceptTouchEvent: 1 | 是否拦截:false
01-06 19:35:07.674 6737-6737/cn.codingblock.view I/————View: dispatchTouchEvent: 1 | 分发事件
01-06 19:35:07.674 6737-6737/cn.codingblock.view I/————View: onTouch: 返回 false
01-06 19:35:07.674 6737-6737/cn.codingblock.view I/————View: onTouchEvent: 1 | 是否消耗事件:true
01-06 19:35:07.704 6737-6737/cn.codingblock.view I/————View: onClick: 

下一场再度端修改代码,让onTouch()方法吃事件,也不怕是归true,再观log:

edtv_test.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // 为了log显示的层次更加清晰,这里的TAG使用View的TAG
        Log.i("————View", "onTouch: 返回 " + false);
        return false;
    }
});

log如下:

01-07 11:03:55.411 2757-2757/cn.codingblock.view I/Activity: dispatchTouchEvent: 0 | 分发事件
01-07 11:03:55.412 2757-2757/cn.codingblock.view I/——Layout: dispatchTouchEvent: 0 | 分发事件
01-07 11:03:55.412 2757-2757/cn.codingblock.view I/——Layout: onInterceptTouchEvent: 0 | 是否拦截:false
01-07 11:03:55.412 2757-2757/cn.codingblock.view I/————View: dispatchTouchEvent: 0 | 分发事件
01-07 11:03:55.412 2757-2757/cn.codingblock.view I/————View: onTouch: 返回 true

01-07 11:03:55.542 2757-2757/cn.codingblock.view I/Activity: dispatchTouchEvent: 2 | 分发事件
01-07 11:03:55.542 2757-2757/cn.codingblock.view I/——Layout: dispatchTouchEvent: 2 | 分发事件
01-07 11:03:55.542 2757-2757/cn.codingblock.view I/——Layout: onInterceptTouchEvent: 2 | 是否拦截:false
01-07 11:03:55.542 2757-2757/cn.codingblock.view I/————View: dispatchTouchEvent: 2 | 分发事件
01-07 11:03:55.542 2757-2757/cn.codingblock.view I/————View: onTouch: 返回 true

01-07 11:03:55.560 2757-2757/cn.codingblock.view I/Activity: dispatchTouchEvent: 1 | 分发事件
01-07 11:03:55.560 2757-2757/cn.codingblock.view I/——Layout: dispatchTouchEvent: 1 | 分发事件
01-07 11:03:55.560 2757-2757/cn.codingblock.view I/——Layout: onInterceptTouchEvent: 1 | 是否拦截:false
01-07 11:03:55.560 2757-2757/cn.codingblock.view I/————View: dispatchTouchEvent: 1 | 分发事件
01-07 11:03:55.560 2757-2757/cn.codingblock.view I/————View: onTouch: 返回 true

于log中我们可看出:

  • 呢View绑定的OnTouchListener中之onTouch()方法是先行让View的onTouchEvent()方法执行的。如果当onTouch()消耗了事件(返回true),那么事件将不在传递给onTouchEvent()方法,最终也未见面调用onClick()方法。
  • 啊View绑定的OnClickListener中之onClick()方法优先级最低,是于普事件流了后才见面于调用,也尽管是急需经过手指的本下–抬起是历程才见面触发onClick()方法。

直播活动前后持续了15上,直播21场次,每场2时以上,最多同时在线人数也125万总人口,营销力堪称该网站年度走最佳,而预算较回落14%。

小结

为更好之接头,可以将事件流看成是同样队人,把ACTION_DOWN类型看做探路人,探路人按规定之线路先活动相同全套,直到走至View的onTouchEvent这里,如果onTouchEvent返回true,可了解成者路通,后续部队可以还原。如果回去false,可以领略成这个路不通,然后探路人再届Layout(ViewGroup)的onTouchEvent中问路通不接入,如果属之说话后续部队虽毫无再错过View那里了,直接到ViewGroup这来就是得了。而要ViewGroup这里路呢死,那么探路人就只好去Activity的onTouchEvent那里了,后续部队也一直去Activity的onTouchEvent这里虽好了。


最后想说的是,本系列文章也罢博主对Android知识进行更梳理,查缺补漏之上学过程,一方面是针对性协调忘记的事物加以复习重新掌握,另一方面相信于重新学习的过程中自然会发巨大的初获得,如果你啊产生和自己同一的想法,不妨关注我并学习,互相探讨,共同进步!

参考文献:

  • 《Android开发方探索》

仲、知识网红导向:直播+旅游+达人

南京某旅游APP旗下的文化网红机构,招募旅游达人并开展培育,让他们更熟识景点的还要控制该景点的知,与此同时最根本的凡掌握住相关的出游技能。如知识网红冯先生是各类滑雪爱好者,他去大兴安岭滑雪节活动之直播,便是事先相当直播卖票,游客买票就送滑雪付费音频课程,以及被旅游者观览冯先生的滑雪直播。这种感受于游人尖叫连连,流连忘返,让屏幕面前的网友们跃跃欲试的想去大兴安岭。

其三、结合导向:直播+旅游景点

上海有旅游网站旗下之MCN网红机构及学识网红机构,派出82称为网红前往第二顶中国张家界民俗文化活动月开幕式,一时间迎来迎来破千万底观看量,成为张家界之“现象级”的营销动作。在直播过程中,将张家界绝版山水和民俗文化通过直播互相形式显得,以及文化付费卖于爱这里的观光客。在当场,效果还理想之是,竟然发出了游客参与喜气洋洋的位移,以及传播到了天涯,受国际友人好评这无异于创新的选。