Android View事件分发机制理解

Posted wjinhhua

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android View事件分发机制理解相关的知识,希望对你有一定的参考价值。


MainActiviity

public class MainActivity extends Activity 
    private TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.tv);
        init();
    
    private void init() 
        tv.setOnTouchListener(new OnTouchListener() 

            @Override
            public boolean onTouch(View v, MotionEvent event) 
                switch (event.getAction()) 
                case MotionEvent.ACTION_DOWN:
                    System.out.println("-----------DOWN-------");
                    break;
                case MotionEvent.ACTION_UP:
                    System.out.println("-----------UP-------");
                    break;
                default:
                    break;
                
                //return false;
                return true;
            
        );

    

main.xml

<com.example.testevent.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.testevent.MainActivity" >

    <com.example.testevent.MyTextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</com.example.testevent.MyLinearLayout>

其中MyLinearLayout继承LinearLayout

public class MyLinearLayout extends LinearLayout

    @SuppressLint("NewApi")
    public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) 
        super(context, attrs, defStyleAttr);
        // TODO Auto-generated constructor stub
    

    public MyLinearLayout(Context context, AttributeSet attrs) 
        super(context, attrs);
        // TODO Auto-generated constructor stub
    

    public MyLinearLayout(Context context) 
        super(context);
        // TODO Auto-generated constructor stub
    

    @Override
    public boolean onTouchEvent(MotionEvent event) 
        // TODO Auto-generated method stub
        int action = event.getAction();

        switch (action) 
        case MotionEvent.ACTION_DOWN:
            System.out.println("MyLinearLayout ---ACTION_DOWN ---");
            break;
        case MotionEvent.ACTION_UP:
            System.out.println("MyLinearLayout ---ACTION_UP ---");
            break;
        default:
            break;
        
        System.out.println("MyLinearLayout ---onTouchEvent ---");       
        return true;
        //return super.onTouchEvent(event);
    

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) 
        // TODO Auto-generated method stub
        System.out.println("MyLinearLayout ---onInterceptTouchEvent ---");
        return super.onInterceptTouchEvent(ev);
        //return true;
    

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) 
        // TODO Auto-generated method stub
        System.out.println("MyLinearLayout ---dispatchTouchEvent ---");
        return super.dispatchTouchEvent(ev);
        //return true;
    


MyTextView继承TextView

public class MyTextView extends TextView 

    public MyTextView(Context context, AttributeSet attrs) 
        super(context, attrs);
        // TODO Auto-generated constructor stub
    

    public MyTextView(Context context) 
        super(context);
        // TODO Auto-generated constructor stub
    

    public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) 
        super(context, attrs, defStyleAttr);
        // TODO Auto-generated constructor stub
    

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) 
        // TODO Auto-generated method stub
        int action = event.getAction();

        switch (action) 
        case MotionEvent.ACTION_DOWN:
            System.out.println("MyTextView ---ACTION_DOWN ---");
            break;
        case MotionEvent.ACTION_UP:
            System.out.println("MyTextView ---ACTION_UP ---");
            break;
        default:
            break;
        
        System.out.println("MyTextView ---onTouchEvent ---");
        return super.onTouchEvent(event);
       // return true;
    

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) 
        // TODO Auto-generated method stub
        System.out.println("MyTextView ---dispatchTouchEvent ---");
        return super.dispatchTouchEvent(event);
        //return true;
    

先看第一张图

通过图我们可以看到事件分发默认情况是由父控件捕捉向子控件传递,子控件不消费(但可以做自己的其他逻辑),最后再回传到父控件,父控件进行消费。
当子控件消费(onTouchEvent返回true)后,不再回传给父控件。这有点类似java的继承关系。如果父控件拦截(onInterceptTouchEvent返回true)之后,将不会传递给子控件。
再看第二张

通过图我们可以看到setOnTouchListener的优先级高于onTouchEvent。

最后,为了方便大家理解,我贴一下整理的输出内容,大家看图不明白,可以对着输出内容来理解

