当前位置: 首页 > news >正文

如何禁止内部viewPager滑动

众所周知,viewPager是能够滑动的,但有时候我们需要禁止它的滑动(微笑地面对*—……—*)。

情况是这样的:

activity中有一个viewPager,viewPager中加入3个Fragment,第三个Fragment中又使用了一个viewPager,这个viewPager中又加入了几个Fragment(本人不是受虐狂,仅仅是功能需要)。如图:

想实现的功能:

点击activity的图标或者滑动的时候能够切换第一个viewPager中的Fragment,点击Fragment3中的图标能够切换第二个viewPager里的Fragment,但是禁止这个viewPager滑动第二个viewPager里的Fragment1里面有一个listView(有下拉刷新功能),要能够上下滑动不受影响。

关键就是禁止内部viewPager滑动,但是其它的功能不受影响。

呵呵,已经元气大伤......

探索过程已经不想吐槽。

 

这个问题涉及到事件的分发机制,需要重写viewPager。那么到底该重写哪个viewPager呢?

首先分析一下这个问题的解决过程:

1.要禁止里面的viewPager左右滑动,那么即是说当我们左右滑动的时候,外面的viewPager要拦截事件,当我们上下滑动的时候外面的viewPager不能拦截事件,这样事件才能传递到内部的viewPager,内部viewPager里的fragment包含的listView才能上下滑动。

2.当然点击事件也不能够拦截,这样点击Fragment3的图标才能切换内部viewPager里面的Fragment。

3.由于内部viewPager在Fragment3,所以我们在外部的viewPager切换到item3的时候再做1,2步的处理。

 

在这里重写外部viewPager会比较方便,即我们用外部拦截法。

接下来请看外部拦截神功。

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import neo.door.usermanager.UserManager;

public class MyViewPager extends ViewPager {
    private int mFirstX =0,mFirstY=0;
    private String TAG = "MyViewPager";

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if(this.getCurrentItem()==2) //如果滑动到了第三个Fragment
        {
            boolean isIntercept=false;
            int x=(int) event.getX();
            int y=(int) event.getY();
            Log.e(TAG, "onInterceptTouchEvent");
            switch (event.getAction()) {
/**
    * 父容器必须返回false,即不拦截ACTION_DOWN事件,
    * 否则后续的ACTION_MOVE,ACTION_UP事件都会直接交给父容器处理,
    * 事件没办法再传递给子元素了
    */
case MotionEvent.ACTION_DOWN:
Log.e(TAG,
"onInterceptTouchEvent_ACTION_DOWN"); isIntercept=false;
break;
/**
     * 根据需要觉定是否拦截
     */
case MotionEvent.ACTION_MOVE: if (Math.abs(x - mFirstX) > Math.abs(y - mFirstY)) //左右滑动 { isIntercept = true; if(正在下拉) //想刷新时候(若不写这一步,如果我们向下滑到一半突然左右滑动那么listView就会卡在中间状态不动。) isIntercept=false; } else //上下滑动 { isIntercept = false; } Log.e(TAG, "onInterceptTouchEvent_ACTION_MOVE"); break;
/**
     * 必须返回false,因为ACTION_UP本身没有太大意义。
 * 
     */
case MotionEvent.ACTION_UP: isIntercept=false; Log.e(TAG, "onInterceptTouchEvent_ACTION_UP"); break; default: break; } mFirstX=x; mFirstY=y; Log.e(TAG, "onInterceptTouchEvent_return"); return isIntercept; } else //如果没有滑动到了第三个Fragment,不作处理 return super.onInterceptTouchEvent(event); } }

首先要知道 onInterceptTouchEvent这个方法,返回true代表拦截,返回false代表不拦截。

注意:

1.ACTION_UP。

考虑一种情况:若是事件交给子元素处理,而父容器在ACTION_UP的时候返回了true,那么子元素就会无法收到ACTION_UP事件,子元素的onClik事件无法触发,也就是说在这道题中,Fragment3的图标将无法点击,并且listView的滑动会在手指离开屏幕的时候停留在中间态。

父容器比较特殊,一旦它开始拦截任何一个事件,那么后续事件都会交给它处理,ACTION_UP作为最后一个事件也一样可以传递给父容器,即便父容器的onInterceptTouchEvent方法在ACTION_UP时返回了false。

2.ACTION_MOVE之中。

假如我们要刷新listView,在我们下拉listView的时候手指突然间左滑或者右滑,那么listView就会停留在中间状态。放开手也不会回去,为什么呢?

原因是这样的:在我们手指下滑的时候,在ACTION_MOVE中判断后不符合 (Math.abs(x - mFirstX) > Math.abs(y - mFirstY)),所以父容器即外部的viewPager返回false,不拦截事件,listView能够滑动。但是当我们在下滑的时候突然间左右滑,那么在ACTION_MOVE中判断后符合 (Math.abs(x - mFirstX) > Math.abs(y - mFirstY)),所以父容器即外部的viewPager返回true,拦截了事件,所以listView无法完成事件,只是停留在了手指左右滑动之前的那个瞬间状态。(这种情况最后的ACTION_UP没有执行,这点还不理解)

所以我们要加个判断,判断listview是否正要下拉刷新,如果是,不要拦截事件。

至于判断方法挺多的,就不再写。

【写到这里,也就差不多了,以后若是有得补充再来补充吧。@—^—@】

转载于:https://www.cnblogs.com/tangZH/p/5934144.html

相关文章:

  • ADO.NET 2.0 - 如何使用 DataView 来筛选数据
  • Sony DV的CCD也是有问题的
  • CakePHP中文手册【翻译】-请求处理组件
  • Itemplate自定义模板列
  • 委托的例子
  • 收藏
  • Linux的发行版及其不同发行版直接的联系与区别
  • 关于qq被盗问题.....
  • 实验五 利用三层交换机实现VLAN间路由
  • 去除开机自启动我的文档
  • 当阳光洒在脸上
  • KeyShot中的环境光遮蔽该怎么进行使用
  • Asp组件龙卷风缩略图水印组件开发
  • [Android Studio 权威教程]断点调试和高级调试
  • Java 专业人士必备的书籍和网站列表
  • 【腾讯Bugly干货分享】从0到1打造直播 App
  • Angular Elements 及其运作原理
  • CAP理论的例子讲解
  • django开发-定时任务的使用
  • Effective Java 笔记(一)
  • es6--symbol
  • go append函数以及写入
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • Java 实战开发之spring、logback配置及chrome开发神器(六)
  • Java反射-动态类加载和重新加载
  • js正则,这点儿就够用了
  • Linux Process Manage
  • Lsb图片隐写
  • Lucene解析 - 基本概念
  • passportjs 源码分析
  • react 代码优化(一) ——事件处理
  • Redis 中的布隆过滤器
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • 计算机在识别图像时“看到”了什么?
  • 技术:超级实用的电脑小技巧
  • 聊聊hikari连接池的leakDetectionThreshold
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 前嗅ForeSpider中数据浏览界面介绍
  • 人脸识别最新开发经验demo
  • 小程序开发中的那些坑
  • 走向全栈之MongoDB的使用
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • #、%和$符号在OGNL表达式中经常出现
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (二)springcloud实战之config配置中心
  • (二开)Flink 修改源码拓展 SQL 语法
  • (分类)KNN算法- 参数调优
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (未解决)macOS matplotlib 中文是方框
  • . NET自动找可写目录
  • .“空心村”成因分析及解决对策122344
  • .bat批处理(二):%0 %1——给批处理脚本传递参数
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法