Android-View事件处理机制

             又遇到过监听事件无效的情况,然后找了一些资料。在这里做点笔记方便以后忘了复习!


一,先看一段代码:我自定义一个MyButton继承Button,并重写了dispatchTouchEvent(...)方法,onTouchEvent(...)方法

package com.example.getmynumber.view;

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

public class MyButton extends Button{
	
	
	
	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
	}

	public MyButton(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
	}
	
	
	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		switch(event.getAction()){
		   case MotionEvent.ACTION_DOWN:
			   Log.i("wangsongbin", "dispatchTouchEvent:ACTION_DOWN");
			   break;
		   case MotionEvent.ACTION_MOVE:
			   Log.i("wangsongbin", "dispatchTouchEvent:ACTION_MOVE");
			   break;
		   case MotionEvent.ACTION_UP:
			   Log.i("wangsongbin", "dispatchTouchEvent:ACTION_UP");
			   break;
		}
		return super.dispatchTouchEvent(event);
	}
	
	
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		   case MotionEvent.ACTION_DOWN:
			   Log.i("wangsongbin", "onTouchEvent:ACTION_DOWN");
			   break;
		   case MotionEvent.ACTION_MOVE:
			   Log.i("wangsongbin", "onTouchEvent:ACTION_MOVE");
			   break;
		   case MotionEvent.ACTION_UP:
			   Log.i("wangsongbin", "onTouchEvent:ACTION_UP");
			   break;

		}
		return super.onTouchEvent(event);
	}

}
在xml文件中引用

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    

    <com.example.getmynumber.view.MyButton
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="hello touchEvent"/>
    
</RelativeLayout>

在Activity中为其绑定监听器

package com.example.getmynumber.activity.textview;

import com.example.getmynumber.R;
import com.example.getmynumber.view.MyButton;

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;

public class TouchEventTestActivity extends Activity{
	
	private MyButton mButton;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_touchtest);
		mButton=(MyButton) findViewById(R.id.btn);
		mButton.setOnTouchListener(new OnTouchListener() {
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch(event.getAction()){
				   case MotionEvent.ACTION_DOWN:
					   Log.i("wangsongbin", "onTouch:ACTION_DOWN");
					   break;
				   case MotionEvent.ACTION_MOVE:
					   Log.i("wangsongbin", "onTouch:ACTION_MOVE");
					   break;
				   case MotionEvent.ACTION_UP:
					   Log.i("wangsongbin", "onTouch:ACTION_UP");
					   break;
				}
				return false;
			}
		});
	}

}

我适当的擦了一下MyButton控件,结果如下:


可一个看到一个执行顺序:dispatchTouchEvent(...)  ,触摸监听touch(...),onTouchEvent(...)

其实我们看一下View的dispatchTouchEvent(...)的源码就清楚了。

    public boolean dispatchTouchEvent(MotionEvent event) {
        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
        }

        if (onFilterTouchEventForSecurity(event)) {
            //noinspection SimplifiableIfStatement
            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {  //监听器onTouch(...)方法的执行位置
                return true;
            }

            if (onTouchEvent(event)) {  //onTouchEvnent(...)方法的执行位置。
                return true;
            }
        }

        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
        }
        return false;
    }
我们可以很明显的看到监听器的onTouch方法的执行位置在onTouchEvent执行方法的前面。而且我还可以看到,如果li(即控件所有

监听器的封装类)不为null,li.mTouchListener(我们设置的触摸监听)不为null, 控件的状态为Enable,触摸监听的onTouch方法

返回true(即触摸事件被消耗掉),我们的onTouchEvent方法可能执行不了。


二,onClickListener,与onLongClickListener 

在这里我重新为MyButton添加了onClickListener和onLongClickListener监听。然后我手指放下,稍稍等一会再拿起来。

package com.example.getmynumber.activity.textview;

import com.example.getmynumber.R;
import com.example.getmynumber.view.MyButton;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;

public class TouchEventTestActivity extends Activity{
	
	private MyButton mButton;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_touchtest);
		mButton=(MyButton) findViewById(R.id.btn);
		mButton.setOnTouchListener(new OnTouchListener() {
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch(event.getAction()){
				   case MotionEvent.ACTION_DOWN:
					   Log.i("wangsongbin", "onTouch:ACTION_DOWN");
					   break;
				   case MotionEvent.ACTION_MOVE:
					   Log.i("wangsongbin", "onTouch:ACTION_MOVE");
					   break;
				   case MotionEvent.ACTION_UP:
					   Log.i("wangsongbin", "onTouch:ACTION_UP");
					   break;
				}
				return false;
			}
		});
		
		mButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				Log.i("wangsongbin", "onClick:ACTION_UP");
			}
		});
		
		mButton.setOnLongClickListener(new OnLongClickListener() {
			
			@Override
			public boolean onLongClick(View v) {
				Log.i("wangsongbin", "onLongClick:ACTION_UP");
				return false;
			}
		});
	}

}
我特地把Action_MOVE去掉,不然很难看到效果。所以去掉后看到的结果是!


onLongClick方法在Action_Down之后,Action_UP之前就执行了。

这段逻辑在onTouchEvent中:

onLongClick的执行途径:

Action_DWON时会启动一个115ms延迟的任务,如果115后如果还没有触发Action_up,则继续启动一个500-115ms的延迟任务

如果500ms后,则执行onLongClick方法。

onClick的执行途径:

在Action_Dwon是标PrePressed,如果在115~500ms内,触发了Action_up则执行onClick方法。

如果在500ms以后触发了Action_up,

1,onLongClickListener.onLongClick(...)返回true,则不会执行onClickListener.onClick(...),

2,onLongClickListener.onLongClick(...)返回false,则依然会执行onClickListener.onClick(...)






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值