默认:
10-05 04:07:55.076: I/System.out(2502): MyLinearLayout ---dispatchTouchEvent ---
10-05 04:07:55.076: I/System.out(2502): MyLinearLayout ---onInterceptTouchEvent ---
10-05 04:07:55.076: I/System.out(2502): MyTextView ---dispatchTouchEvent ---
10-05 04:07:55.076: I/System.out(2502): MyTextView ---ACTION_DOWN ---
10-05 04:07:55.076: I/System.out(2502): MyTextView ---onTouchEvent ---
10-05 04:07:55.076: I/System.out(2502): MyLinearLayout ---ACTION_DOWN ---
10-05 04:07:55.076: I/System.out(2502): MyLinearLayout ---onTouchEvent ---


MyTextView-- onTouchEvent----return true===
10-05 04:14:15.616: I/System.out(2548): MyLinearLayout ---dispatchTouchEvent ---
10-05 04:14:15.616: I/System.out(2548): MyLinearLayout ---onInterceptTouchEvent ---
10-05 04:14:15.616: I/System.out(2548): MyTextView ---dispatchTouchEvent ---
10-05 04:14:15.616: I/System.out(2548): MyTextView ---ACTION_DOWN ---
10-05 04:14:15.616: I/System.out(2548): MyTextView ---onTouchEvent ---
10-05 04:14:15.696: I/System.out(2548): MyLinearLayout ---dispatchTouchEvent ---
10-05 04:14:15.696: I/System.out(2548): MyLinearLayout ---onInterceptTouchEvent ---
10-05 04:14:15.696: I/System.out(2548): MyTextView ---dispatchTouchEvent ---
10-05 04:14:15.696: I/System.out(2548): MyTextView ---ACTION_UP ---
10-05 04:14:15.696: I/System.out(2548): MyTextView ---onTouchEvent ---


MyTextView-- dispatchTouchEvent----return true===  //onTouchEvent&&dispatchTouchEvent----return true===
10-05 04:16:39.676: I/System.out(2591): MyLinearLayout ---dispatchTouchEvent ---
10-05 04:16:39.676: I/System.out(2591): MyLinearLayout ---onInterceptTouchEvent ---
10-05 04:16:39.676: I/System.out(2591): MyTextView ---dispatchTouchEvent ---
10-05 04:16:39.746: I/System.out(2591): MyLinearLayout ---dispatchTouchEvent ---
10-05 04:16:39.746: I/System.out(2591): MyLinearLayout ---onInterceptTouchEvent ---
10-05 04:16:39.746: I/System.out(2591): MyTextView ---dispatchTouchEvent ---


MyLinearLayout-- onTouchEvent----return true=== 
10-05 04:22:09.476: I/System.out(2677): MyLinearLayout ---dispatchTouchEvent ---
10-05 04:22:09.476: I/System.out(2677): MyLinearLayout ---onInterceptTouchEvent ---
10-05 04:22:09.476: I/System.out(2677): MyTextView ---dispatchTouchEvent ---
10-05 04:22:09.476: I/System.out(2677): MyTextView ---ACTION_DOWN ---
10-05 04:22:09.476: I/System.out(2677): MyTextView ---onTouchEvent ---
10-05 04:22:09.476: I/System.out(2677): MyLinearLayout ---ACTION_DOWN ---
10-05 04:22:09.476: I/System.out(2677): MyLinearLayout ---onTouchEvent ---
10-05 04:22:09.546: I/System.out(2677): MyLinearLayout ---dispatchTouchEvent ---
10-05 04:22:09.546: I/System.out(2677): MyLinearLayout ---ACTION_UP ---
10-05 04:22:09.546: I/System.out(2677): MyLinearLayout ---onTouchEvent ---



MyLinearLayout-- onInterceptTouchEvent----return true
10-05 04:28:40.086: I/System.out(2720): MyLinearLayout ---dispatchTouchEvent ---
10-05 04:28:40.096: I/System.out(2720): MyLinearLayout ---onInterceptTouchEvent ---
10-05 04:28:40.096: I/System.out(2720): MyLinearLayout ---ACTION_DOWN ---
10-05 04:28:40.096: I/System.out(2720): MyLinearLayout ---onTouchEvent ---

