葡京网上娱乐场Android查缺补漏(View篇)–事件分发机制

事件分发机制是Android中尤其主要的一个知识点,同时也是难关,相信到近日甘休很多Android开发者对事件分发机制并不曾一个那一个系统的认识,当然也包涵博主个人在内。可能在平常的开销工作中大家并不曾发现到事件分发机制起到的功力,其实它是时刻存在的只是大家不明了而已,似乎有的滑动争持、点击事件时期的争执等等大多是因为事件分发处理不当导致的。想起了博主大学时做过一个小品种,里面就应运而生了滑动龃龉的题材,固然最终在网上一步步望着别人的教程也糊里糊涂的化解了,但毕竟不知其所以然,那么今日就让大家共同来深切的探赜索隐一下事变分发机制吗。

文案是一个成品中不得缺失的一有的,好的文案是一举两得产品不得缺失的。文案承载的是成品所要传达给用户的消息,最根本的目标是抒发清楚产品所要传达给用户的音讯。而选取什么艺术表明,文字究竟怎么写,那几个都是达到目标的手段。

什么是事件分发机制?

说了半天的事件分发机制那究竟是个啥东西吧?我们不用把它想象的那么高深莫测,不要在思想上给协调设上阻碍,其实很简单掌握,博主的通晓是:不难的话,事件分发机制就是Android系统对事件传递进程规定的一种事件传递规则,事件都会根据这些规则进行分发传递。

在探究事件分发机制此前,大家先来确定一下解析的手续,化整为零,种种击破:

  • 弄领悟分析目的:Motion伊夫nt。
  • 刺探五个章程:dispatchTouch伊夫nt(Motion伊夫nt
    event)、onInterceptTouch伊芙nt(Motion
    event)、onTouch伊芙nt(Motion伊芙nt event)。
  • Motion伊夫nt事件的传递进程
  • 小结

废话不多说,写一下谈得来多年来关于写文案的片段想想。

MotionEvent

事实上点击事件的散发过程就是对Motion伊夫nt事件的分发进度,当用户点击操作按下后,Motion伊夫nt事件随后暴发并透过一定的平整传递到指定的View上,这么些传递的历程和规则就是事件分发机制。

而点击操作触发Motion伊芙nt事件是一个事变流或者说是一个风浪体系,其卓绝的事件类型有如下二种:

  • MotionEvent.ACTION_DOWN:手指刚点下屏幕时接触此类型。
  • MotionEvent.ACTION_MOVE:手指在显示器上移动时会多次触及此类型。
  • MotionEvent.ACTION_UP:手指在显示器上抬起时接触此类型。

要更加注意的是,平日意况下一个Motion伊夫nt事件种类蕴涵一个 ACTION_DOWN
若干个 ACTION_MOVE 和 ACTION_UP
是一个一体化的轩然大波序列。(点下来立马抬起指头时,会只有 ACTION_DOWN 和
ACTION_UP,那也是一个全体的事件种类)

1

dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent

  • boolean dispatchTouchEvent (MotionEvent event):

分发事件,只要事件能传递到当前View就自然会调用此情势,其再次来到值是一个布尔类型表示是或不是消耗事件。再次来到true代表消耗事件,事件流的存续部分还会随之传递过来;重返false代表不消耗事件,事件流的一而再部分就不再传递于此。

  • boolean onInterceptTouchEvent (MotionEvent ev):

此方法表示是还是不是拦截Motion伊芙nt事件,只有ViewGroup类型的控件才有此方法。即使此措施再次回到true表示拦截事件,事件将传递给当下View的onTouch伊夫nt()方法,而不再向其属下的View传递。假使此方法重临false表示不阻碍事件,事件将传递给下级View的dispatchTouch伊夫nt()。

  • boolean onTouchEvent (MotionEvent event):

此办法用来处理Motion伊芙nt,重临值表示是或不是消耗事件。重返true表示消耗事件,那么事件流的接续部分还会传递过来;重临false表示不消耗事件,事件将提交上级View的onTouch伊夫nt()处理,假如上边View的onTouch伊芙nt()依然重临false,那么事件将再交给上级的上级处理,以此类推,假设各级View的onTouch伊夫nt()都不消耗事件,那么事件最终将交由Activity的onTouch伊芙nt()处理。

上文说了这么多仍旧不够具体,先用流程图大体说可瑞康(Karicare)个以上多少个法子的涉嫌,及调用流程,下文还会组成具体示例详细表明在事变分发传递中种种艺术的调用规则。

三者关系大体如下图:

葡京网上娱乐场 1

