安藤忠雄:从三流拳击师到顶尖建筑家

事件分发机制是Android中至极关键的一个知识点,同时也是困难,相信到近日结束很多Android开发者对事件分发机制并从未一个至极系统的认识,当然也包罗博主个人在内。可能在经常的支出工作中我们并从未察觉到事件分发机制起到的功效,其实它是随时存在的只是我们不精晓而已,就像有些滑行顶牛、点击事件期间的争辩等等大多是因为事件分发处理不当导致的。想起了博主大学时做过一个小项目,里面就出现了滑动争辨的题目,尽管最终在网上一步步看着人家的科目也糊里糊涂的化解了,但归根结蒂不知其所以然,那么前些天就让我们一块来深入的探赜索隐一下事件分发机制吗。

关于安藤忠雄广为流传的故事:据传他养了两条狗,一条叫丹下健三,一条叫勒·柯布西耶。他心中中神级般存在的现代建造巨擘,居然化身为他生活中的两条狗。那就是首屈一指的“安藤忠雄”做派。

咋样是事件分发机制?

说了半天的轩然大波分发机制这到底是个吗东西吧?我们决不把它想象的那么高深莫测,不要在思维上给自己设上阻碍,其实很容易精通,博主的敞亮是:简而言之,事件分发机制就是Android系统对事件传递过程规定的一种事件传递规则,事件都会按部就班这些规则举行分发传递。

在琢磨事件分发机制往日,我们先来规定一下解析的步调,化整为零,各个击破:

  • 弄精通分析目的:Motion伊芙(Eve)nt。
  • 打探多个点子:dispatchTouch伊芙(Eve)nt(Motion伊芙nt
    event)、onInterceptTouch伊夫(Eve)nt(Motion
    event)、onTouch伊芙(Eve)nt(Motion伊芙(Eve)nt event)。
  • Motion伊夫(Eve)nt事件的传递过程
  • 小结

图表来自网络

MotionEvent

实则点击事件的散发过程就是对Motion伊芙nt事件的分发过程,当用户点击操作按下后,Motion伊芙(Eve)nt事件随后发出并通过自然的规则传递到指定的View上,这多少个传递的过程和规则就是事件分发机制。

而点击操作触发Motion伊芙(Eve)nt事件是一个轩然大波流或者说是一个事件连串,其至高无上的轩然大波类型有如下两种:

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

要特别注意的是,常常情形下一个Motion伊芙(Eve)nt事件系列包含一个 ACTION_DOWN
若干个 ACTION_MOVE 和 ACTION_UP
是一个完全的风波类别。(点下来立马抬起指头时,会只有 ACTION_DOWN 和
ACTION_UP,这也是一个完好无缺的风波系列)

当然,安藤对建筑的挚爱也源自他们的启蒙。

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伊芙(Eve)nt()处理,假诺下边View的onTouch伊芙(Eve)nt()依旧重返false,那么事件将再交给上级的上级处理,以此类推,假如各级View的onTouch伊芙(Eve)nt()都不消耗事件,那么事件结尾将送交Activity的onTouch伊芙nt()处理。

上文说了这般多如故不够具体,先用流程图大体表达一个之上两个办法的关联,及调用流程,下文还会结合实际示例详细表达在事变分发传递中逐条艺术的调用规则。

三者关系大体如下图:

图片 1

假诺安藤还有第三条狗,他会起个什么名字?我猜答案是:路易斯(Louis)·康。这位大器晚成的建筑家,跟安藤忠雄平等,对建筑有宗教般的信仰情结;跟安藤忠雄扳平,热爱旅行,最终每天倒在旅程上。

Motion伊夫(Eve)nt事件传递过程

当手辅导击屏幕发生一个Touch事件后,事件遵照Activity->Window->View的逐一依次传递。

先是会传送给Activity的dispatchTouch伊芙nt(),在此方法内部会将由Window处理,接着事件会传送给根View,根View接收到事件后就会遵从事件分发机制去处理事件。

根View在此间就是一个ViewGroup,它在接受到事件后会调用dispatchTouch伊芙nt(),在此办法内部会透过onInterceptTouch伊夫(Eve)nt()方法判断是否拦截事件,假诺onInterceptTouch伊夫nt()重返true就意味着它要阻止事件,事件将传递给当下ViewGroup的onTouch伊夫nt()。即使onInterceptTouch伊芙(Eve)nt()放回false就象征它不阻拦事件,事件将传给其属下的View,调用下级View的dispatchTouch伊夫(Eve)nt()。

