Android中ViewPager带来的滑动卡顿问题解决要点解析

问题说明:
当SwipeRefreshLayout中放置了ViewPager控件,两者的滑动会相互冲突.具体表现为ViewPager的左右滑动不顺畅,容易被SwipeRefreshLayout拦截(即出现刷新的View).

问题原因:
ViewPager本身是处理了滚动事件的冲突,它在横向滑动时会调用requestDisallowInterceptTouchEvent()方法使父控件不拦截当前的Touch事件序列.但是SwipeRefreshLayout的requestDisallowInterceptTouchEvent()方法什么也没有做,所以仍然会拦截当前的Touch事件序列.

问题分析:
为什么SwipeRefreshLayout的requestDisallowInterceptTouchEvent()方法什么都不做?

首先SwipeRefreshLayout继承自ViewGroup.

在requestDisallowInterceptTouchEvent()方法什么都不做的情况下,用户可以从底部下拉刷新一次拉出LoadingView.
如果方法调用ViewGroup的requestDisallowInterceptTouchEvent()方法, 可以解决ViewPager的兼容问题,但是用户在界面底部下拉至头部后,无法继续下拉,需要手指放开一次才能拉出LoadingView.
目标分析:
那么为了更加顺滑地滚动,想要的效果当然是一次性拉出LoadingView.既然ViewPager在左右滑动时才会调用requestDisallowInterceptTouchEvent()方法,那么SwipeRefreshLayout只应该在上下滑动时才拦截Touch事件.

具体逻辑如下:

记录是否调用了requestDisallowInterceptTouchEvent()方法,并且设置为true.
在SwipeRefreshLayout中判断是否是上下滑动.
如果同时满足1,2,则调用super.requestDisallowInterceptTouchEvent(true).
否则调用super.requestDisallowInterceptTouchEvent(false).
注意:因为ViewGroup的requestDisallowInterceptTouchEvent方法设置true后,Touch事件在dispatchTouchEvent()方法中就会被拦截,所以需要在dispatchTouchEvent()方法中判断是否为上下滑动.

实现代码(部分):

//非法按键 private static final int INVALID_POINTER = -1; //dispatch方法记录第一次按下的x private float mInitialDisPatchDownX; //dispatch方法记录第一次按下的y private float mInitialDisPatchDownY; //dispatch方法记录的手指 private int mActiveDispatchPointerId = INVALID_POINTER; //是否请求拦截 private boolean hasRequestDisallowIntercept = false; @Override public void requestDisallowInterceptTouchEvent(boolean b) { hasRequestDisallowIntercept = b; // Nope. } @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mActiveDispatchPointerId = MotionEventCompat.getPointerId(ev, 0); final float initialDownX = getMotionEventX(ev, mActiveDispatchPointerId); if (initialDownX != INVALID_POINTER) { mInitialDisPatchDownX = initialDownX; } final float initialDownY = getMotionEventY(ev, mActiveDispatchPointerId); if (mInitialDisPatchDownY != INVALID_POINTER) { mInitialDisPatchDownY = initialDownY; } break; case MotionEvent.ACTION_MOVE: if (hasRequestDisallowIntercept) { //解决viewPager滑动冲突问题 final float x = getMotionEventX(ev, mActiveDispatchPointerId); final float y = getMotionEventY(ev, mActiveDispatchPointerId); if (mInitialDisPatchDownX != INVALID_POINTER && x != INVALID_POINTER && mInitialDisPatchDownY != INVALID_POINTER && y != INVALID_POINTER) { final float xDiff = Math.abs(x - mInitialDisPatchDownX); final float yDiff = Math.abs(y - mInitialDisPatchDownY); if (xDiff > mTouchSlop && xDiff * 0.7f > yDiff) { //横向滚动不需要拦截 super.requestDisallowInterceptTouchEvent(true); } else { super.requestDisallowInterceptTouchEvent(false); } } else { super.requestDisallowInterceptTouchEvent(false); } } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) { hasRequestDisallowIntercept = false; } break; } return super.dispatchTouchEvent(ev); } private float getMotionEventY(MotionEvent ev, int activePointerId) { final int index = MotionEventCompat.findPointerIndex(ev, activePointerId); if (index < 0) { return -1; } return MotionEventCompat.getY(ev, index); } private float getMotionEventX(MotionEvent ev, int activePointerId) { final int index = MotionEventCompat.findPointerIndex(ev, activePointerId); if (index < 0) { return -1; } return MotionEventCompat.getX(ev, index); }

时间: 2024-10-27 07:28:52

Android中ViewPager带来的滑动卡顿问题解决要点解析的相关文章

Android中ViewPager带来的滑动卡顿问题解决要点解析_Android

