Android 事件传递机制TextView,ImageView等没有默认clickable属性的View单独设置onTouch事件注意事项

本文讲解TextView,ImageView等没有默认clickable属性的View单独设置onTouch事件


Android 事件传递机制:Android 事件传递机制初涉


我们知道 Button,TextView 等控件的基类都是View。只要你触摸到了任何一个控件,就一定会调用该控件的dispatchTouchEvent方法。那当我们去触摸TextView的时候,底层就会去调用TextView类(实际上是基类View)里的dispatchTouchEvent方法,所以接下来看View源码中dispatchTouchEvent()方法的具体实现。


dispatchTouchEvent()方法源码:

public boolean dispatchTouchEvent(MotionEvent event) {    
  
    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&    
  
            mOnTouchListener.onTouch(this, event)) {    
  
        return true;  //事件不往下传递  
  
    }    
  
    return onTouchEvent(event);    
  
} 


分析上述代码,第2行 如果三个条件都为真的话,就返回true,否则执行onTouchEvent。

先看第一个条件:mOnTouchListener!=null,这个条件就是如果设置了OnTouchListener就会为true,否则是false。


第二个条件(mViewFlags & ENABLED_MASK) == ENABLED是判断当前点击的控件是否是enable的,按钮默认都是enable的,因此这个条件恒定为true。


第三个条件就比较复杂了,mOnTouchListener.onTouch(this, event),这个其实就是去回调控件注册touch事件时的onTouch方法。也就是说如果我们在onTouch方法里返回true,就会让这三个条件全部成立,从而整个方法直接返回true。如果我们在onTouch方法里返回false,就会再去执行onTouchEvent(event)方法。



TexView设置触摸事件demo


布局:

<?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">

    <TextView
        android:id="@+id/activity_motionevent_textview"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:background="#FF0000"
        android:textColor="#FFFFFF"
        android:text="Android 自定义View之MotionEvent方法详解"/>

</RelativeLayout>



Java代码:

public class MotionEventActivity extends AppCompatActivity {

    private TextView textView;
    private int lastX;
    private int lastY;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_motionevent);
        textView= (TextView) findViewById(R.id.activity_motionevent_textview);
        textView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                int action=motionEvent.getAction();
                int x= (int) motionEvent.getX();
                int y= (int) motionEvent.getY();
                switch(action){
                    case MotionEvent.ACTION_DOWN://按下
                        lastX=x;
                        lastY=y;
                        Log.d("TAG", "按下坐标----:("+lastX+","+lastY+")");
                        break;
                    case MotionEvent.ACTION_MOVE://移动
                        float offsetX=x-lastX;
                        float offsetY=y-lastY;
                        Log.d("TAG", "移动X轴位移量offsetX----:"+offsetX);
                        Log.d("TAG", "移动X轴位移量offsetY----:"+offsetY);
                        break;
                    case MotionEvent.ACTION_UP://抬起
                        Log.d("TAG", "抬起坐标----:("+x+","+y+")");
                        break;
                }
                return false;
            }
        });
    }

}


结果:


即此时TextView按下无论如何移动TextView只打印按下动作,移动和抬起动作不执行。这是因为只设置了TextView的触摸事件OnTouchListener,而TextView默认是不可点击的,所以按照dispatchTouchEvent源码返回false执行return onTouchEvent(event);



修改布局文件

<?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">

<TextView
    android:id="@+id/activity_motionevent_textview"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:clickable="true"
    android:layout_centerInParent="true"
    android:gravity="center"
    android:background="#FF0000"
    android:textColor="#FFFFFF"
    android:text="Android 自定义View之MotionEvent方法详解"/>

</RelativeLayout>

即为TextView添加android:clickable="true" Java代码不变

结果:



此时 按下 移动 抬起 动作全部执行。 

猜你喜欢

转载自blog.csdn.net/weixin_37730482/article/details/80662153