根View的手下人View可能又是一个ViewGroup,假若这样的话其传递流程同根View一样。无论根View的下级View是不是ViewGroup,假如不阻碍事件,最后事件会传送到一个纯View的控件上。

当一个View(纯View控件)接收到事件后,也会调用其dispatchTouch伊夫(Eve)nt(),然后在此措施内部会调用当前View的onTouch伊夫nt(),即使onTouch伊夫nt()再次回到true则表示要拍卖此事件。如若回去false表示不消耗事件,其上司View的onTouch伊夫(Eve)nt()将被调用,则事件流的持续部分不再传递到当下View,在一个轩然大波流中也不会再调用当前View的dispatchTouch伊夫(Eve)nt()。

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

安藤忠雄在高校课堂讲述康的著述和故事时表示,他希望团结最终的人生也像康这样,将生命在团结心爱的东西上收尾。

示例一,默认情状下的风波传递流程

创制3个类,一个Activity、一个卫冕自LinearLayout的View,一个继承自Button的View,一碗水端平写他们的dispatchTouch伊夫nt()、onIntercepteTouch伊芙(Eve)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>

运转代码,点击伊芙ntDispatchTestView(肉色区域),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伊夫(Eve)nt方法中,此时onTouch伊夫nt方法再次来到true,表示要处理事件,所以事件流的后续部分仍旧通过log中的流程到达了View的onTouch伊芙nt方法中。

生于一九四一年的安藤忠雄,二零一九年已经七十六岁了,依照劳动法规定,早已经通过了退休的壁垒,但他一如既往像晚年的路易斯(Louis)·康一样,每日带着巨大的劳作热情,去自己的建筑设计事务所,去世界各地旅行观光,参加来自各大城市建筑工程比赛邀请,还花大量的生气去高校讲座,发表她新的“海上森林”植树目的。

示例二、在示例一的基本功上,让View的onTouch伊夫(Eve)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伊夫(Eve)nt方法处理,而从log可以见到ViewGroup的onTouch伊夫nt默认也不消耗事件,所以事件由提交Activity的onTouch伊芙(Eve)nt方法处理,最后事件流的存续部分不再传递给ViewGroup和View,而是一向传送给Activity的onTouch伊芙(Eve)nt处理。

他身上或多或少也看不到已经放在建筑的世界四十余年来的疲倦感,也看不出这位资深海内外大师级的建筑家半点骄傲的影子。

示例三、在示例二的底蕴上让ViewGroup消耗事件

修改伊芙ntDispatchLinearLayout的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伊芙(Eve)nt方法,因为已经了解View不处理事件,所以没必要再经过onInterceptTouch伊夫nt方法来判定了。

三得利佐治先生曾告知安藤忠雄一句乌尔曼的诗:“青春不是人生的一段时光,青春是一种心态。”或许,从这天起,安藤忠雄就将那句诗记在心上。

示例四、假若在ViewGroup的onInterceptTouch伊芙nt中回到了true拦截了轩然大波,整个事件将不再传递给View而是直接交由ViewGroup的onTouch伊夫(Eve)nt处理。

修改伊芙(Eve)ntDispatchLinearLayout的onInterceptTouch伊芙(Eve)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监听器。

在伊芙(Eve)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伊芙(Eve)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伊夫(Eve)nt这里就可以了。


说到底想说的是,本系列著作为博主对Android知识进行重复梳理,查缺补漏的读书过程,一方面是对自己忘记的事物加以复习重新明白,另一方面相信在重新学习的历程中定会有远大的新获得,假若你也有跟自身一样的想法,不妨关注自己一同念书,相互商量,共同提升!

参考文献:

  • 《Android开发情势探索》

十七岁时,他拿到事情拳击手执照,只身飘洋过海去泰国出席拳击比赛。回想这段人生,他说:“拳击是一种毫不仰赖外人的斗殴竞赛,比赛前多少个月,会只为了这第一次大战而努力操练,有时还必须绝食来磨练身体与精神。如此赌上性命,独自承受孤独与光荣。”

01 “独自承受孤独与光荣”

