您的位置:首页 > 移动开发 > Android开发

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方法的返回值:

@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事件.


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: