首先,为了避免滑动冲突,我们要继承ViewFlow,重写onInterceptTouchEvent

 public class MyViewFlow extends ViewFlow {
private ViewPager mPager; public MyViewFlow(Context context, AttributeSet attrs) {
super(context, attrs);
} public void setViewPager(ViewPager viewPager) {
mPager = viewPager;
} @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mPager != null)
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mPager.requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
mPager.requestDisallowInterceptTouchEvent(false);
break;
case MotionEvent.ACTION_CANCEL:
mPager.requestDisallowInterceptTouchEvent(false);
break;
case MotionEvent.ACTION_MOVE:
mPager.requestDisallowInterceptTouchEvent(true);
break;
}
return super.onInterceptTouchEvent(ev);
}
}

调用setViewPager指定viewPager后,滑动便不再冲突

接下来,我们实现无限循环滚动

 public class AdapterBanner extends BaseAdapter {

     private LayoutInflater mInflater;
private static final int[] ids = { R.drawable.banner, R.drawable.banner, R.drawable.banner, R.drawable.banner}; public AdapterBanner(Context context) {
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
} @Override
public int getCount() {
//return ids.length;
return Integer.MAX_VALUE;//返回很大的值使得getView中的position不断增大来实现循环
} @Override
public Object getItem(int position) {
return position;
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item_fr_acmain_nearby_banner, null);
}
convertView.findViewById(R.id.imgView).setBackgroundResource(ids[position%ids.length]);
return convertView;
} }

关键代码在第13行和31行的红色部分。不过这样实现之后,和CircleFlowIndicator结合使用,会发现程序ANR(无响应),原因是CircleFlowIndicator会调用ViewFlow.getViewCount()来绘制圆点,显然这个数是Integer.MAX_VALUE,圆点数太多了导致ANR,我们需要继续扩展MyViewFlow的getViewCount()。如下。

     private int mCount;
public void setCount(int count){
mCount=count;
}
@Override
public int getViewsCount() {
return mCount;
}

需要调用MyViewFlow.setCount(int count)指定真实的数目,这样做了之后,发现程序不会ANR了。CircleFlowIndicator绘制的圆点数目也正常。但是会发现,无论怎么滑动,圆点状态都不变化,分析ViewFlow的源码,发现要重写一下onScrollChanged,我们继续扩展MyViewFlow,代码如下。

     private int mLastIndex;
@Override
public void setAdapter(Adapter adapter, int initialPosition){
super.setAdapter(adapter,initialPosition);
mLastIndex = initialPosition;
} @Override
protected void onScrollChanged(int h, int v, int oldh, int oldv) {
//super.onScrollChanged(h, v, oldh, oldv);
if (mIndicator != null) {
/*
* The actual horizontal scroll origin does typically not match the
* perceived one. Therefore, we need to calculate the perceived
* horizontal scroll origin here, since we use a view buffer.
*/
int hPerceived = h + (mCurrentAdapterIndex%mCount - mCurrentBufferIndex)
* getChildWidth(); if(mLastIndex%mCount==mCount-1 && mCurrentAdapterIndex>mLastIndex) {
oldh=0;
hPerceived = 0;
}
if(mLastIndex%mCount==0&&mCurrentAdapterIndex<mLastIndex)
hPerceived=h+(mCount-1-mCurrentBufferIndex)*getChildWidth(); LogUtil.e(Config.MYTAG,"mCurrentAdapterIndex="+mCurrentAdapterIndex);
LogUtil.e(Config.MYTAG,"mLastIndex="+mLastIndex);
LogUtil.e(Config.MYTAG, "hPerceived=" + hPerceived); mIndicator.onScrolled(hPerceived, v, oldh, oldv); mLastIndex=mCurrentAdapterIndex;
}
} 

