@ZeroGeek
2016-09-22T11:54:53.000000Z
字数 4834
阅读 609
android
View可以监听交互事件(触碰,点击等),当View与ViewGroup之间重叠时,Android系统是怎么处理这些事件的呢?本文主要分析ACTION_DOWN事件(常用的有ACTION_UP,ACTION_MOVE等)在View之间的传递,涉及下面3个方法:
(代码附录在最后,迫不及待来分析吧)自定义了个LogButton,作为View这类。LogLinearLayout,作为ViewGroup这类,加上Activity,全部重写dispatchTouchEvent,onTouchEvent,onInterceptTouchEvent,并捕获ACTION_DOWN和ACTION_UP事件,输出log。布局就是把一个LogButton放入一个LogLinearLayout中。然后在Activity中监听onTouch事件。
首先自定义个LogButton,作为View这类
public class LogButton extends Button {
private static final String TAG = "LogButton";
public LogButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(MainActivity.MY_TAG, TAG+" onTouchEvent :ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.d(MainActivity.MY_TAG, TAG+" onTouchEvent :ACTION_UP");
break;
}
// 注意这里默认是true。
return true;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(MainActivity.MY_TAG, TAG+" dispatchTouchEvent :ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.d(MainActivity.MY_TAG, TAG+" dispatchTouchEvent :ACTION_UP");
break;
}
return super.dispatchTouchEvent(ev);
}
}
然后定义个LogLinearLayout,作为ViewGroup这类
public class LogLinearLayout extends LinearLayout {
private static final String TAG = "LogLinearLayout";
public LogLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(MainActivity.MY_TAG, TAG+" onTouchEvent :ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.d(MainActivity.MY_TAG, TAG+" onTouchEvent :ACTION_UP");
break;
}
// 这里默认是super.onTouchEvent(event)
return super.onTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(MainActivity.MY_TAG, TAG+" onInterceptTouchEvent :ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.d(MainActivity.MY_TAG, TAG+" onInterceptTouchEvent :ACTION_UP");
break;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(MainActivity.MY_TAG, TAG+" dispatchTouchEvent :ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.d(MainActivity.MY_TAG, TAG+" dispatchTouchEvent :ACTION_UP");
break;
}
return super.dispatchTouchEvent(ev);
}
}
主界面,其实是Activity类实现了Window的一个Callback接口,里面包含这2个方法。
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
public static final String MY_TAG = "zero";
private LogButton btn;
private LogLinearLayout ly;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (LogButton) findViewById(R.id.log_btn);
ly = (LogLinearLayout) findViewById(R.id.log_ly);
btn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(MainActivity.MY_TAG, TAG+" btn onTouch :ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.d(MainActivity.MY_TAG, TAG+" btn onTouch :ACTION_UP");
break;
}
return false;
}
});
ly.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(MainActivity.MY_TAG, TAG+" layout onTouch :ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.d(MainActivity.MY_TAG, TAG+" layout onTouch :ACTION_UP");
break;
}
return false;
}
});
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(MainActivity.MY_TAG, TAG+" dispatchTouchEvent :ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.d(MainActivity.MY_TAG, TAG+" dispatchTouchEvent :ACTION_UP");
break;
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(MainActivity.MY_TAG, TAG+" onTouchEvent :ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.d(MainActivity.MY_TAG, TAG+" onTouchEvent :ACTION_UP");
break;
}
return super.onTouchEvent(event);
}
}
布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.zero.eventdemo.MainActivity">
<com.zero.eventdemo.LogLinearLayout
android:id="@+id/log_ly"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.zero.eventdemo.LogButton
android:id="@+id/log_btn"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="log button"/>
</com.zero.eventdemo.LogLinearLayout>
</LinearLayout>