中华怀有数千年的知识,人的学问修养很重点的一个反映就是对文字的利用。很多少人写文字,更加是短文,总想着有诗意,貌似只有那样才能反映出自己的内涵。诗意性的文字即便简练而有内涵,但有一小胜笔就是不利被通晓。而网络的用户又越发斯巴鲁化,即便仅仅追求文字诗意的话,最终导致的结果就是用户不明白,目标达不到,那样的文案也只能是退步的。

MotionEvent事件传递进度

当手指点击显示屏发出一个Touch事件后,事件依据Activity->Window->View的依次依次传递。

率先会传送给Activity的dispatchTouch伊夫nt(),在此措施内部会将由Window处理,接着事件会传递给根View,根View接收到事件后就会根据事件分发机制去处理事件。

根View在此地就是一个ViewGroup,它在收受到事件后会调用dispatchTouch伊夫nt(),在此措施内部会因此onInterceptTouch伊芙nt()方法判断是或不是拦截事件,固然onInterceptTouch伊芙nt()重返true就象征它要堵住事件,事件将传递给当下ViewGroup的onTouch伊芙nt()。即使onInterceptTouch伊夫nt()放回false就意味着它不阻碍事件,事件将传给其下属的View,调用下级View的dispatchTouch伊夫nt()。

根View的手下人View可能又是一个ViewGroup,借使这样的话其传递流程同根View一样。无论根View的部下View是还是不是ViewGroup,假设不阻拦事件,最后事件会传送到一个纯View的控件上。

当一个View(纯View控件)接收到事件后,也会调用其dispatchTouch伊芙nt(),然后在此方法内部会调用当前View的onTouch伊夫nt(),如若onTouch伊夫nt()再次来到true则象征要拍卖此事件。假设回到false表示不消耗事件,其顶头上司View的onTouch伊芙nt()将被调用,则事件流的后续部分不再传递到眼前View,在一个风浪流中也不会再调用当前View的dispatchTouch伊芙nt()。

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

话不相对,也并不是说文案就必定不可能有所诗意性,还跟应用场景和面向的用户有关。倘诺您的使用场景需求创设一种诗意的空气,那使用诗意的文字依旧有需求的。若是你的用户是一群文化学者的话,那诗意性的文字也不会难精通,用户反倒会欣赏。

示例一,默许意况下的事件传递流程

创制3个类,一个Activity、一个继承自LinearLayout的View,一个持续自Button的View,比量齐观写他们的dispatchTouch伊夫nt()、onIntercepteTouch伊芙nt()、onTouch伊芙nt(),多个类及布局文件的代码如下:

  • 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的onInterceptTouch伊夫nt方法默许是不阻止事件的,View的onTouch伊芙nt方法默许消耗事件。事件流的ACTION_DOWN类型Motion
伊夫nt率先到达View的onTouch伊芙nt方法中,此时onTouch伊夫nt方法再次来到true,表示要处监护人件,所以事件流的一而再部分如故通过log中的流程到达了View的onTouch伊芙nt方法中。

文案起到烘托气氛,匹配产品气质的功效。

示例二、在示例一的基本功上,让View的onTouch伊夫nt不消耗事件时的传递流程

接下去让地点的伊夫ntDispatchTestView的onTouch伊夫nt再次来到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的onTouch伊芙nt不消耗事件时,事件会提交ViewGroup的onTouch伊芙nt方法处理,而从log可以看出ViewGroup的onTouch伊芙nt默许也不消耗事件,所以事件由提交Activity的onTouch伊夫nt方法处理,最终事件流的持续部分不再传递给ViewGroup和View,而是直接传送给Activity的onTouch伊芙nt处理。

多多文案背后都隐藏着成品的小买卖目的,可是在文案的抒发上,大家又不想把自己的真人真事目标传达给用户。一来是没须要,二来也为了幸免引起用户的反感,原因或许还有不少那里就不多说了。即便产品我有买卖目的,可是文案上大家还索要反映团结是从用户的益处出发,毕竟要加进用户的引力。

示例三、在示例二的基本功上让ViewGroup消耗事件

修改EventDispatchLinearLayout的onTouch伊夫nt(),让其归来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的onTouch伊夫nt,发现它不消耗事件,继而再次回到上级的ViewGroup的onTouch伊夫nt中,发现它要用度事件,事件流的继承部分就不在传递给View,也不在调用ViewGroup的onInterceptTouch伊夫nt方法,因为已经理解View不处总管件,所以没要求再经过onInterceptTouch伊芙nt方法来判断了。

