一、在很多的形情之下,用到ScrollView的必定会遇到滑动冲突。
解决方法有可以把ScrollView的滑动设为禁止:
//禁止scrollview 的滑动 scrollView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { return true; } });这样ScrollView的滑动功能就会失效。
但这只是表面上的在整个view的传递中,Touch事件还是会被ScrollView或者HorizontalScrollView所消费掉。ScrollView或HorizontalScrollView包裹的子view就不会接收到Touch事件。所以在子view中无法进行其他关于Touch事件的操作。
要解决事件传递,创建一个HorizontalScrollView或ScrollView的子类继承其全部功能,在这基础上重写onInterceptTouchEvent()方法,把返回值直接置为false。则Touch事件就会经由控件基础上传递到包裹的子view中。等view消费了事件之后则解决了这个ScrollView不往下传事件的问题:
** * @author wangyao * @package * @date 2017/8/2 15:58 * @describe 用于解决HorizontalScrollView横向滑动的拦截的问题 * @project */ public class MyHorizontalScrollView extends HorizontalScrollView { public MyHorizontalScrollView(Context context) { super(context); } public MyHorizontalScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public MyHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent ev) { return true; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return false; } }
二、
1、在事件的传递中经常用到的三个方法是:dispatchTouchEvent():事件是否往下(子view)去分发;onInterceptTouchEvent():事件的拦截,事件是否在这里拦截或者是往下传递;onTouchEvent():事件的消费处理,如此为止消费掉则一个事件的过程完毕。
2、一个事件是先由父View->子View往下传的;
3、如所有的子View的onTouchEvent()都不消费,这个事件再由子View逐层传给父View这要看onTouchEvent()方法去不去消费事件;
三、进行HorizontalScrollView手势的拦截的demo:
需求:在HorizontalScrollView中进行双指滑动HorizontalScrollView跟随着手势滑动,单指滑动的事件自己不处理,留给其子view进行手势的处理。
思想:在自定义MyHorizontalScrollView中的onInterceptTouchEvent()的方法里进行处理事件拦截的条件。
代码:
package com.example.administrator.canvasdemo.view; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.HorizontalScrollView; /** * @author wangyao * @package com.example.administrator.canvasdemo.view * @date 2017/8/29 20:31 * @describe TODO * @project */ public class MyHorizintalScrollView extends HorizontalScrollView { private boolean isDragCanvsMode; private boolean isDoubleDrag = false; private float mStartDownX; private float mStartDownY; private float mMoveDragCanvsX; private float mMoveDragCanvsY; public MyHorizintalScrollView(Context context) { super(context); } public MyHorizintalScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public MyHorizintalScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onTouchEvent(MotionEvent event) { //多点拖动的操作 switch (event.getAction()&MotionEvent.ACTION_MASK){ case MotionEvent.ACTION_DOWN:{ // Log.i("everb","按下去:"+mStartDownX); } break; case MotionEvent.ACTION_POINTER_DOWN:{ isDoubleDrag = true; } break; case MotionEvent.ACTION_MOVE:{ // Log.i("everb", "canvas scrollview onTouchEvent:" + event.getX() + " " + event.getY() + " event.getAction(): " + event.getAction()+ " isDoubleDrag:"+isDoubleDrag); mMoveDragCanvsX = event.getX(); Log.i("everb","move的值:"+mMoveDragCanvsX); float canvsMoveX = mMoveDragCanvsX - mStartDownX; Log.i("everb","移动的值:"+canvsMoveX); //双指滑动的距离进行双指滑动HorizontalScrollView也进行随手势滑动 this.scrollBy(-(int)canvsMoveX,0); } break; case MotionEvent.ACTION_CANCEL:{ isDoubleDrag = false; // Log.i("everb", "canvas scrollview onTouchEvent:ACTION_CANCEL"); } break; } mStartDownX=mMoveDragCanvsX; return false; } @Override public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction()&MotionEvent.ACTION_MASK){ case MotionEvent.ACTION_DOWN:{ mStartDownX = event.getX(); isDragCanvsMode=false; } break; case MotionEvent.ACTION_POINTER_DOWN:{ //多指按下的识别 isDragCanvsMode=true; } break; } // Log.i("everb","canvas scrollview onInterceptTouchEvent:"+event.getX()+" "+event.getY() + " event.getAction()"+event.getAction()); if(isDragCanvsMode == false){ //如单指按下则事件不拦截,把事件传递到子view中 return false; } // Log.i("everb","canvas scrollview onInterceptTouchEvent:"+event.getX()+" "+event.getY() + " event.getAction()"+event.getAction()); //如是双指按下则返回true,把事件拦截在自己的onTouchEvent进行处理 return true; } }