问题说明:当SwipeRefreshLayout中放置了ViewPager控件,两者的滑动会相互冲突.具体表现为ViewPager的左右滑动不顺畅,容易被SwipeRefreshLayout拦截(即出现刷新的View). 问题原因:ViewPager本身是处理了滚动事件的冲突,它在横向滑动时会调用requestDisallowInterceptTouchEvent()方法使父控件不拦截当前的Touch事件序列.但是SwipeRefreshLayout的requestDisallowInterce

android webview 滑动-webview中内容滑动卡顿

问题描述 webview中内容滑动卡顿 有谁遇到过webview里面内置的可上下滑动的内容在android中滑动很卡顿的问题不?求解 解决方案 http://tieba.baidu.com/p/3201362042

Android编程开发ScrollView中ViewPager无法正常滑动问题解决方法_Android

本文实例讲述了Android编程开发ScrollView中ViewPager无法正常滑动问题解决方法.分享给大家供大家参考,具体如下: 这里主要介绍如何解决ViewPager在ScrollView中滑动经常失效.无法正常滑动问题. 解决方法只需要在接近水平滚动时ScrollView不处理事件而交由其子View(即这里的ViewPager)处理即可,重写ScrollView的onInterceptTouchEvent函数,如下: package cc.newnews.view; import an

Android编程开发ScrollView中ViewPager无法正常滑动问题解决方法

本文实例讲述了Android编程开发ScrollView中ViewPager无法正常滑动问题解决方法.分享给大家供大家参考,具体如下: 这里主要介绍如何解决ViewPager在ScrollView中滑动经常失效.无法正常滑动问题. 解决方法只需要在接近水平滚动时ScrollView不处理事件而交由其子View(即这里的ViewPager)处理即可,重写ScrollView的onInterceptTouchEvent函数,如下: package cc.newnews.view; import an

Android中ViewPager获取当前显示的Fragment

前言 在项目中,有时会用到在ViewPager中显示同样类型的Fragment,同时这样的Fragment的个数是动态的,但是PagerAdapter没有给我们提供getCurrentFragment类似的方法.下面就给大家介绍下Android中ViewPager获取当前显示的Fragment的方法,一起看看吧. 一.使用 getSupportFragmentManager().findFragmentByTag()方法 Viewpager + FragmentPagerAdapter 情况下

viewpager卡顿-把ViewPager 切换时出现卡顿的问题

问题描述 把ViewPager 切换时出现卡顿的问题 我用的viewpager动态添加了五个view放在list中,每个view对应一个布局文件,比如我现在在其中的一个布局中放了好几个Imageview,然后切换,就会出现很明显的卡断.图片数量少的时候比如只放一个imageview的时候就不会有卡顿!怎么解决?跪求各位大神! 解决方案 分析卡顿的原因 : 1. 布局原因: 布局层次较多,繁琐,每次加载页面的时候,重新初始化布局,浪费时间. 2. 页面缓存机制原因: 不要没次都让ViewPager

优化-ListView需要用imageloader加载大量网络图片滑动卡顿

问题描述 ListView需要用imageloader加载大量网络图片滑动卡顿 需求:类似QQ空间动态功能,每个Item加载头像跟图片还有一些文字. 使用的是UIL来加载图片. 问题:在滑动listview的时候会卡顿,然后加载过的图片再次出现的时候又会重新加载.并不能实现首次下载第二次的时候从内存中加载.PS:每张图片大小在20K以内.网络状态良好. 已尝试方法:优化ImageLoaderConfiguration.设置ListView.setOnScrollListener(new Paus

android中Viewpager中嵌套子viewpager问题

问题描述 android中Viewpager中嵌套子viewpager问题 如上图所示,应用首页一个Viewpager和一个RadioButton组成,而在viewpager中添加四个Fragement,通过滑动或者点击RadioButton可以进行Fragement间的切换,在第一个Fragement中添加了一个3s轮播Viewpager切换图片.现在主要有两个问题希望大家可以帮助到我,谢谢! 问题一:应用刚刚打开默认是打开第一个Fragement,这个时候该fragment中的轮播图正常播放

android-Android RecyclerView滑动卡顿怎么解决?求指点!

问题描述 Android RecyclerView滑动卡顿怎么解决?求指点! 使用recyclerview滑动加载更多会出现卡顿的情况,求大神指导这应该怎么解决! 解决方案 ViewHolder复用一下试试 解决方案二: 楼上的用过recyclerview没,该listview是强制使用的viewholder的.他卡顿不是网络任务多,就是图片多. 解决方案三: 顶一下 ~~~! 顶一下 ~~~! 顶一下 ~~~!