滑动冲突问题,触摸事件拦截处理

最近遇到了几个关于滑动冲突的问题。问题的具体表现为:

  1. ScrollView里嵌套了一个垂直的ListView或者RecycleView会出现滑动卡顿的问题。问题的原因是ScrollView的滑动事件与子View(ListView或者RecycleView)的滑动发生了冲突。

解决的方法是写一个自定义ScrollView拦截子View的滑动事件。自定义ScrollView代码见下:

public class MyScrollView extends ScrollView {
    public MyScrollView(Context context) {
        super(context);
    }

public MyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

@Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

return true;
    }
}

  1. 这种情况下的另一种问题是ListView的setSecletion()方法会被ScrollView屏蔽,导致ListView无法实现跳到指定Item。

解决的办法可以是:计算指定item到顶部的距离,调用scrollTo(x,y)方法滑到指定位置,比较复杂。

  1. ScrollView里嵌套了一个水平的ListView或者RecycleView也会出现滑动卡顿或者划不动的问题。原因和1是一样的。

解决办法也是写一个自定义ScrollView,判断滑动的意图是垂直滑动还是水平滑动:

public class MyScrollView extends ScrollView {
    public MyScrollView(Context context) {
        super(context);
    }

    public MyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private int x, y;

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN://按下y
                x = (int) ev.getX();
                y = (int) ev.getY();
                break;
            case MotionEvent.ACTION_MOVE://移动
                int new_x = (int) ev.getX();
                int new_y = (int) ev.getY();

                //判断有水平滑动的意向
                int move_x = Math.abs(new_x - x);//x轴滑动的距离
                int move_y = Math.abs(new_y - y);//y轴滑动的距离
                if (move_x > (move_y + 10))//10的偏移量
                {
                    return false;//传递给字View
                }
//                //判断有上下滑动的意向(用于字VIew是上下,parent是水平的)
//                int move_x = Math.abs(new_x - x);//x轴滑动的距离
//                int move_y = Math.abs(new_y - y);//y轴滑动的距离
//                if (move_y > (move_x + 10))//10的偏移量
//                {
//                    return false;
//                }

                break;
        }

        return super.onInterceptTouchEvent(ev);
    }
}

利用事件拦截可以解决很多Bug,也可以实现很酷炫的功能,如https://github.com/SingleShadowBlade/ScrollDemo.git

这是一个ListView的Item可以水平滑动,并且和titlebar同步滑动的效果,也可以斜着滑

关于事件拦截的原理可以看:http://www.apkbus.com/blog-820900-61403.html

时间: 2024-08-03 11:55:07

滑动冲突问题,触摸事件拦截处理的相关文章

Android ViewGroup触摸事件拦截详解

前言 在自定义ViewGroup中,有时候需要实现触摸事件拦截,比如ListView下拉刷新就是典型的触摸事件拦截的例子.触摸事件拦截就是在触摸事件被parent view拦截,而不会分发给其child,即使触摸发生在该child身上.被拦截的事件会转到parent view的onTouchEvent方法中进行处理.但是这个交互过程还是挺复杂的,有多种情况,今天我们就来分析一下吧.这篇分析文章已经放了一段时间了,如果有任何问题请高人指出. 触摸事件的分发 简单来说触摸事件的分发会经过这么几个顺序

从ScrollView嵌套EditText的滑动事件冲突分析触摸事件的分发机制以及TextView的简要实现和冲突的解决办法

本篇文章假设读者没有任何的触摸事件基础知识,所以我们会从最基本的触摸事件分发处说起. ScrollView为什么会出现嵌套EditText出现滑动事件冲突呢?相信你会有这种疑问,我们来看这么一种情况: 有一个固定高度的EditText,假设它只能显示3行文本,但是,我们在其中输入的文本多余三行时,那么这时就需要可以在EditText内部进行小幅滚动了.那么将这个EditText放入了ScrollView当中, 并且ScrollView内容过多以致ScrollView也可以滑动,这时候就会出现Ed