MyLinearLayout-- dispatchTouchEvent----return true===
10-05 04:31:52.536: I/System.out(2852): MyLinearLayout ---dispatchTouchEvent ---
10-05 04:31:52.636: I/System.out(2852): MyLinearLayout ---dispatchTouchEvent ---

-------------------------------------------------------
setOnTouchListener--- return false=======

默认:
10-05 04:48:19.746: I/System.out(3243): MyLinearLayout ---dispatchTouchEvent ---
10-05 04:48:19.746: I/System.out(3243): MyLinearLayout ---onInterceptTouchEvent ---
10-05 04:48:19.746: I/System.out(3243): MyTextView ---dispatchTouchEvent ---
10-05 04:48:19.746: I/System.out(3243): -----------DOWN-------
10-05 04:48:19.746: I/System.out(3243): MyTextView ---ACTION_DOWN ---
10-05 04:48:19.746: I/System.out(3243): MyTextView ---onTouchEvent ---
10-05 04:48:19.746: I/System.out(3243): MyLinearLayout ---ACTION_DOWN ---
10-05 04:48:19.746: I/System.out(3243): MyLinearLayout ---onTouchEvent ---

MyTextView--dispatchTouchEvent----return true
10-05 05:00:27.706: I/System.out(3419): MyLinearLayout ---dispatchTouchEvent ---
10-05 05:00:27.706: I/System.out(3419): MyLinearLayout ---onInterceptTouchEvent ---
10-05 05:00:27.706: I/System.out(3419): MyTextView ---dispatchTouchEvent ---
10-05 05:00:27.786: I/System.out(3419): MyLinearLayout ---dispatchTouchEvent ---
10-05 05:00:27.786: I/System.out(3419): MyLinearLayout ---onInterceptTouchEvent ---
10-05 05:00:27.786: I/System.out(3419): MyTextView ---dispatchTouchEvent ---

MyTextView--onTouchEvent----return true
10-05 05:03:39.846: I/System.out(3462): MyLinearLayout ---dispatchTouchEvent ---
10-05 05:03:39.846: I/System.out(3462): MyLinearLayout ---onInterceptTouchEvent ---
10-05 05:03:39.846: I/System.out(3462): MyTextView ---dispatchTouchEvent ---
10-05 05:03:39.846: I/System.out(3462): -----------DOWN-------
10-05 05:03:39.846: I/System.out(3462): MyTextView ---ACTION_DOWN ---
10-05 05:03:39.846: I/System.out(3462): MyTextView ---onTouchEvent ---
10-05 05:03:39.926: I/System.out(3462): MyLinearLayout ---dispatchTouchEvent ---
10-05 05:03:39.936: I/System.out(3462): MyLinearLayout ---onInterceptTouchEvent ---
10-05 05:03:39.936: I/System.out(3462): MyTextView ---dispatchTouchEvent ---
10-05 05:03:39.936: I/System.out(3462): -----------UP-------
10-05 05:03:39.936: I/System.out(3462): MyTextView ---ACTION_UP ---
10-05 05:03:39.936: I/System.out(3462): MyTextView ---onTouchEvent ---

MyLinearLayout-- dispatchTouchEvent----return true===== MyTextView-- setOnTouchListener无效
10-05 04:31:52.536: I/System.out(2852): MyLinearLayout ---dispatchTouchEvent ---
10-05 04:31:52.636: I/System.out(2852): MyLinearLayout ---dispatchTouchEvent ---


MyLinearLayout-- onInterceptTouchEvent----return true===== MyTextView-- setOnTouchListener无效
10-05 04:28:40.086: I/System.out(2720): MyLinearLayout ---dispatchTouchEvent ---
10-05 04:28:40.096: I/System.out(2720): MyLinearLayout ---onInterceptTouchEvent ---
10-05 04:28:40.096: I/System.out(2720): MyLinearLayout ---ACTION_DOWN以上是关于Android View事件分发机制理解的主要内容,如果未能解决你的问题,请参考以下文章

完全理解Android TouchEvent事件分发机制

理解Android View的事件传递机制

Android 源码解析View的touch事件分发机制

Android事件分发机制总结

View事件分发机制

Android查缺补漏(View篇)--事件分发机制源码分析