转载请标明原文地址:简单灵活解决 Viewgroup嵌套 产生的手势冲突问题
这是接着上一篇Android 下拉刷新上拉加载 多种应用场景 超级大放送(上)的,这里介绍一下怎么 简单灵活解决Viewgroup嵌套产生的手势冲突问题。虽然这里只是以ViewPager为例,但是提供了一种解决此类问题的通用思路。
先来看一下网易新闻客户端的界面效果:
 
上一篇实现的Demo效果图,手势效果响应和上图一样
关于Viewgroup嵌套产生的手势冲突问题主要分为两类:
这里提供一种 解决以上问题的通用方案:
public class SubView1 extends View {
	private static String TAG = SubView1.class.getSimpleName();
	private GestureDetector mGestureDetector;
	private Paint paint = new Paint();
	public SubView1(Context context) {
		super(context);
	}
	public SubView1(Context context, AttributeSet attrs) {
		super(context, attrs);
		// 为mGestureDetector设置监听器
		mGestureDetector = new GestureDetector(context, new MTouchDetector());
		// 保证能触发相应的事件
		setFocusable(true);
		setClickable(true);
		setEnabled(true);
		setLongClickable(true);
	}
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// 指定宽和高
		setMeasuredDimension(600, 200);
		// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}
	@Override
	public void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
		paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
		canvas.drawColor((Color.parseColor("#FFA07A")));
		canvas.drawText("SubView1", 100, 100, paint);
	}
	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		int action = event.getAction();
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			// L.i(TAG, "dispatchTouchEvent ACTION_DOWN");
			break;
		case MotionEvent.ACTION_MOVE:
			// L.i(TAG, "dispatchTouchEvent ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			// L.i(TAG, "dispatchTouchEvent ACTION_UP");
			break;
		default:
			break;
		}
		getParent().requestDisallowInterceptTouchEvent(true); // 先告诉父Viewgroup,不要拦截我我
		mGestureDetector.onTouchEvent(event); // 通过GestureDetector将MotionEvent事件交给监听器OnGestureListener
		return super.dispatchTouchEvent(event);
	}
	class MTouchDetector extends SimpleOnGestureListener {
		// Touch down时触发
		public boolean onDown(MotionEvent e) {
			L.i(TAG, "onDown");
			return super.onDown(e);
		}
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			//tan(60°),手势与垂直方向大于30°,相应子View的onScroll,父Viewgroup的onScroll则不会响应
			if (1.732*Math.abs(distanceX) >= Math.abs(distanceY)) {
				
				L.i(TAG, "不要拦截我");
				getParent().requestDisallowInterceptTouchEvent(true);	// 告诉父Viewgroup不要拦截我,事件我自行处理			
				return true;
				
			} else {
				getParent().requestDisallowInterceptTouchEvent(false);// 告诉父Viewgroup拦截我,响应父Viewgroup的onScroll
				L.i(TAG, "拦截我");
				return false;
			}
		}
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			L.i(TAG, "onFling");
			return super.onFling(e1, e2, velocityX, velocityY);
		}
		// 双击的第二下Touch down时触发
		public boolean onDoubleTap(MotionEvent e) {
			L.i(TAG, "onDoubleTap");
			return super.onDoubleTap(e);
		}
		public boolean onDoubleTapEvent(MotionEvent e) {
			L.i(TAG, "onDoubleTapEvent");
			return super.onDoubleTapEvent(e);
		}
	}
}       再定义父ViewGrouppublic class MLinearLayout extends LinearLayout {
	private static String TAG = MLinearLayout.class.getSimpleName();
	// private static String TAG = SubView1.class.getSimpleName();
	private GestureDetector mGestureDetector;
	@SuppressLint("ClickableViewAccessibility")
	public MLinearLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		mGestureDetector = new GestureDetector(context, new MTouchDetector());
		this.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				return mGestureDetector.onTouchEvent(event);
			}
		});
		setFocusable(true);
		setClickable(true);
		setEnabled(true);
		setLongClickable(true);
	}
	@SuppressLint("NewApi")
	public MLinearLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}
	public MLinearLayout(Context context) {
		super(context);
	}
	class MTouchDetector extends SimpleOnGestureListener {
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			L.i(TAG, "onScroll");
			return true;
		}
	}
	@Override
	public boolean onInterceptTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
	 	mGestureDetector.onTouchEvent(event);
		return false;
	}
}<span style="font-size: 11.9999990463257px; font-family: Arial, Helvetica, sans-serif; background-color: rgb(254, 254, 254);">      </span>/**
 * @author wen_er
 *
 */
public class MyViewPager extends ViewPager {
	private static String TAG = MyViewPager.class.getSimpleName();
	private GestureDetector mGestureDetector;
	public MyViewPager(Context context) {
		super(context);
		mGestureDetector = new GestureDetector(context, new ScrollDetector());
	}
	public MyViewPager(Context context, AttributeSet attrs) {
		super(context, attrs);
		// mGestureDetector = new GestureDetector(context, new
	
	}
	class ScrollDetector extends SimpleOnGestureListener {
		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			if (Math.abs(distanceX) >= Math.abs(distanceY)) {
				getParent().requestDisallowInterceptTouchEvent(true);// 告诉父viewGroup不要拦截我
				return true;
			} else {
				getParent().requestDisallowInterceptTouchEvent(false);// 告诉父viewGroupw拦截我
				return false;
			}
		}
	}
	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		L.i(TAG, "dispatchTouchEvent");
		getParent().requestDisallowInterceptTouchEvent(true);
		mGestureDetector.onTouchEvent(event);
		return super.dispatchTouchEvent(event);
	}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/yalinfendou/article/details/47814519