Android事件传递机制(dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent)
Android中的事件类型分为按键事件和屏幕触摸事件,Touch事件是屏幕触摸事件的基础事件,有必要对它进行深入的了解。
View即普通的控件,没有子布局的,如Button、TextView.
ViewGroup继承自View,表示可以有子控件,如Linearlayout、Listview这些。
事件即MotionEvent,最重要的有3个:
- (1)MotionEvent.ACTION_DOWN 按下View,是所有事件的开始
- (2)MotionEvent.ACTION_MOVE 滑动事件
- (3)MotionEvent.ACTION_UP 与down对应,表示抬起
明确事件传递机制的最终目的都是为了触发执行View的点击监听和触摸监听:
******.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Log.i(tag, "testLinelayout---onClick...");
}
});
*******.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return false;
}
});
我们简称为onClick监听和onTouch监听,一般程序会注册这两个监听。从上面可以看到,onTouch监听里默认return false。不要小看了这个return false,后面可以看到它有大用。
对于View来说,事件传递机制有两个函数:dispatchTouchEvent负责分发事件,在dispatch*里又会调用onTouchEvent表示执行事件,或者说消费事件,
总结
1、事件入口是dispatchTouchEvent(),它会先执行注册的onTouch监听,如果一切顺利的话,接着执行onTouchEvent,在onTouchEvent里会执行onClick监听。
2、无论是dispatchTouchEvent还是onTouchEvent,如果返回true表示这个事件已经被消费、处理了,不再往下传了。在dispathTouchEvent的源码里可以看到,如果onTouchEvent返回了true,那么它也返回true。如果dispatch*在执行onTouch监听的时候,onTouch返回了true,那么它也返回true,这个事件提前被onTouch消费掉了。就不再执行onTouchEvent了,更别说onClick监听了。
3、我们通常在onTouch监听了设置图片一旦被触摸就改变它的背景、透明度之类的,这个onTouch表示事件的时机。而在onClick监听了去具体干某些事。
在自定义的View里面添加再设置一个外加View
再mianActivity中添加进来:
sideBar.setTextView(dialog);
在sideBar中再对他进行设置。
/**
* 在mainActivity中吧TextView设置进来。
* @param mTextDialog
*/
public void setTextView(TextView mTextDialog) {
this.mTextDialog = mTextDialog;
}
在dispatchTouchEvent中对他进行监听和控制。
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
final int action = event.getAction();
final float y = event.getY();// 点击y坐标
final int oldChoose = choose;
final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
final int c = (int) (y / getHeight() * b.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.
switch (action) {
case MotionEvent.ACTION_UP:
setBackgroundDrawable(new ColorDrawable(0x00000000));
choose = -1;//
invalidate();
if (mTextDialog != null) {
mTextDialog.setVisibility(View.INVISIBLE);
}
break;
default:
setBackgroundResource(R.drawable.sidebar_background);
if (oldChoose != c) {
if (c >= 0 && c < b.length) {
if (listener != null) {
listener.onTouchingLetterChanged(b[c]);
}
if (mTextDialog != null) {
mTextDialog.setText(b[c]);
mTextDialog.setVisibility(View.VISIBLE);
}
choose = c;
invalidate();
}
}
break;
}
return true;
}
View.VISIBLE、INVISIBLE、GONE的区别
android中UI应用的开发中经常会使用view.setVisibility()来设置控件的可见性,其中该函数有3个可选值,他们有着不同的含义:
View.VISIBLE—->可见
View.INVISIBLE—->不可见,但这个View仍然会占用在xml文件中所分配的布局空间,不重新layout
View.GONE——>不可见,但这个View在ViewGroup中不保留位置,会重新layout,不再占用空间,那后面的view就会取代他的位置,
invalidate()函数
invalidate()函数的主要作用是请求View树进行重绘,该函数可以由应用程序调用,或者由系统函数间接调用,例如setEnable(), setSelected(), setVisiblity()都会间接调用到invalidate()来请求View树重绘,更新View树的显示。