上一篇给出了测试工程程序,下面要给每一层的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 [email protected] * @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事件.