使用NestedScrollView+ViewPager+RecyclerView+SmartRefreshLayout打造酷炫下拉视差效果并解决各种滑动冲突

使用NestedScrollView+ViewPager+RecyclerView+SmartRefreshLayout打造酷炫下拉视差效果并解决各种冲突 如果你还在为处理滑动冲突而发愁,那么你需要静下心来看看这边文章,如果你能彻底理解这篇文章中使用的技术,那么,一切滑动冲突的问题解决起来就轻而易举了:先扔一个最终实现的效果图 先分析下效果图中实现的功能点 顶部下拉时背景图形成视差效果 上拉时标题栏透明切换显示 底部实现TabLayout+ViewPager+Fragment+RecyclerV

自定义控件(视图)2期笔记12:View的滑动冲突之 外部拦截法

1. 外部拦截法: 点击事件通过父容器拦截处理,如果父容器需要就拦截,不需要就不拦截. 2. 下面通过一个Demo示例说明: (1)首先我们创建一个Android工程,如下: (2)我们来到activity_main.xml,如下: 1 <com.himi.viewconflict.ui.RevealLayout 2 xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="htt

自定义控件(视图)2期笔记13:View的滑动冲突之 内部拦截法

1. 内部拦截法: 父容器不拦截事件,所有的事件全部都传递给子元素,如果子元素需要此事件就直接消耗掉,否则就交给父容器进行处理. 这种方法和Android中的事件分发机制不一样,需要配合requestDisallowInterceptTouchEvent方法才能正常工作,使用起来较外部拦截法稍显负责一点. 我们需要重写子元素的dispatchTouchEvent方法. 这种方法的伪代码是: 1 @Override 2 public boolean dispatchTouchEvent(Motio

【滑动冲突】常见情形及解决方案

安卓开发过程中滑动冲突的情形主要有2类: 父view与子view的滑动方向不同,如:父view左右滑动,子view上下滑动或相反(ViewPage里面嵌套ListView).这种情形是比较简单的,只需要根据不同的滑动动作进行相应的拦截与处理即可. 父view与子view的滑动方向相同,即,父view左右,子view也左右(ViewPage里面嵌套可以缩放.移动的ImageView).这种情形需要根据具体情况来进行拦截处理,比如父View在出现子View滑动到边缘的情况才进行拦截处理. 滑动冲突解

Android中TouchEvent触摸事件机制

当我们的手指在Android屏幕上点击或滑动时,就会触发触摸事件TouchEvent.在App中ViewGroup和View存在多级嵌套,在最外层的是Activity,最内层的View,介于Activity与View之间的是一些ViewGroup.本文为了简化讨论,我们假设一个Activity中只有一个ViewGroup,这个ViewGroup中只有一个View.当我们用手指触摸到View的UI时,就会产生触摸事件TouchEvent,总的过程如下图所示: 首先是最外层的Activity接收到该

Android ViewGroup 触摸事件传递机制

引言 上一篇博客我们学习了Android View 触摸事件传递机制,不了解的同学可以查看Android View 触摸事件传递机制.今天继续学习Android触摸事件传递机制,这篇博客将和大家一起探讨ViewGroup的触摸事件传递机制. 示例 示例代码如下: public class MainActivity extends ActionBarActivity { private String TAG = "MainActivity"; private MyViewGroup pa

Android触摸事件分发

Android的触摸分发机制和如何实现拦截 Android的触摸分发机制和如何实现拦截 前言 触摸事件的分发 情景分析 总结 前言 在自定义ViewGroup中,有时候需要实现触摸事件拦截,比如ListView下拉刷新就是典型的触摸事件拦截的例子.触摸事件拦截就是在触摸事件被parent view拦截,而不会分发给其child,即使触摸发生在该child身上.被拦截的事件会转到parent view的onTouchEvent方法中进行处理.但是这个交互过程还是挺复杂的,有多种情况,今天我们就来分