1.View的事件分发两个重要方法
1.1.dispatchTouchEvent
1.2.onTouchEvent
2.通过上述两个方法阅读源码
2.1.View的dispatchTouchEvent源码
/**
* Pass the touch screen motion event down to the target view, or this
* view if it is the target.
*
* @param event The motion event to be dispatched.
* @return True if the event was handled by the view, false otherwise.
*/
public boolean dispatchTouchEvent(MotionEvent event) {
...
boolean result = false;
if (onFilterTouchEventForSecurity(event)) {
if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
result = true;
}
//1.ListenerInfo存放所有listen的信息,如OnTouchListener,onClickListener等
ListenerInfo li = mListenerInfo;
/**
* 2.返回result为true条件
* 1.ListenerInfo不为空
* 2.onTouchListener不为空
* 3.(mViewFlags & ENABLED_MASK) == ENABLED 表示View的enable为true
* 4.onTouchListener.onTouch为true
*/
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}
/**
* 3.返回result为true条件
* 1.result为false时
* 2.onTouchEvent返回true
*/
if (!result && onTouchEvent(event)) {
result = true;
}
}
...
return result;
}
由源码可知:
1.当调用View的dispatchTouchEvent的时候,首先会查看ListenerInfo信息。通过ListenerInfo可知View的事件执行
2.当onTouchListener.onTouch返回true时,result为true,此时就不会执行onTouchEvent方法。
3.当onTouchListener.onTouch返回false时,result为false,此时执行onTouchEvent方法。
通过代码测试
1.布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".twelve.ScalableActivity">
<com.yc.drawdashboard.touch.TouchView
android:id="@+id/touchview"
android:layout_width="200dp"
android:layout_height="200dp"
android:background="@color/colorPrimary"/>
</LinearLayout>
2.自定义一个TouchView,重写dispatchTouchEvent,onTouchEvent
public class TouchView extends View {
public TouchView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("TAG","onTouchEvent----"+event.getAction());
return super.onTouchEvent(event);
}
}
3.主页面代码,添加onTouchListener,onClickListener
public class ScalableActivity extends AppCompatActivity {
private TouchView mTouchView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scalable);
mTouchView = findViewById(R.id.touchview);
//添加onTouchListener,onTouch返回默认false
mTouchView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.e("TAG","onTouch----"+event.getAction());
return false;
}
});
//添加onClickListener
mTouchView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("TAG","onClick");
Toast.makeText(ScalableActivity.this,"onClick",Toast.LENGTH_SHORT).show();
}
});
}
}
第一种情况:
当View的dispatchTouchEvent,onTouchListener.onTouch,onTouchEvent,onClickListener时,都返回默认值时
执行顺序:
dispatchTouchEvent按下
onTouch按下
onTouchEvent按下
dispatchTouchEvent移动
onTouch移动
onTouchEvent移动
dispatchTouchEvent抬起
onTouch抬起
onTouchEvent抬起
onClick
动画效果:
image_one.gif第二种情况:
当View的dispatchTouchEvent,onTouchListener.onTouch,onTouchEvent,onClickListener返回默认值时,只有dispatchTouchEvent去掉super.dispatchTouchEvent(event),直接返回true或false,其他都不变
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.e("TAG","dispatchTouchEvent----"+event.getAction());
return true; //或者false
}
执行顺序:
dispatchTouchEvent按下
dispatchTouchEvent移动
dispatchTouchEvent抬起
动画效果:
第三种情况:
当View的dispatchTouchEvent,onTouchListener.onTouch,onTouchEvent,onClickListener返回默认时,只有onTouchListener.onTouch返回true,其他都不变
//添加onTouchListener,onTouch返回默认false
mTouchView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.e("TAG","onTouch----"+event.getAction());
return true;
}
});
执行顺序:
dispatchTouchEvent按下
onTouch按下
dispatchTouchEvent移动
onTouch移动
dispatchTouchEvent抬起
onTouch抬起
不执行onTouchEvent和onClickListener
动画效果:
第四种情况
当View的dispatchTouchEvent,onTouchListener.onTouch,onTouchEvent,onClickListener返回默认时,只有onTouchEvent返回true,其他都不变
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("TAG","onTouchEvent----"+event.getAction());
return true;
}
执行顺序:
dispatchTouchEvent按下
onTouch按下
onTouchEvent按下
dispatchTouchEvent移动
onTouch移动
onTouchEvent移动
dispatchTouchEvent抬起
onTouch抬起
onTouchEvent抬起
不执行onClickListener
动画效果:
第五种情况:
当有onTouchListener.onTouch,onTouchEvent,onClickListener时,onTouch返回false,onTouchEvent返回false,其他都不变
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("TAG","onTouchEvent----"+event.getAction());
return false;
}
执行顺序:
dispatchTouchEvent按下
onTouch按下
onTouchEvent按下
后续手指移动,手指抬起等所有事件都不执行
动画效果:
第七种情况:
当有onTouchListener.onTouch,onTouchEvent,onClickListener时,onTouch返回false,onTouchEvent调用super.onTouchEvent(event),并且返回false,其他都不变
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("TAG","onTouchEvent----"+event.getAction());
super.onTouchEvent(event);
return false;
}
执行顺序:
dispatchTouchEvent按下
onTouch按下
onTouchEvent按下
后续手指移动,手指抬起等所有事件都不执行
动画效果:
第八种情况:
当有onTouchListener.onTouch,onTouchEvent,onClickListener时,onTouch返回false,onTouchEvent调用super.onTouchEvent(event),并且返回false,其他都不变
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("TAG","onTouchEvent----"+event.getAction());
super.onTouchEvent(event);
return true;
}
执行顺序:
dispatchTouchEvent按下
onTouch按下
onTouchEvent按下
dispatchTouchEvent移动
onTouch移动
onTouchEvent移动
dispatchTouchEvent抬起
onTouch抬起
onTouchEvent抬起
onClick
动画效果:
第九种情况:
当有onTouchListener.onTouch,onTouchEvent,onClickListener时,onTouch返回false,onTouchEvent调用super.onTouchEvent(event),ACTION_DOWN(按下事件)返回false,ACTION_MOVE,ACTION_UP返回true,其他都不变
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("TAG","onTouchEvent----"+event.getAction());
super.onTouchEvent(event);
boolean result = false;
switch (event.getAction()){
case MotionEvent.ACTION_DOWN: //按下事件返回false
result = false;
break;
case MotionEvent.ACTION_MOVE:
result = true;
break;
case MotionEvent.ACTION_UP:
result = true;
break;
}
return result;
}
}
执行顺序:
dispatchTouchEvent按下
onTouch按下
onTouchEvent按下
后续手指移动,手指抬起等所有事件都不执行
动画效果:
第十种情况:
当有onTouchListener.onTouch,onTouchEvent,onClickListener时,onTouch返回false,onTouchEvent调用super.onTouchEvent(event),ACTION_DOWN(按下事件)返回true,ACTION_MOVE,ACTION_UP返回false,其他都不变
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("TAG","onTouchEvent----"+event.getAction());
super.onTouchEvent(event);
boolean result = false;
switch (event.getAction()){
case MotionEvent.ACTION_DOWN: //按下事件返回true
result = true;
break;
case MotionEvent.ACTION_MOVE:
result = false;
break;
case MotionEvent.ACTION_UP:
result = false;
break;
}
return result;
}
}
执行顺序:
dispatchTouchEvent按下
onTouch按下
onTouchEvent按下
dispatchTouchEvent移动
onTouch移动
onTouchEvent移动
dispatchTouchEvent抬起
onTouch抬起
onTouchEvent抬起
onClick
动画效果:
3.总结:View的dispatchTouchEvent,onTouchListener.onTouch,onTouchEvent,onClickListener之间的关系。
结合源码和上述测试结果可知:
1.调用onTouchListener.onTouch的前提下,View的dispatchTouchEvent必须调用super.dispatchTouchEvent。
2.调用onTouchEvent的前提下,View的onTouchListen.onTouch必须返回false并且enable属性为false。
3.调用onClickListener的前提下,View的onTouchEvent必须调用super.onTouchEvent(event)并且ACTION_DOWN必须返回true。
网友评论