HorizontalScrollView及ScrollView解决滑动冲突

本文介绍了解决Android中ScrollView滑动冲突的方法,包括禁止ScrollView滑动及通过重写onInterceptTouchEvent方法实现事件传递,同时提供了HorizontalScrollView手势拦截的具体实现案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、在很多的形情之下,用到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;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值