布局文件:GroupView继承了FrameLayout,其中层叠了两个View
<com.example.textdemo.view.DTGroupView
android:id="@+id/dTGroupView1"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.textdemo.view.DTView
android:id="@+id/dTView1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.example.textdemo.view.DTView1
android:id="@+id/dTView2"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.example.textdemo.view.DTGroupView>
public class DTGroupView extends FrameLayout{
public DTGroupView(Context context) {
super(context);
}
public DTGroupView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DTGroupView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.i("dt", "group+++dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.i("dt", "group+++onInterceptTouchEvent");
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i("dt", "group+++onTouchEvent");
return super.onTouchEvent(event);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Log.i("dt", "group+++onLayout");
getChildAt(0).layout(l, t, r, b);
getChildAt(1).layout(l, t, r, b);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.i("dt", "group+++onMeasure");
getChildAt(0).measure(widthMeasureSpec, heightMeasureSpec);
getChildAt(1).measure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i("dt", "group+++onDraw");
}
}
先研究一下绘图方法,日志如下:
03-07 11:15:41.032 4975 4975 I dt : DTView+++onMeasure
03-07 11:15:41.032 4975 4975 I dt : DTView1+++onMeasure
03-07 11:15:41.032 4975 4975 I dt : group+++onMeasure
03-07 11:15:41.032 4975 4975 I dt : DTView+++onMeasure
03-07 11:15:41.032 4975 4975 I dt : DTView1+++onMeasure
03-07 11:15:41.035 4975 4975 I dt : group+++onLayout
03-07 11:15:41.035 4975 4975 I dt : DTView+++onLayout
03-07 11:15:41.035 4975 4975 I dt : DTView1+++onLayout
03-07 11:15:41.054 4975 4975 I dt : DTView+++onDraw
03-07 11:15:41.055 4975 4975 I dt : DTView1+++onDraw
对比代码我们很好理解,Measure测量方法,从ViewGroup中getChildAt(0)开始测量,然后测量完控件之后,测量ViewGroup本身(多出的测量方法是由于我在代码中调用了一次),Layout布局方法是从最下层空间逐级往上执行。
03-07 11:16:38.609 4975 4975 I dt : group+++dispatchTouchEvent
03-07 11:16:38.611 4975 4975 I dt : group+++onInterceptTouchEvent
03-07 11:16:38.614 4975 4975 I dt : DTView1+++dispatchTouchEvent
03-07 11:16:38.615 4975 4975 I dt : DTView1+++onTouchEvent
03-07 11:16:38.615 4975 4975 I dt : DTView+++dispatchTouchEvent
03-07 11:16:38.615 4975 4975 I dt : DTView+++onTouchEvent
03-07 11:16:38.616 4975 4975 I dt : group+++onTouchEvent
触摸事件分发机制:首先理解ViewGroup包含dispatch/intercept/onTouchEvent,而View只包含dispatch/onTouchEvent;看日志,dispatch最先执行,然后是onIntercept,如果没有被打断,才继续派发给子控件,子控件最上层首先接收事件,执行dispatch然后onTouch,然后如果返回false则继续派发给下层控件,