布局文件: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则继续派发给下层控件,