UI 10: Touch事件分发

2024-06-17  本文已影响0人  xqiiitan

1. 自定义View的套路

1.1 自定义属性,获取自定义属性(达到可配置的效果)
1.2 onMeasure() 方法,用于测量计算自己的宽高;
继承自View要实现;如果是继承系统已有的TextView,Button,系统已经实现好了onMeasure 计算好了宽高。
1.3 onDraw() 用于绘制自己的显示;
1.4 onTouch() 用于与用户交互。

2. 自定义ViewGroup的套路

2.1 自定义属性,获取自定义属性(用的较少);
2.2 onMeasure()方法,for循环测量子view,根据子view的宽高来计算自己的宽高;
2.3 onDraw()方法,一般不需要,默认不会调用。如果要绘制,需要实现dispatchDraw() 方法.
2.4 onLayout()方法,用来摆放子view,前提是可见非GONE状态。
2.5 大部分情况下,不会继承自ViewGroup;
往往是继承 系统已经提供好的 ViewGroup,如ViewPager、RelativeLayout、ScrollView。
不要管onLayout()方法,


3. onTouch 源码分析

3.1 打印touch事件的顺序:setOnTouchListener、onTouchEvent、onClickListener 三个都设置了。
前提是onTouchListener 返回false;

  1. 首先执行,Activity中 setOnTouchListener 的onTouch事件;
  2. 然后执行了,TouchView中的 onTouchEvent事件。

OnTouchListener.DOWN -> onTouchEvent.DOWN -> OnTouchListener.MOVE -> onTouchEvent.MOVE
-> OnTouchListener.UP -> onTouchEvent.UP -> OnClickListener()

3.2 前提是onTouchListener 返回true;
OnTouchListener.DOWN -> OnTouchListener.MOVE -> OnTouchListener.UP


4. View 与 Touch相关的重要方法

dispatchTouchEvent(MotionEvent event) 做事件分发。

boolean result = false;
ListenerInfo li = mListenerInfo;  // ListenerInfo 存放了关于View 的所有Listener信息(OnClickListener/OnScrollChangeListener... )
if (li != null && li.mOnTouchListener != null
        && (mViewFlags & ENABLED_MASK) == ENABLED // 是否是Enable
        && li.mOnTouchListener.onTouch(this, event)) { // 如果onTouch 返回的false,result=false; 如果是true,result也就是true。
    result = true;
}
if (!result && onTouchEvent(event)) { // 如果result=false,就会执行onTouch事件;如果result=true,就不会执行onTouch事件。
    result = true;
}

return result; // 返回。

onTouchEvent()方法,一般都会被覆写。

onTouchEvent:: DOWN
setPressed(true, x, y)/ checkForLongClick/

case MotionEvent.ACTION_UP:
performClickInternal()-- performClick()
li.mOnClickListener.onClick(this); 调用点击事件。点击事件,在View的onTouchEvent-> ACTION_UP里面。

现象1:当Activity 不添加setOnTouchListener;
TouchView的onTouchEvent 返回true;
只执行onTouchEvent的事件(action: 0 2 1【onTouchEvent.DOWN-> onTouchEvent.MOVE-> onTouchEvent.UP】),不会执行onCLick事件。
因为直接返回的true,没有执行 super.onTouchEvent(event), 让View.onTouchEvent(event) 得到执行。所以不会执行onClick事件。

现象2:当Activity 添加setOnTouchListener;TouchView 添加dispatchTouchEvent 返回true。
事件都不会执行。代表需要 消费所有的事件。

View 是没有 interceptTouchEvent, 打断事件方法。ViewGroup 才有事件的分发和拦截。
每个View,先调用自己的 dispatchTouchEvent();
然后调用 super.dispatchTouchEvent()
在调用自己的onTouchEvent(), super.onTouchEvent()

View的按下效果,setPressed(false) 效果取消。


上一篇 下一篇

猜你喜欢

热点阅读