Android5.1 触摸屏事件分发机制和源码解析二 --(ViewGroup篇)

一。案例分析

还是和上文一样,写一个非常简单的项目。

我们自定义了一个LinearLayout和Button控件。

由代码中,我们可以发现LinearLayout比Button多了一个onInterceptTouchEvent()方法。

MyLinearLayout.java

package com.example.viewanalyse;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;

public class MyLinearLayout extends LinearLayout {
	private static final String TAG = "ViewAnalyse";
	public MyLinearLayout(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

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

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		Log.d(TAG, "dispatchTouchEvent-- action="+ev.getAction()+"--MyLinearLayout");
		return super.dispatchTouchEvent(ev);
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		Log.d(TAG, "onInterceptTouchEvent-- action="+ev.getAction()+"--MyLinearLayout");
		return super.onInterceptTouchEvent(ev);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		Log.d(TAG, "onTouchEvent-- action="+event.getAction()+"--MyLinearLayout");
		return super.onTouchEvent(event);
	}



}

MyButton.java

package com.example.viewanalyse;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.widget.Button;

public class MyButton extends Button {

    private static final String TAG = "ViewAnalyse";
    
	public MyButton(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

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


	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		Log.d(TAG, "onTouchEvent-- action="+event.getAction()+"--MyButton");
		return super.onTouchEvent(event);
	}


	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		Log.d(TAG, "dispatchTouchEvent-- action="+event.getAction()+"--MyButton");
		// TODO Auto-generated method stub
		super.dispatchTouchEvent(event);
		return true;
	}


}

布局文件activity_main.xlm

<com.example.viewanalyse.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:id="@+id/layout"
    tools:context=".MainActivity" >

    <com.example.viewanalyse.MyButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button"
        android:text="button" />

</com.example.viewanalyse.MyLinearLayout>

MainActivity.java

package com.example.viewanalyse;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

public class MainActivity extends Activity implements View.OnTouchListener,View.OnClickListener {
	private MyLinearLayout mLayout;
    private Button mButton;
    private static final String TAG = "ViewAnalyse";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mLayout =(MyLinearLayout)findViewById(R.id.layout);
        mButton =(MyButton)findViewById(R.id.button);
        
        mLayout.setOnTouchListener(this);
        mButton.setOnTouchListener(this);

        mLayout.setOnClickListener(this);
        mButton.setOnClickListener(this);

        
    }

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		// TODO Auto-generated method stub
		Log.d(TAG, "onTouch-- action="+event.getAction()+" --"+v);
		return false;
	}
	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		Log.d(TAG, "onClick --"+v);
	}


    
}

1.1 我们用手指点击一下button,打印出来的log:

10-16 11:32:41.410: D/ViewAnalyse(10616): dispatchTouchEvent-- action=0--MyLinearLayout
10-16 11:32:41.410: D/ViewAnalyse(10616): onInterceptTouchEvent-- action=0--MyLinearLayout
10-16 11:32:41.410: D/ViewAnalyse(10616): dispatchTouchEvent-- action=0--MyButton
10-16 11:32:41.410: D/ViewAnalyse(10616): onTouch-- action=0 --com.example.viewanalyse.MyButton
10-16 11:32:41.410: D/ViewAnalyse(10616): onTouchEvent-- action=0--MyButton
10-16 11:32:41.460: D/ViewAnalyse(10616): dispatchTouchEvent-- action=1--MyLinearLayout
10-16 11:32:41.460: D/ViewAnalyse(10616): onInterceptTouchEvent-- action=1--MyLinearLayout
10-16 11:32:41.460: D/ViewAnalyse(10616): dispatchTouchEvent-- action=1--MyButton
10-16 11:32:41.460: D/ViewAnalyse(10616): onTouch-- action=1 --com.example.viewanalyse.MyButton
10-16 11:32:41.460: D/ViewAnalyse(10616): onTouchEvent-- action=1--MyButton
10-16 11:32:41.470: D/ViewAnalyse(10616): onClick --com.example.viewanalyse.MyButton

1.2 我们用手指点击一下除button以外的其他区域(ViewGroup事件派发),打印出来的log:

10-16 11:35:04.260: D/ViewAnalyse(10616): dispatchTouchEvent-- action=0--MyLinearLayout
10-16 11:35:04.260: D/ViewAnalyse(10616): onInterceptTouchEvent-- action=0--MyLinearLayout
10-16 11:35:04.260: D/ViewAnalyse(10616): onTouch-- action=0 --com.example.viewanalyse.MyLinearLayout
10-16 11:35:04.260: D/ViewAnalyse(10616): onTouchEvent-- action=0--MyLinearLayout
10-16 11:35:04.320: D/ViewAnalyse(10616): dispatchTouchEvent-- action=1--MyLinearLayout
10-16 11:35:04.320: D/ViewAnalyse(10616): onTouch-- action=1 --com.example.viewanalyse.MyLinearLayout
10-16 11:35:04.320: D/ViewAnalyse(10616): onTouchEvent-- action=1--MyLinearLayout
10-16 11:35:04.330: D/ViewAnalyse(10616): onClick --com.example.viewanalyse.MyLinearLayout

由Log1.1 我们可以发现,点击一下button,首先触发的是Linearlayout中的dispatchTouchEvent() -->LinearLayout中的onInterceptTouchEvent,然后才是button的dispatchTouchEvent()方法(其中button的事件分发流程就是和上篇View中的分发流程一样)。也就是说,点击一个View事件,首先触发的是父控件的dispatchTouchEvent() -->onInterceptTouchEvent -->然后再传递给子控件进行派发,即子控件的dispatchTouchEvent() .....

由Log1.2 我们可以发现,点击ViewGroup的事件派发和点击View的事件派发有一点差异。差异点主要在在action_down的时候,ViewGroup多了一个onInterceptTouchEvent()方法:

ViewGroup事件顺序为:dispatchTouchEvent->onInterceptTouchEvent->onTouch->onTouchEvent

View事件顺序为:dispatchTouchEvent->onTouch->onTouchEvent

在action_up的时候,LinearLayout却没有触发onInterceptTouchEvent(), 和View的事件派发流程一致。


二。ViewGroup.java传递事件源码分析

猜你喜欢

转载自blog.csdn.net/genius9_9/article/details/49176759