View类很复杂,到今天自己都没有勇气去看,先从事件分发开始吧
题外话,外面调用虽然一样,但是下面源码其实每个版本的实现都是不一样的。
具体代码可以见https://github.com/2954722256/demo_event
大体内容描述:
有1个Activity, 3个相关继承的View (2个是继承LinearLayout的ViewGroup, 1个是Button,也就是单纯的View)
这3个类之间没有继承关系,只是想表达在layout中的嵌套团系
ViewGroup,我们大体知道是 组合模式 的树形结构,ViewGroup可以添加ViewGroup和View, View本身是不能添加View的
文件大体结构:
R.layout.activity_main:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:color/background_light" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.aohuan.test.dodoevent.view.TouchEventFather
android:layout_width="300dp"
android:layout_height="300dp"
android:background="#468AD7"
android:layout_centerHorizontal="true"
android:orientation="vertical"
android:id="@+id/father">
<com.aohuan.test.dodoevent.view.TouchEventChilds
android:id="@+id/childs"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_margin="50dp"
android:layout_gravity="center_horizontal"
android:background="#E1110D">
<com.aohuan.test.dodoevent.view.TouchEventChilds2
android:id="@+id/childs2"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_margin="50dp" />
</com.aohuan.test.dodoevent.view.TouchEventChilds>
</com.aohuan.test.dodoevent.view.TouchEventFather>
</RelativeLayout>
<com.aohuan.test.dodoevent.view.EventButton
android:id="@+id/testBtn"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_margin="50dp"
/>
<com.aohuan.test.dodoevent.view.EventViewGroup
android:id="@+id/testLl"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_margin="50dp"
android:background="@android:color/darker_gray"
/>
</RelativeLayout>
MainActivity:
package com.aohuan.test.dodoevent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import com.aohuan.test.dodoevent.tools.TouchEventUtil;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ((ViewGroup)this.getWindow().getDecorView().getRootView()).getChildAt(0).setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// TouchEventUtil.doClick(MainActivity.class);
// }
// });
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
TouchEventUtil.logActionMsg(getClass(),"onTouchEvent",ev);
return super.onTouchEvent(ev);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
TouchEventUtil.logActionMsg(getClass(),"dispatchTouchEvent",ev);
return super.dispatchTouchEvent(ev);
}
}
EventButton:
package com.aohuan.test.dodoevent.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Button;
import com.aohuan.test.dodoevent.tools.TouchEventUtil;
public class EventButton extends Button{
public EventButton(Context context) {
super(context);
}
public EventButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EventButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
TouchEventUtil.logActionMsg(getClass(),"onTouchEvent",ev);
return super.onTouchEvent(ev);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
TouchEventUtil.logActionMsg(getClass(),"dispatchTouchEvent",ev);
return super.dispatchTouchEvent(ev);
}
}
EventViewGroup
package com.aohuan.test.dodoevent.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import com.aohuan.test.dodoevent.tools.TouchEventUtil;
public class EventViewGroup extends LinearLayout{
public EventViewGroup(Context context) {
super(context);
}
public EventViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EventViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
TouchEventUtil.logActionMsg(getClass(),"onTouchEvent",ev);
return super.onTouchEvent(ev);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
TouchEventUtil.logActionMsg(getClass(),"dispatchTouchEvent",ev);
return super.dispatchTouchEvent(ev);
}
}
TouchEventFather:
package com.aohuan.test.dodoevent.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import com.aohuan.test.dodoevent.tools.TouchEventUtil;
public class TouchEventFather extends LinearLayout {
private final Context mContext;
public TouchEventFather(Context context) {
super(context);
this.mContext = context;
}
public TouchEventFather(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
// this.setOnClickListener(new OnClickListener() {
// @Override
// public void onClick(View v) {
// TouchEventUtil.doClick(TouchEventFather.class);
// }
// });
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
TouchEventUtil.logActionMsg(getClass(),"dispatchTouchEvent",ev);
return super.dispatchTouchEvent(ev);
// return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
TouchEventUtil.logActionMsg(getClass(),"onInterceptTouchEvent",ev);
return super.onInterceptTouchEvent(ev);
// return true;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
TouchEventUtil.logActionMsg(getClass(),"onTouchEvent",ev);
return super.onTouchEvent(ev);
}
}
TouchEventChilds:
package com.aohuan.test.dodoevent.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import com.aohuan.test.dodoevent.tools.TouchEventUtil;
public class TouchEventChilds extends LinearLayout {
private final Context mContext;
public TouchEventChilds(Context context) {
super(context);
this.mContext = context;
}
public TouchEventChilds(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
// this.setClickable(false);
// this.setOnClickListener(new OnClickListener() {
// @Override
// public void onClick(View v) {
// TouchEventUtil.doClick(TouchEventChilds.class);
// }
// });
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
TouchEventUtil.logActionMsg(getClass(),"onInterceptTouchEvent",ev);
return super.onInterceptTouchEvent(ev);
// return true;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
TouchEventUtil.logActionMsg(getClass(),"dispatchTouchEvent",ev);
return super.dispatchTouchEvent(ev);
// return true;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
TouchEventUtil.logActionMsg(getClass(),"onTouchEvent",ev);
return super.onTouchEvent(ev);
}
}
TouchEventChilds2:
package com.aohuan.test.dodoevent.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import com.aohuan.test.dodoevent.tools.TouchEventUtil;
public class TouchEventChilds2 extends Button {
Context mContext;
public TouchEventChilds2(Context context) {
super(context);
this.mContext = context;
}
public TouchEventChilds2(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
// this.setClickable(false);
// this.setOnClickListener(new OnClickListener() {
// @Override
// public void onClick(View v) {
// TouchEventUtil.doClick(TouchEventChilds2.class);
// }
// });
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
TouchEventUtil.logActionMsg(getClass(),"dispatchTouchEvent",ev);
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
TouchEventUtil.logActionMsg(getClass(),"onTouchEvent",ev);
return super.onTouchEvent(ev);
}
}
TouchEventUtil:(打印的帮助类,简单过滤MotionEvent的种类)
package com.aohuan.test.dodoevent.tools;
import android.util.Log;
import android.view.MotionEvent;
public class TouchEventUtil {
public static void logActionMsg(Class cls, String functionName, MotionEvent ev) {
logActionMsg(cls, functionName, ev, "noMsg");
}
enum LogType {
Down, Up, Move, All
}
static LogType mLogType = LogType.Down;
public static void logActionMsg(Class cls, String functionName, MotionEvent ev, String msg) {
switch (mLogType) {
case Down:
if (ev.getAction() == MotionEvent.ACTION_DOWN)
doPrint(cls, functionName, ev, msg);
break;
case Up:
if (ev.getAction() == MotionEvent.ACTION_UP)
doPrint(cls, functionName, ev, msg);
break;
case Move:
if (ev.getAction() == MotionEvent.ACTION_MOVE)
doPrint(cls, functionName, ev, msg);
break;
case All:
doPrint(cls, functionName, ev, msg);
break;
default:
break;
}
}
private static void doPrint(Class cls, String functionName, MotionEvent ev, String msg) {
Log.e("touch", cls.getSimpleName() + "\t----\t" + functionName + "\t---->\t" + getTouchAction(ev.getAction()) + "\t---->\t" + msg);
}
private static String getTouchAction(int actionId) {
String actionName = "Unknow:id=" + actionId;
switch (actionId) {
case MotionEvent.ACTION_DOWN:
actionName = "ACTION_DOWN";
break;
case MotionEvent.ACTION_MOVE:
actionName = "ACTION_MOVE";
break;
case MotionEvent.ACTION_UP:
actionName = "ACTION_UP";
break;
case MotionEvent.ACTION_CANCEL:
actionName = "ACTION_CANCEL";
break;
case MotionEvent.ACTION_OUTSIDE:
actionName = "ACTION_OUTSIDE";
break;
}
return actionName;
}
public static void doClick(Class cls){
Log.e("【click】", cls.getSimpleName() + " is clicked!!");
}
}
下一篇我们可以了解dispatchTouchEvent事件分发浅析(二)分发