当然,有几个变量mIndicator,mCurrentAdapterIndex,mCurrentBufferIndex是沿用父类ViewFlow的,如果找不到,需要将父类ViewFlow中这些变量改为public即可(虽然从oop角度,这种做法很脏,但很省事,大半夜码文字很累,我很懒)。

至此,大功告成!

整体MyViewFlow代码如下:

package common.control.viewflow;

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Adapter; import com.xxx.android.main.Config; import common.util.LogUtil; public class MyViewFlow extends ViewFlow {
private ViewPager mPager; public MyViewFlow(Context context, AttributeSet attrs) {
super(context, attrs);
} public void setViewPager(ViewPager viewPager) {
mPager = viewPager;
} @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mPager != null)
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mPager.requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
mPager.requestDisallowInterceptTouchEvent(false);
break;
case MotionEvent.ACTION_CANCEL:
mPager.requestDisallowInterceptTouchEvent(false);
break;
case MotionEvent.ACTION_MOVE:
mPager.requestDisallowInterceptTouchEvent(true);
break;
}
return super.onInterceptTouchEvent(ev);
}
private int mCount;
public void setCount(int count){
mCount=count;
}
@Override
public int getViewsCount() {
return mCount;
}
private int mLastIndex;
@Override
public void setAdapter(Adapter adapter, int initialPosition){
super.setAdapter(adapter,initialPosition);
mLastIndex = initialPosition;
} @Override
protected void onScrollChanged(int h, int v, int oldh, int oldv) {
//super.onScrollChanged(h, v, oldh, oldv);
if (mIndicator != null) {
/*
* The actual horizontal scroll origin does typically not match the
* perceived one. Therefore, we need to calculate the perceived
* horizontal scroll origin here, since we use a view buffer.
*/
int hPerceived = h + (mCurrentAdapterIndex%mCount - mCurrentBufferIndex)
* getChildWidth(); if(mLastIndex%mCount==mCount-1 && mCurrentAdapterIndex>mLastIndex) {
oldh=0;
hPerceived = 0;
}
if(mLastIndex%mCount==0&&mCurrentAdapterIndex<mLastIndex)
hPerceived=h+(mCount-1-mCurrentBufferIndex)*getChildWidth(); LogUtil.e(Config.MYTAG,"mCurrentAdapterIndex="+mCurrentAdapterIndex);
LogUtil.e(Config.MYTAG,"mLastIndex="+mLastIndex);
LogUtil.e(Config.MYTAG, "hPerceived=" + hPerceived); mIndicator.onScrolled(hPerceived, v, oldh, oldv); mLastIndex=mCurrentAdapterIndex;
}
}
}

自动播放就不用讲了,网上很多。同学们如果有收获,记得回赞。