前阵子大家的制品对接了第三方登录,平时都会让用户在第四回利用第三方登录时成立一个祥和平台的新账号。可为了更大程度上的充实用户的便捷性,大家并没有这样做,省去了用户登录时成立新账号的步调,只是到了需求的时候才让用户去创立一个新账号。即便成立新账号的理由是因为用户使用了第三方账号,所以她们并从未我们平台的账号。然则我们在创作文案时,也并不曾这么平昔的写出来,而是告诉用户大家是为了更好的为他服务。

示例四、倘诺在ViewGroup的onInterceptTouch伊夫nt中回到了true拦截了事件,整个事件将不再传递给View而是直接交由ViewGroup的onTouch伊夫nt处理。

修改伊夫ntDispatchLinearLayout的onInterceptTouch伊芙nt(),让其再次来到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

难题出现了,很多个人不晓得所谓的更好的服务是何许。文案让她发出了想不开,也无法很好的达标大家的目标。之所以出现这么的标题,是因为文案表明的音信不够醒目,用户的心底有了狐疑,也认证某些有些时候纵然你的语言婉转了看起来淡雅了,不过却不如间接的语言传递的更简约可看重。

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

在伊夫ntDispatchActivity的onCreate()方法里面添加如下代码,并将伊夫ntDispatchLinearLayout和伊夫ntDispatchTestView的各艺术的再次回到值都还原成示例一中的状态。

@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的onTouch伊芙nt()方法执行的。即使在onTouch()消耗了风浪(重临true),那么事件将不在传递给onTouch伊芙nt()方法,最终也不会调用onClick()方法。
  • 为View绑定的OnClickListener中的onClick()方法优先级最低,是在总体事件流截止后才会被调用,也就是索要通过手指的按下–抬起那些过程才会触发onClick()方法。

一经单独是功效性功用的话,那么文案就要言必有中。

小结

为了更好的驾驭,可以把事件流看成是一队人,把ACTION_DOWN类型看做探路人,探路人按规定的路线先走一次,直到走到View的onTouch伊芙nt那里,若是onTouch伊芙nt再次来到true,可见晓成此路通,后续部队可以过来。假若回去false,可以清楚成此路不通,然后探路人再到Layout(ViewGroup)的onTouch伊夫nt中问路通不通,即使通的话后续部队就不要再去View那里了,直接到ViewGroup那来就可以了。而只要ViewGroup那里路也不通,那么探路人就只可以去Activity的onTouch伊夫nt那里了,后续部队也一贯去Activity的onTouch伊夫nt那里就足以了。


终极想说的是,本序列小说为博主对Android知识举办再一次梳理,查缺补漏的就学进程,一方面是对友好忘记的事物加以复习重新了解,另一方面相信在重新学习的进程中定会有巨大的新取得,假如您也有跟自家同一的想法,不妨关怀自我一块儿上学,相互商讨,共同升高!

参考文献:

  • 《Android开发格局探索》

2

事实上景况中大家平常不可能把文案的字数写的太多,一个是页面版面所限,还有一个勘测的因素就是用户的耐性程度,用户很难有耐心去看完大家的长篇文字。为了不使得用户因文字过多而关闭页面,就必要减少文案的篇幅,首先我们要尝尝着把复杂的政工说的不难,如若实际不行,就先传递最要害的新闻给用户。借助空间和岁月的概念,在文字的偏重点和时间的先后性上下功夫,适当的时候告诉她正好的音信。

说到那,让自身想开另一个难点就是页面前后的承接性。越发是在产品的新手流程中,大部分出品使用的法门都是亟需一步一步的给用户讲解清楚。有时候我们会发觉前一个页面跟后一个页面所要描述的事物并无法连贯起来,前后的承接相比突兀,那时候大家得以动用文案对用户进行率领。常见的一种形式是将文案写成问句,既增添前后承接的合理又能更好的让用户读懂大家所要传达的音讯。

3

后天尤为多的产品文案都利用了网上时下流行的各样体,例如此前的凡客体、咆哮体等,跟风Tmall,很多成品对用户的称谓也写成了“亲”,文案的格局得以有无数花样。

借助于网络流行语会追加用户对文案的钟爱程度,可是也要留心采纳程度,再好的事物使用频率多了,难免也会让用户暴发反感。

好的文案在高达表明新闻的功底上,还有一个闪光点就是拉近与用户之间的偏离,文案也是成品跟用户调换的载体,调换的进度中文案的语气不用过于严穆,写的任性一些,会追加用户对平台的亲切感。尤其是赶上产品出标题的时候,文案写好了不但会下滑用户的怒气,适当的拍拍用户马屁也是可以的,或许还会讨得用户的一笑,然则那往往须求配上一个卖萌的形象。

在产品设计过程中,文案的行使会很灵敏。差距的场景,不一样的用户群,不一样的时候,文案被寄予的目标就会有所分化,文案的情节自然也会分歧。