http://blog.csdn.net/yanbober/article/details/45887547/
【工匠若水 http://blog.csdn.net/yanbober】此博主分析的已经很详细了,我只是借鉴一下。
先把代码贴上:
public class MainActivity extends AppCompatActivity {
private TouchView view;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view = (TouchView) findViewById(R.id.touch_view);
view.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
Log.d("TAG","setOnTouchListener ->"+motionEvent.getAction());
return false;
}
});
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d("TAG","onClick ");
}
});
}
}
mainActivity布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.xxha.xh.viewontouch.MainActivity">
<com.xxha.xh.viewontouch.TouchView
android:id="@+id/touch_view"
android:background="@color/colorAccent"
android:layout_width="100dp"
android:layout_height="100dp"
/>
</RelativeLayout>
自定义的touchView类
/**
* Created by Lm on 2017/10/18.
* Email:1002464056@qq.com
*/
public class TouchView extends View {
public TouchView(Context context) {
super(context);
}
public TouchView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TouchView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("TAG","onTouchEvent ->"+event.getAction());
return super.onTouchEvent(event);
}
}
运行,点击控件,运行结果为
10-18 14:42:51.154 31628-31628/com.xxha.xh.viewontouch D/TAG: setOnTouchListener ->0
10-18 14:42:51.154 31628-31628/com.xxha.xh.viewontouch D/TAG: onTouchEvent ->0
10-18 14:42:51.233 31628-31628/com.xxha.xh.viewontouch D/TAG: setOnTouchListener ->2
10-18 14:42:51.233 31628-31628/com.xxha.xh.viewontouch D/TAG: onTouchEvent ->2
10-18 14:42:51.250 31628-31628/com.xxha.xh.viewontouch D/TAG: setOnTouchListener ->2
10-18 14:42:51.250 31628-31628/com.xxha.xh.viewontouch D/TAG: onTouchEvent ->2
10-18 14:42:51.251 31628-31628/com.xxha.xh.viewontouch D/TAG: setOnTouchListener ->1
10-18 14:42:51.251 31628-31628/com.xxha.xh.viewontouch D/TAG: onTouchEvent ->1
10-18 14:42:51.251 31628-31628/com.xxha.xh.viewontouch D/TAG: onClick
结论:
1. Android控件的Listener事件触发顺序是先触发onTouch,其次onClick。
2. 如果控件的onTouch返回true将会阻止事件继续传递,返回false事件会继续传递。
看一下源码(只贴重点):
public boolean dispatchTouchEvent(MotionEvent event) {
......(只贴重点)
boolean result = false;
......
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}
if (!result && onTouchEvent(event)) {
result = true;
}
}
两个if 方法中 li指的是触摸对象,不为null,li.mOnTouchListener指的是对象设置了OnTouchListener监听,也不为null ,enable指的是控件是否可用(默认可用),最关键的是onTouch(), 如果onTouch返回ture则,if语句执行,反之不执行。
从而推断出触摸程序的执行顺序为 :一触摸就执行dispatchTouchEvent,然后执行 onTouch() 方法。
1.若onTouch为true,则result 为true,继而下面的if (!result && onTouchEvent(event))中,!result为flase了就不会执行onTouchEvent()方法
2.若onTouch为false,则result 为fasle,继而下面的if (!result && onTouchEvent(event))中,!result为true,就会继续执行onTouchEvent(),判断onTouchEvent()的返回值。
再次推断程序的执行顺序为:一触摸就执行dispatchTouchEvent,然后执行 onTouch() 方法,然后执行 onTouchEvent()方法
dispatchTouchEvent()方法分析完后没有看到onClick()方法在哪里执行的,也就是说onclick()应该与onTouchEvent有关系。
直接给出结论不再具体分析:
1. onTouchEvent方法中会在ACTION_UP分支中触发onClick的监听。
2. 当dispatchTouchEvent在进行事件分发的时候,只有前一个action返回true,才会触发下一个action。
时间太仓促,来不及写了,大体执行过程就是这样。
综合得出Android View的触摸屏事件传递机制有如下特征:
- 触摸控件(View)首先执行dispatchTouchEvent方法。
- 在dispatchTouchEvent方法中先执行onTouch方法,后执行onClick方法(onClick方法在onTouchEvent中执行,下面会分析)。
- 如果控件(View)的onTouch返回false或者mOnTouchListener为null(控件没有设置setOnTouchListener方法)或者控件不是enable的情况下会调运onTouchEvent,dispatchTouchEvent返回值与onTouchEvent返回一样。
- 如果控件不是enable的设置了onTouch方法也不会执行,只能通过重写控件的onTouchEvent方法处理(上面已经处理分析了),dispatchTouchEvent返回值与onTouchEvent返回一样。
- 如果控件(View)是enable且onTouch返回true情况下,dispatchTouchEvent直接返回true,不会调用onTouchEvent方法。
- 当dispatchTouchEvent在进行事件分发的时候,只有前一个action返回true,才会触发下一个action(也就是说dispatchTouchEvent返回true才会进行下一次action派发)。