Android中事件处理机制之——View的事件分发详解(一)

转载请注明出处:http://blog.csdn.net/xiaohao0724/article/details/54780880

Android中事件分发和事件传递是一个难点牵涉的东西较多,下面我们就由浅入深一点一点来给解析事件的分发和传递机制。

在分析事件的机制之前需要大家了解如下知识:

Android所有控件的父控件都是View和ViewGroup

ViewGroup继承了View
Button、EditText、TextView、ImageView等都继承了View
RelativeLayout、LinearLayout、FrameLayout、TableLayout、AbsoulteLayout五大布局继承了ViewGroup
事件处理机制主要通过dispatchTouchEvent方法来处理,当触摸到了任何一个控件,就一定会调用该控件(或该控件的父类)的dispatchTouchEvent方法


View是根据dispatchTouchEvent的返回值进行事件分发,当返回true时响应所有事件,事件的分发事件停止。

 public boolean dispatchTouchEvent(MotionEvent event) {
     
        return false/true;
}


ViewGroup根据onInterceptTouchEvent的返回值判断是否去拦击事件进行事件传递的,返回true拦截事件不向子控件传递,返回false是不拦截传递给子控件

	public boolean onInterceptTouchEvent(MotionEvent ev) {
	 
		return false/true;
	}


View中dispatchTouchEvent的完整方法

public boolean dispatchTouchEvent(MotionEvent event) {  
    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&  
            mOnTouchListener.onTouch(this, event)) {  
        return true;  
    }  
    return onTouchEvent(event);  
}  

当给View设置了setOnTouchListener之后

①mOnTouchListener != null   恒成立
②(mViewFlags & ENABLED_MASK) == ENABLED  恒成立
③mOnTouchListener.onTouch(this, event)   跟 setOnTouchListener中回调的onTouch的返回值相同


OK,本篇带大家来一块来分析比较简单的一种情况的事件分发。

首先新建一个EventView工程:

activity_main.xml布局代码

<RelativeLayout 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:gravity="center"
    tools:context=".MainActivity" >

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:background="@drawable/ic_launcher" />

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/imageView"
        android:layout_marginTop="30dp"
        android:gravity="center"
        android:text="点击" />

</RelativeLayout>

MainActivity.java代码

package com.havorld.eventview;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity {

	protected static final String TAG = "TAG";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		ImageView imageView = (ImageView) findViewById(R.id.imageView);
		Button button = (Button) findViewById(R.id.button);

		imageView.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {

				// event.getAction()返回0是按下down,返回1是抬起up,返回2是移动move
				Log.e(TAG, "imageView---onTouch---" + event.getAction());
				return true;
			}
		});
		
		button.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				
				Log.e(TAG, "button ---onTouch---" + event.getAction());
				return true;
			}
		});

	}

}

一、对ImageView进行事件分发分析

点击并滑动ImageView图片:

当setOnTouchListener回掉的onTouch方法返回true时:


onTouch方法返回false时:



原因分析:

看源码找到控件的父类View中的dispatchTouchEvent方法
当onTouch返回true时dispatchTouchEvent返回true,响应所有的事件。此时不调用onTouchEvent方法。
当onTouch返回false时将调用onTouchEvent方法,dispatchTouchEvent中的返回值与onTouchEvent的返回值相同,查看onTouchEvent方法知当控件的clickable = false时onTouchEvent返回的返回为false(默认情况下ImageView的clickable = false),即dispatchTouchEvent返回false 不响应所有事件(所有事件指得是按下、滑动、抬起事件)。


此时再给ImageView设置一个点击事件:

	imageView.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {

				Log.e(TAG, "imageView---onClick");
			}
	});



setOnTouchListener回掉的 onTouch方法返回true时




onTouch方法返回false时:



原因分析:


对于onTouch方法的事件分析:

看源码找到控件的父类View中的dispatchTouchEvent方法
当onTouch返回true时dispatchTouchEvent返回true,onTouch方法响应所有的事件
当onTouch返回false时调用onTouchEvent方法,dispatchTouchEvent中的返回值与onTouchEvent的返回值相同(给ImageView设置setOnClickListener事件后其clickable = true)onTouchEvent返回值为true,即dispatchTouchEvent返回true响应所有事件。


对于onClick方法的事件分析:

查看源码知onClick方法是在onTouchEvent方法里面的performClick()方法做的回调
当onTouch返回true时dispatchTouchEvent返回true,不调用onTouchEvent方法,所以不调用onTouchEvent方法里面的performClick()方法,所以不响应onClick事件(可理解成onTouch返回true时事件被onTouch消费掉了不再传递给onClick方法)
当onTouch返回false时调用onTouchEvent方法,调用onTouchEvent方法里面的performClick()方法,所以响应onClick事件

setOnTouchListener回掉的 onTouch方法返回true时
onTouch方法返回false时:

二、对Button进行事件分发分析

点击并滑动Button按钮:
需要注意的是默认情况下Button按钮的clickable = true

其它分析过程同ImageView,请各位看客个自行分析咯。


总结一下:

先给ImageView设置setOnTouchListener、setOnClickListener方法。

当点击并滑动ImageView时,先调用其父类View中的dispatchTouchEvent,此时对dispatchTouchEvent中的条件进行判断,

①当onTouch方法返回true时,dispatchTouchEvent方法直接返回true(因为mOnTouchListener != null 、 (mViewFlags & ENABLED_MASK) == ENABLED方法恒成立)不再调用onTouchEvent方法,此时响应onTouch方法中的所有事件,由于onClick方法是在onTouchEvent方法中的回调所以onClick方法不再执行。

当onTouch方法返回false时,dispatchTouchEvent方法调用onTouchEvent方法并与onTouchEvent的返回值相同,onTouchEvent又回调了performClick()方法,performClick()方法又回调了onClick所以执行onClick方法。在源码中可以看出onTouchEvent的返回值跟控件clickable 的返回值相同,默认情况下ImageView的clickable = false,在设置了setOnClickListener事件后其clickable = true,所以onTouchEvent返回值为true,dispatchTouchEvent的返回值为true,onTouch响应所有事件。


Button的自己总结下哈。

OK,是不是觉得很简单,后面的文章我们将对一些复杂的情况进行分析





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值