> View和ViewGroup
-- 事件传递的顺序:Activity -> ViewGroup -> View
-- ViewGroup的相关事件有三个:onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent;onClickListener
View的相关事件只有两个:dispatchTouchEvent、onTouchEvent。onClickListener
-- View体系的绘制流程是从ViewRootImpl的performTraversals方法开始的;
View的测量大小流程:performMeasure –> measure –> onMeasure等方法;
View的测量位置流程:performLayout –> layout –> onLayout等方法;
View的绘制流程:performDraw-> draw-> onDraw等方法;
-- ((ViewGroup)getWindow().getDecorView().findViewById(android.R.id.content)).getChildAt(0)这种方式获取Activity所设置的View。这个mDecor显然就是getWindow().getDecorView()返回的View,而我们通过setContentView设置的View是它的一个子View。
dispatchTouchEvent (Activity) ->是否超出Activity所属的Window边界 (Activity) -> superDispatchTouchEvent (Window abstract class) -> superDispatchTouchEvent(PhoneWindow) -> superDispatchTouchEvent(DecorView) -> dispatchTouchEvent(ViewGroup FrameLayout)。
> Android事件分发机制
-- Android事件分发机制主要由“事件分发”—>“事件拦截”—>“事件响应”这三步来进行逻辑控制的。
1. 事件分发:public boolean dispatchTouchEvent(MotionEvent ev)
当监听到有触发事件时,首先由Activity进行捕获,然后事件就进入事件分发的流程。Activity本身没有事件拦截,从而将事件传递给最外层的View的dispatchTouchEvent(MotionEvent ev)方法,该方法将对事件进行分发。
return true : View消费所有事件。
return false :停止分发,交由上层控件的onTouchEvent方法进行消费,如果本层控件是Activity,那么事件将被系统消费、处理。
super.dispatchTouchEvent(ev): 将事件交由本层的事件拦截onInterceptTouchEvent方法处理。
2. 事件拦截:public boolean onInterceptTouchEvent(MotionEvent ev)
return true: 对事件拦截,交由本层的onTouchEvent进行处理。
return false: 不拦截,分发到子View,由子View的dispatchTouchEvent方法处理。
super.onInterceptTouchEvent(ev):默认表示事件拦截,交由本层的onTouchEvent进行处理。
3. 事件响应:public boolean onTouchEvent(MotionEvent ev)
return true: 表示onTouchEvent处理完事件后消费了此次事件。
return false: 不响应事件,不断的传递给上层的onTouchEvent方法处理,直到某个View的onTouchEvent返回true,则认为该事件被消费。如果到最顶层View还是返回false,那么该事件不消费,将交由Activity的onTouchEvent进行处理。
return: super.onTouchEvent,不响应事件,结果与return返回false一样。
-- Android的分发机制:
1.ViewGroup默认不拦截任何事件。
2.点击事件的分发过程如下:dispatchTouchEvent—>onTouchListener的OnTouch方法—>onTouchEvent—>onClickListener的onClick方法。从而也可以看出onTouch优先于onClick执行。
3.子View可以通过使用getParent().requestDisallowInterceptTouchEvent(true),阻止ViewGroup对其MOVE或UP事件进行拦截。
4.一个点击事件产生后,传递过程是:Activity—>Window—>View。顶级View接受到事件后,就会按照上面的规则去分发事件。
> View.java,ViewGroup.java
-- View.java
public boolean dispatchTouchEvent(MotionEvent event)
public boolean onTouchEvent(MotionEvent event)
public class TestButton extends Button {
public TestButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.i("TestButton", "dispatchTouchEvent action = " + event.getAction());
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i("TestButton", "onTouchEvent action = " + event.getAction());
return super.onTouchEvent(event);
}
}
-- ViewGroup.java
public boolean dispatchTouchEvent(MotionEvent event)
public boolean onTouchEvent(MotionEvent event)
public boolean onInterceptTouchEvent(MotionEvent event)
public class TestLinearLayout extends LinearLayout {
public TestLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d("TestLinerLayout", "onInterceptTouchEvent action = " + ev.getAction());
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.d("TestLinerLayout", "dispatchTouchEvent action = " + ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("TestLinerLayout", "onTouchEvent action = " + event.getAction());
return super.onTouchEvent(event);
}
}
> Activity事件分发
public class MainActivity extends Activity {
private RTButton button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
System.out.println("Activity---dispatchTouchEvent---DOWN");
break;
case MotionEvent.ACTION_MOVE:
System.out.println("Activity---dispatchTouchEvent---MOVE");
break;
case MotionEvent.ACTION_UP:
System.out.println("Activity---dispatchTouchEvent---UP");
break;
default:
break;
}
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
System.out.println("Activity---onTouchEvent---DOWN");
break;
case MotionEvent.ACTION_MOVE:
System.out.println("Activity---onTouchEvent---MOVE");
break;
case MotionEvent.ACTION_UP:
System.out.println("Activity---onTouchEvent---UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("MainActivity", "onTouch action = "+event.getAction() + v);
return false;
}
}