这句话伴随安藤忠雄至今。

高中毕业后,一遍偶然机会去日本首都游览,看到由弗兰克(Frank)·劳埃德(劳埃德(Lloyd))·赖特(Wright)设计的帝国大餐馆,触发他无意里的建造梦想。他发轫进修建筑设计。

“只要遇到让自己感兴趣的东西,我都会想挑衅看看。例如去听建筑和室内设计的函授课程,还有上设计学的夜校。”

万幸得很,他在书中碰着了人生导师勒·柯布西耶。“我清楚了柯布西耶这位当代建筑界的大王,实际上也是自学出身的建筑家,通过文字描述,我精晓到她与老旧的体裁相抗争,从而创立出一条新的征途。他的存在,让自身早已超过了独自的崇拜。”

二十岁时,他游历日本,看遍日本国内丹下健三的作品。二十四岁时,他踏上非洲之旅,从横滨港搭船到纳霍德卡,转乘大车经西伯伊兹密尔铁路前往华沙,从阿姆斯特丹到芬兰共和国、法兰西共和国、瑞士、意大利、希腊,再到西班牙,最终从南法的杜阿拉绕经南美洲的休斯敦(Houston),再到马达加斯加、印度、菲律宾事后回国。

定期四个月的旅程。他亲自感受了汪洋的修建,从史前罗午时代的万神殿到胡志明市卫城之丘的帕提农神庙,从西班牙的巴塞罗这安东尼奥·高迪的建造,到意大利赫尔辛基、那格浦尔米开朗琪罗的壁画、画作,再到勒·柯布西耶的朗香圣母礼拜堂、拉图雷特修道院和马普托的会面住宅。

勒·柯布西耶

法兰西朗香教堂

这几乎能够作为是安藤忠雄一回现代构筑的根源之旅,更是三回心灵的朝圣之旅。遗憾的是他最终无缘见上这年去世的勒·柯布西耶。

饥渴的安藤,通过实地旅行,触摸到建筑的本质和真理,二十几岁的出游,成了她随后的人生无可取代的资产。

进修和远足,这一等级的人生将近十年,安藤开端踏上修建设计师之路。这条路一走就是四十多年,从一个底特律平民家庭的子女巨变成蜚声海外的建造大师。但想起这四十多年的修建人生,安藤用五个字作了包括:连续失败连战。

从面临争议的处女作“住吉的长屋”,到知名全球的“光之教堂”,这中档是十年的跨度。安藤总是苦口婆心地说,二十几岁的人生,是看不到收获的,充满不安感地生活,不停地读书、旅行、实践、成长,才能迎来四十几岁将来人生的晨曦。

“……在现实社会里,想要认真地追求理想,必然会跟社会争辩。恐怕大都不会如自己所愿,而过着连战连续失败的小日子。即使如此,如故不停地挑衅,就是作为建筑家的活着形式。只要不抛弃地努力拼搏,将来肯定有那么一天会看出曙光。愿意相信那种可能性的强韧意志和容忍,就是建筑家最需要的天赋……”

自然,成就安藤忠雄建筑家的三大法宝,除了自学、旅行,还有结交。

上世纪六十年代先前时期,安藤平常从科伦坡前往东京(Tokyo),与当下艺术界的时髦派年轻人来往频繁,其中囊括剧团人员高松次郎、筱原有司男、寺山修司、唐十郎,平面设计人员横尾忠则、田中一光,版画师筱山纪信等等,平常与她们共同流连于剧团、风月堂、沙龙酒吧,谈论对艺术的认识。

一九九六年春,安藤去东京(Tokyo)大学建筑史任教,三得利的佐治先生“为了让圣彼得(Peter)堡的安藤不会在东京(Tokyo)被欺负”,特地邀请了熊谷信昭、三宅一生、中村雁治郎等友人,几位东京(Tokyo)大学的讲授,以及关关西财经界的人选为她饯行,单是这顿饭,就足以想到安藤的交接面有多么广泛。

而外三得利的佐治先生,安藤与关西地区的财经界另外有力人员也颇有交往,例如朝日朗姆酒的樋口先生、三洋电机的井植先生、京瓷美达的稻盛先生,安藤结识的这么些公司界的政要,都是尽人皆知世界的,他们给安藤建筑事务所带动许多上门的饭碗:唐十郎的活动剧院,京瓷美达赞助的“都市巨蛋”、三洋电机支援的“本福寺佛堂”、朝日鸡尾酒的“大山崎山庄美术馆”、三得利的“天吕梁三得利博物馆”。