扩展ViewFlow避免和ViewPager滑动冲突,同时支持无限循环,并完美和CircleFlowIndicator结合的更多相关文章

  1. (转)ViewPager,ScrollView 嵌套ViewPager滑动冲突解决

    ViewPager,ScrollView 嵌套ViewPager滑动冲突解决 本篇主要讲解一下几个问题 粗略地介绍一下View的事件分发机制 解决事件滑动冲突的思路及方法 ScrollView 里面嵌 ...

  2. PullToRefreshListView中嵌套ViewPager滑动冲突的解决

    PullToRefreshListView中嵌套ViewPager滑动冲突的解决 最近恰好遇到PullToRefreshListView中需要嵌套ViewPager的情况,ViewPager 作为头部 ...

  3. Android ScrollView与ViewPager滑动冲突

    前段时间做项目碰到在ScrollView里添加ViewPager,但是发现ViewPager的左右滑动和ScrollView的滑动冲突了,解决这个问题的方法是重写ScrollView. 代码: pub ...

  4. ViewPager,实现真正的无限循环(定时+手动)

    利用定时器,实现循环轮播,很简单:只需在定时器的消息里加如下代码即可: int count = adapter.getCount(); if (count > 1) { // 多于1个,才循环 ...

  5. 封装一个ViewPager真正的实现图片无限循环滚动带导航点

    效果图: 大家在写项目的过程中常常会碰到须要实现Viewpager里面载入几张图片来循环自己主动轮播的效果,假设不封装一下的话代码分散在activity里面会显得非常乱.并且也不利于我们下次复用,所以 ...

  6. Android ViewPager嵌套ViewPager滑动冲突处理方法

    dispatchTouchEvent方法用于事件的分发,Android中所有的事件都必须经过这个方法的分发, 然后决定是自身消费当前事件还是继续往下分发给子控件处理.返回true表示不继续分发,事件没 ...

  7. scrollview和viewpager滑动冲突

    import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; i ...

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

    使用NestedScrollView+ViewPager+RecyclerView+SmartRefreshLayout打造酷炫下拉视差效果并解决各种冲突 如果你还在为处理滑动冲突而发愁,那么你需要静 ...

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

    如果你还在为处理滑动冲突而发愁,那么你需要静下心来看看这边文章,如果你能彻底理解这篇文章中使用的技术,那么,一切滑动冲突的问题解决起来就轻而易举了: 先扔一个最终实现的效果图 先分析下效果图中实现的功 ...

随机推荐

  1. Windows 2008安装SQL 2008图解

    SQL Server 2008是一个重大的产品版本,它推出了许多新的特性和关键的改进,使得它成为至今为止的最强大和最全面的SQL Server版本. 在现今数据的世界里,公司要获得成功和不断发展,他们 ...

  2. CodeIgnitor 创建admin和其他目录,前后端分离,很巧妙的方式,网上查找其他的都不是使用这种方式实现的。

    在index.php的第97和98行的注释, // The directory name, relative to the "controllers" folder. Leave ...

  3. 常用Sql语句书写

    一.增:有2种方法 1.使用insert插入单行数据: 语法:insert [into] <表名> [列名] values <列值> 例:insert into Strdent ...

  4. 将html页改成jsp的两种方式

    将html页改成jsp的两种方式 作者: 字体:[增加 减小] 类型:转载 时间:2013-08-13 将html页改成jsp有两种方法,第一种是直接修改html文件,另一种是新建jsp文件.下面为大 ...

  5. HTML回顾

    <frameset>和<body>是同一级的,已经在html5中被弃用    结合---->    效果   注意::::span标签不自动换行****

  6. 基于OpenCv的人脸检测、识别系统学习制作笔记之二

    在网上找到了一个博客,里面有大量内容适合初学者接触和了解人脸检测的博文,正好符合我目前的学习方面,故将链接放上来,后续将分类原博客的博文并加上学习笔记. 传送门: http://blog.sina.c ...

  7. linux系统基础网络配置

    1.修改主机名 临时方法: 退出当前shell重新登录即可生效.此法只能临时修改生效.重启系统后失效. 提示:很多人使用hostname主机名来修改,其实这个只是作为暂时的.重启后将恢复到配置前的主机 ...

  8. sql trunc()的使用

    1.TRUNC(for dates)TRUNC函数为指定元素而截去的日期值.其具体的语法格式如下:TRUNC(date[,fmt])其中:date 一个日期值fmt 日期格式,该日期将由指定的元素格式 ...

  9. SQLSERVER truncate table之后是否会重置表的自增值

    SQLSERVER truncate table之后是否会重置表的自增值 今天清理业务库数据的时候,开发人员说可以使用truncate table把两个表的所有数据清理掉 这两个表都有自增ID,都做了 ...

  10. [stm32] 利用uc-gui封装画图和画线函数移植51上的模拟动画

    >_<:这里的动画是黄色矩形区域中一个模仿俯视图的起重机运作动画,一个是模仿主视图的吊钩的运动.通过改变初始Init函数中的数据b_x,b_y实现矩形区域的移动.当实时采集时要首先根据起重 ...