Android View touch事件传递方式规律
2015-12-23 10:24
666 查看
上一篇给出了测试工程程序,下面要给每一层的Button添加click事件处理.
这里需要以DurianSubFrameLayout这一层进行,因为这一层刚好是一个中间层,可谓"上有老下有小"
DurianSubFrameLayout.java的代码调整一下:
/**
* @Title: DurianSubFrameLayout.java
* @Package com.durian.view
* @Description: TODO
* @author zhibao.liu from durian organization
* @date 2015-12-22 下午02:47:13
* @version V1.0
*/
package com.durian.view;
import com.durian.viewgroup.R;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.Toast;
/**
* @ClassName: DurianSubFrameLayout
* @Description: TODO
* @author zhibao.liu Freelancer
* @email warden_sprite@foxmail.com
* @date 2015-12-22 下午02:47:13
*
*/
public class DurianSubFrameLayout extends FrameLayout {
private final static String TAG = "DurianSubFrameLayout";
private int mDisplayWidth = 1200;
private int mDisplayHeight = 1824;
private Button mButton;
private Context mContext;
private DurianSubLinearLayout mDurianSubLinearLayout;
public DurianSubFrameLayout(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
initView(context);
}
public DurianSubFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
initView(context);
}
public DurianSubFrameLayout(Context context) {
super(context);
// TODO Auto-generated constructor stub
initView(context);
}
private void initView(Context context) {
mContext=context;
mButton = new Button(context);
mButton.setText("Second SubFrameLayout Button");
mButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(mContext, TAG+" button !", Toast.LENGTH_SHORT).show();
Log.i(TAG,"Third SubFrameLayout button click");
}
});
addView(mButton);
mDurianSubLinearLayout = new DurianSubLinearLayout(context);
addView(mDurianSubLinearLayout);
setBackgroundDrawable(context.getResources().getDrawable(
R.drawable.alpha_background));
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
Log.i(TAG, TAG+ " onTouchEvent");
return super.onTouchEvent(event);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
// TODO Auto-generated method stub
super.onLayout(changed, left, top, right, bottom);
for (int i = 0; i < getChildCount(); i++) {
Log.i(TAG, "*** count i : " + i);
View child = getChildAt(i);
if (child instanceof Button) {
child.layout(mDisplayWidth / 2 - 250, i * mDisplayHeight / 12,
mDisplayWidth / 2 + 250, (i + 1) * mDisplayHeight / 12);
} else {
child.layout(0, i * mDisplayHeight / 12, mDisplayWidth, (i + 1)
* mDisplayHeight / 6);
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(mDisplayWidth, mDisplayHeight / 4);
}
}
首先不分析程序,先给出我分析的结论,然后再看程序验证,如果有错误还请修正,非常感谢
下面用一个表格大致显示如下:
好了现在我在DurianSubFrameLayout.java容器中,修改dispatchTouchEvent方法的返回值:
运行程序,多次点击:
从上面看没有onTouch的报文出来,可想而知,事件在进入这个容器时被阻止,那么这个容器的子容器的touch事件也不会响应了.
然后将上面同样设置成返回false,效果和上面一样
然后将上面恢复,并且设置返回true:
运行查看log :
会发现这个容器消费了touch事件,那么意味着什么呢?这个容器里面的子Button和下一级子布局容器均在不会相应touch事件了.所以点击button和自布局里面的button都不会有响应,但是这个容器的touch事件是可以响应的.
在修改一下:
运行结果,并且点击当前布局和下一级自布局:
sublinear是下一级的子布局log信息.
综合上述,可以发现结论基本上是正确的,但是有一个地方需要注意,
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
Log.i(TAG, TAG+ " onTouchEvent");
return super.onTouchEvent(event);
}
在这个里面,无论返回true 还是 false,里面的log都会执行,也就是说onTouchEvent里面的程序一定会执行.返回true还是false只是针对事件传递的,是对下一级的约束,不会因为这个地方返回true或者false导致里面程序不执行.但是一般很多情况下如果这个里面有自己的程序,我们一般会自己在自己程序后面增加一行return true,为了防止下一级的touch事件导致UI显示混乱.
对于其他的按键KeyEvent事件也是类似的,所以如果你的主容器由多层layout叠加,比如3层,那么希望触摸的时候,相应的是第二次或者第三层,那么根据上面的结论,开发人员应该知道如何调整事件传递路线,从而达到第二层或者第三层去相应Event事件.
这里需要以DurianSubFrameLayout这一层进行,因为这一层刚好是一个中间层,可谓"上有老下有小"
DurianSubFrameLayout.java的代码调整一下:
/**
* @Title: DurianSubFrameLayout.java
* @Package com.durian.view
* @Description: TODO
* @author zhibao.liu from durian organization
* @date 2015-12-22 下午02:47:13
* @version V1.0
*/
package com.durian.view;
import com.durian.viewgroup.R;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.Toast;
/**
* @ClassName: DurianSubFrameLayout
* @Description: TODO
* @author zhibao.liu Freelancer
* @email warden_sprite@foxmail.com
* @date 2015-12-22 下午02:47:13
*
*/
public class DurianSubFrameLayout extends FrameLayout {
private final static String TAG = "DurianSubFrameLayout";
private int mDisplayWidth = 1200;
private int mDisplayHeight = 1824;
private Button mButton;
private Context mContext;
private DurianSubLinearLayout mDurianSubLinearLayout;
public DurianSubFrameLayout(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
initView(context);
}
public DurianSubFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
initView(context);
}
public DurianSubFrameLayout(Context context) {
super(context);
// TODO Auto-generated constructor stub
initView(context);
}
private void initView(Context context) {
mContext=context;
mButton = new Button(context);
mButton.setText("Second SubFrameLayout Button");
mButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(mContext, TAG+" button !", Toast.LENGTH_SHORT).show();
Log.i(TAG,"Third SubFrameLayout button click");
}
});
addView(mButton);
mDurianSubLinearLayout = new DurianSubLinearLayout(context);
addView(mDurianSubLinearLayout);
setBackgroundDrawable(context.getResources().getDrawable(
R.drawable.alpha_background));
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
Log.i(TAG, TAG+ " onTouchEvent");
return super.onTouchEvent(event);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
// TODO Auto-generated method stub
super.onLayout(changed, left, top, right, bottom);
for (int i = 0; i < getChildCount(); i++) {
Log.i(TAG, "*** count i : " + i);
View child = getChildAt(i);
if (child instanceof Button) {
child.layout(mDisplayWidth / 2 - 250, i * mDisplayHeight / 12,
mDisplayWidth / 2 + 250, (i + 1) * mDisplayHeight / 12);
} else {
child.layout(0, i * mDisplayHeight / 12, mDisplayWidth, (i + 1)
* mDisplayHeight / 6);
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(mDisplayWidth, mDisplayHeight / 4);
}
}
首先不分析程序,先给出我分析的结论,然后再看程序验证,如果有错误还请修正,非常感谢
下面用一个表格大致显示如下:
好了现在我在DurianSubFrameLayout.java容器中,修改dispatchTouchEvent方法的返回值:
@Override public boolean dispatchTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub return true;//super.dispatchTouchEvent(ev); }
运行程序,多次点击:
从上面看没有onTouch的报文出来,可想而知,事件在进入这个容器时被阻止,那么这个容器的子容器的touch事件也不会响应了.
然后将上面同样设置成返回false,效果和上面一样
然后将上面恢复,并且设置返回true:
@Override public boolean dispatchTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub return true;//super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub Log.i(TAG, TAG+ " onTouchEvent"); return super.onTouchEvent(event); }
运行查看log :
会发现这个容器消费了touch事件,那么意味着什么呢?这个容器里面的子Button和下一级子布局容器均在不会相应touch事件了.所以点击button和自布局里面的button都不会有响应,但是这个容器的touch事件是可以响应的.
在修改一下:
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub return false;//super.onInterceptTouchEvent(ev); }
运行结果,并且点击当前布局和下一级自布局:
sublinear是下一级的子布局log信息.
综合上述,可以发现结论基本上是正确的,但是有一个地方需要注意,
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
Log.i(TAG, TAG+ " onTouchEvent");
return super.onTouchEvent(event);
}
在这个里面,无论返回true 还是 false,里面的log都会执行,也就是说onTouchEvent里面的程序一定会执行.返回true还是false只是针对事件传递的,是对下一级的约束,不会因为这个地方返回true或者false导致里面程序不执行.但是一般很多情况下如果这个里面有自己的程序,我们一般会自己在自己程序后面增加一行return true,为了防止下一级的touch事件导致UI显示混乱.
对于其他的按键KeyEvent事件也是类似的,所以如果你的主容器由多层layout叠加,比如3层,那么希望触摸的时候,相应的是第二次或者第三层,那么根据上面的结论,开发人员应该知道如何调整事件传递路线,从而达到第二层或者第三层去相应Event事件.
相关文章推荐
- [置顶] Android selector设置详解
- android的锁屏解锁
- android状态栏一体化
- Android解析json数组对象的方法及Apply和数组的三个技巧
- Android各种访问权限Permission详解
- [置顶] Java、Android、IOS通用的加密解密方法
- dc学习之基于Android Studio的jni开发总结
- Android学习路线指南
- Android编程下拉菜单spinner用法小结(附2则示例)
- Android实现截屏并保存操作功能
- android 之控件篇
- Android监测程序压入后台及从后台返回
- Android library中为什么不能使用switch-case语句访问资源ID
- Android随手笔记44之JSON数据解析
- Android 开始
- 记一次Android下载过程的内存优化
- Android中类ListPreference使用介绍
- Android之双指操作
- android小知识
- Android学习笔记45之gson解析json