安藤忠雄卢布尔雅那工作室

02  “以建造来对都市有所诉求”

不认为自己有任何身份来谈谈建筑。

即便事先读过一本与建筑相关的创作,比如隈研吾的《十宅论》,这是青春时候隈研吾的理论式小说,像是硕士生毕业小说一样,偏向于学术气息,即使大抵能看得了解,但味道等同白开水煮大白菜。得益于隈研吾小说的研读,对日本的价值观住房类型有了大致的问询。

打听安藤的修建创作之后,才算清楚,前日的日本建造完全不是如此。比如她的著述住吉长屋、小筱邸、六甲集合住宅,完全不是事先的记忆和价值观,完全是颠覆性的。而且,通过这么些简单有趣的著述,安藤先生将他的宏图意见、住宅建筑实现的阅历,一一演讲,一些常识性的道理却像珍珠般闪闪发光。

安藤忠雄自传随笔

在《建筑家安藤忠雄》一书中,建筑设计那样类似复杂苦涩难懂的事物,竟被他说得简单有趣、通俗易懂,与什么高校派张嘴闭口理论术语满天飞的师父相相比较,安藤特别民间。

他说:“建筑设计的目标,是要修建合理、符合经济效益,且更要紧的是喜上眉梢的建筑。可是,闷在封闭的不透气的室内,和住在有点多少不便却足以期待天空自然呼吸的小院里,两相比较,到底哪类相比较‘舒适’呢?生活在其间的人最有发言权。假设更深一层去考虑生活方法和传统的题材,建筑的可能便会大增,变得越来越随意吧!人的身心其实远比想象中来得坚韧。”

与刻意强调高度、规模、技术、结构、色彩、理念推导和数据模型的建筑设计师相相比,安藤花更多笔墨谈论他的计划性意见,直白、简单的表述,一下子让人掀起他透过建筑创作的诉求、意图和设法。

“将光泽与风等抽象化的当然导入建筑中间”的住吉长屋;“以光为主题的清心寡欲式生活空间”的小筱邸;“让新加坡的水岸空间再一次重生”TIME’S;“让过去延续活在当代”的表参道之丘;“与水畔风景合二为一”的本福寺水御堂;“水面上浮着十字架”的水之教堂;“光与影弹奏的交响曲”的光之教堂……这种严穆而雅观的,直捣人心的上空,就一首首美好的诗记在内心深处。在她的小说之中,可以最大限度突显思考的结果。很多时候,安藤像是一位国学家,在思考建筑与都市、自然、光影、生命之间的涉及。

安藤忠雄随笔:住吉的长屋

安藤忠雄小说:水之教堂

安藤忠雄随笔:南美洲现代美术馆

安藤忠雄小说:保利大马戏团

03 “让生活融入自然中才是住宅的精神”

安藤忠雄通过他的作品表达了好多近似的建造常识。

譬如,他常说:每个城市都各有独特的魅力,对各样地点我都有谈得来的发现和打动。又比如说,在《建筑家安藤忠雄》一书中,他表示她的建筑思考原点:“建筑的性命和再生。”

比方不精通非常地点的野史、人文、自然环境、城市规划、居住习惯,他认为自己从没身份谈论这些地点的建筑设计。因而,他花费大量的时光去世界各地旅行,通晓不同国度不同城市的文脉、社会生态和建筑风格。

他大力反对去追随浪潮,他对东瀛八九十年间的狂热消费主义嗤之以鼻:“跳脱出把旧的东西就是垃圾而废弃的消费主义圈圈,善用现有事物,将过往联系到将来;只要重拾我们在过去美好的时日里爱抚事物的生活模式,一定可以培养属于自己的都市景致。”

他始终认为,假使一向地迎合业主,恐怕会迷路建筑本质;倘使卷入商业建筑的金钱游戏,恐怕会迷路自己。由此,他深感自己与社会顶牛,并自觉地与商业性建筑类型保持自然的相距。“项目承载与否的判断标准,不在于预算与范围,只看自己能否和客户研商梦想并迎接挑衅。”

他如故说:“我也间接认为:建筑家应对团结设计过的建造负责,只要建筑还设有,就该对它承担。”在那个短缺信仰的年份,我们从安藤身上,可以找到所有稀缺的灵魂。也许是旅行、自学、对擅自的归依、从来没有体制的约束,等等那些,成就了安藤的这种格调。我以为,这才是建筑家身上最要害的事物。艺术是书儒家性格的显示模式。同样道理,建筑也是建筑家人性的变现。

安藤忠雄随笔:光之教堂效果图

安藤忠雄随笔:光之教堂模型  

安藤忠雄随笔:光之教堂实景拍摄  

安藤忠雄著作:光之教堂设计效能图

04 “不要模仿旁人!创制新东西!跳脱出全方位事物的框框!”

这是一流的安藤忠雄式观点。当然,你也得以明白为,他描述的实际都是关于生活的一部分实在观念,然后,通过他的经济学思想,将其以建造的花样来演绎。

安藤忠雄平时以咨询的花样来诱导我们,“面对城市,建筑该是何种样貌?建筑能对都市做什么?”“建筑物是为何人而建?社会现在的要求为啥?”“为啥这个世界不可能更好玩呢?社会不可以更可以吗?”“怎么着让建筑确实?”……

提问、思考、意念、百折不挠,随之结合安藤的修建创作创意,将她对建筑的认识和统筹理念不断道来。在深受启发之余,引发更多的合计。

安藤忠雄问:“什么是人生的甜美?”

安藤忠雄答:“我觉得,一个人的确的甜美并不是待在美好里面。从海外凝望光明,朝它努力奔去,就在这拼命忘我的流年里,才有人生真正的加码。”

恍如的问题好像是从安藤忠雄人体里自可是然生长出来的。像青色植株。

初阶众多国内建造专家谈及的话题,更多关系到的是规模、低度、结构、色彩、象征、格局,理念层面及精神层面的东西从来不人甘愿敞如沐春风扉来议论,这就难怪广大常识性的审美意识和审美观点也鲜为人知。

简单易行,就是我们的驳斥阁楼不是建筑在美学基础常识上,还是建设在所谓“浪潮”、所谓“高见”、所谓“妙论”、所谓“奇谈”上。所以,城市前行的结果是,越来越难看、无序、庞大、混乱、错愕,污染、堵塞、水患、噪音,司空眼惯,钢筋水泥建筑的都市,成为囚禁无发现东风标致的铁笼。

正如安藤忠雄所说的这样:“只会凭借经济理论,一再重复建设与破坏的循环,最终暴发世界上无比的‘混沌’都市。”

建筑家安藤忠雄

05 “清水混凝土小说家”

居于地球村的时代,安藤忠雄成了社会风气的一有些。

意大利特雷维索FABRICA、意大利约翰内斯堡Gucci剧场、意大利威蒙彼利埃古迹海关大楼、美利坚联邦合众国沃夫兹堡现代美术馆、德意志联邦共和国霍姆布洛伊美术馆、麦纳麦海洋博物馆、巴林遗迹博物馆等跨区域、跨国界著作,遍布世界各地。

一流的安藤忠雄有诸多誉称,其中“清水混凝土作家”最为显赫,并传到。安藤是建筑宗教最忠诚的教徒,“筑禅”既是他的心语,也是他的境地。

像十六世纪中叶西方基督教的传教士一样,现在的安藤忠雄在依靠其他机会传播、讲解、讲师他对建筑、创制、学习、生命的接头和通晓,去世界各地举行发言、建筑小说展览、担任多所高等高校的客座助教、出版多种关于建筑的书本。

自然,后日的安藤忠雄就像胡志明市相同,不是一天建成的。

她已变为日本依靠全球化、后现代工业浪潮,推广到世界各地“文化标记”和“产业代表”,像大家了解的紫式部、清少纳言、川端康成、大江健三郎、村上春树、小津安二郎、黑泽明、北野武、三船敏郎、高仓健、三宅一生、山本耀司、原研哉等名字之于扶桑同样;像我们耳熟能详的菊花、樱花、俳句、和歌、茶道、浮世绘、歌舞伎、武士道、富士山、山口县等东西之于日本一律,他一度改成一个国际性的专出名字,一张后现代扶桑的片子。

【Written by: 唐 瞬】

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图