手把手带你用viewpager实现gallary效果,外加无限循环,自动轮播

效果图:图很丑,各位看官且按需更改。

主要功能:
①Gallary样式
②无限轮播
③自动轮播和手势操作间冲突解决

提前说明:可以先不看提供的连接,文章末尾会提供整体代码。

1、大致思路:

经过查阅网上资料,个人感觉viewPager实现最为靠谱,省时省力。下面就将上述的需求一个个解决:
①Gallary样式:使用ViewPager.PageTransformer解决滑动动画。
参照:
https://developer.android.com/training/animation/screen-slide.html
https://www.jianshu.com/p/722ece163629
②无限轮播:在PagerAdapter里面进行操作,让getCount()方法返回的值足够大。
参照:方法二
http://blog.csdn.net/Just_Sanpark/article/details/17436037
③自动轮播和收拾操作间冲突解决:
自动轮播使用handler发送延时消息;在viewpager的dispatchTouchEvent方法里面来进行ViewPager接收到Touch事件的操作。

2、接下来下面是代码实现了,先创建个普通的ViewPager:

①activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.tongtong.tiny.loopviewpagergallary.MainActivity"><!-- 这里的ViewPager最好包一层父布局,并给它设置android:clipChildren="false"属性--><FrameLayoutandroid:id="@+id/fl_vp_parent"android:layout_width="match_parent"android:layout_height="160dp"android:layout_centerInParent="true"android:background="#aadc71ff"android:clipChildren="false"><!-- 宽度不要占满屏幕设置android:clipChildren="false"属性 --><android.support.v4.view.ViewPagerandroid:id="@+id/id_viewpager"android:layout_width="250dp"android:layout_height="120dp"android:layout_gravity="center"android:clipChildren="false"></android.support.v4.view.ViewPager></FrameLayout></android.support.constraint.ConstraintLayout>

ViewPager:

public class PageTransformerAdapter extends PagerAdapter {private Context context;private List<TextView> list;public PageTransformerAdapter(Context context, List<TextView> list) {this.context = context;this.list = list;}@Overridepublic int getCount() {return list.size();}@Overridepublic boolean isViewFromObject(View view, Object object) {return view == object;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {container.addView(list.get(position));return list.get(position);}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {TextView iv = (TextView) object;container.removeView(iv);}
}

MainActivity代码:

public class MainActivity extends AppCompatActivity {public static final String TAG = MainActivity.class.getSimpleName();//测试数据个数public static final int LIST_SIZE = 10;FrameLayout flVpParent;ViewPager mViewPager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);flVpParent = findViewById(R.id.fl_vp_parent);mViewPager = findViewById(R.id.id_viewpager);List<TextView> viewList = getViewLists();PageTransformerAdapter mAdapter = new PageTransformerAdapter(MainActivity.this, viewList);mViewPager.setAdapter(mAdapter);}/*** 生成List<TextView>数据** @return*/private List<TextView> getViewLists() {List<TextView> list = new ArrayList<>();for (int j = 0; j < LIST_SIZE; j++) {TextView tv = generateTextView(j);list.add(tv);}return list;}/*** 生成单个的TextView对象** @param j* @return*/private TextView generateTextView(final int j) {TextView tv = new TextView(this);tv.setBackgroundColor(Color.parseColor("#2371e9"));String str = "这个是第" + (j + 1) + "个View";tv.setTag(str);tv.setText(str);tv.setTextColor(Color.parseColor("#f0523c"));tv.setTextSize(30);tv.setGravity(Gravity.CENTER);tv.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Log.e(TAG, "第" + (j + 1) + "个View被点击了");}});return tv;}
}

效果如下图:

好了,架子搭建好了,可以开始一步步实现需求了。

3、Gallary视图效果:利用ViewPager.PageTransformer实现

①viewpager的布局文件设置之前已经设置好了,这里直接使用
②新建ScaleDownPageTransformer,实现ViewPager.PageTransformer接口

/*** Desc:    左右缩放的PageTransformer* Created by tiny on 2018/1/19.* Time: 17:04* Version:*/public class ScaleDownPageTransformer implements ViewPager.PageTransformer {private static final float DEFAULT_MIN_SCALE = 0.9f;private float mMinScale = DEFAULT_MIN_SCALE;/*** Apply a property transformation to the given page.** @param view     Apply the transformation to this page* @param position Position of page relative to the current front-and-center*                 position of the pager. 0 is front and center. 1 is one full*                 page position to the right, and -1 is one page position to the left.*/@Overridepublic void transformPage(View view, float position) {float limitLow = -1;float limitMid = 0;float limitHigh = 1;if (position < limitLow) {view.setScaleX(mMinScale);view.setScaleY(mMinScale);} else if (position <= limitHigh) { // [-1,1]if (position < limitMid) //[-1,0){float factor = mMinScale + (1 - mMinScale) * (1 + position);view.setScaleX(factor);view.setScaleY(factor);} else//[0,1]{float factor = mMinScale + (1 - mMinScale) * (1 - position);view.setScaleX(factor);view.setScaleY(factor);}} else { // (1,+Infinity]view.setScaleX(mMinScale);view.setScaleY(mMinScale);}}
}

③将ScaleDownPageTransformer设置给viewPager对象。

//设置Page间间距
mViewPager.setPageMargin(20);
//设置缓存的页面数量
//这个如果设置为1,或者使用默认值1时,在向左滑动时,右面新加载出的view第一次加载时的缩放动画不显示。。
mViewPager.setOffscreenPageLimit(2);
mViewPager.setPageTransformer(true, new ScaleDownPageTransformer());
mViewPager.setAdapter(mAdapter);

参考官网demo:https://developer.android.com/training/animation/screen-slide.html
https://www.jianshu.com/p/722ece163629

效果如下:

4、无限循环

接下来看下无线循环的需求,具体细节和原理的说明网上有好多,我选择的是这篇文章的第二种方法。
传送门:http://blog.csdn.net/Just_Sanpark/article/details/17436037

下面直接上代码:
PagerAdapter做了些修改:

public class PageTransformerAdapter extends PagerAdapter {private Context context;private List<TextView> list;public PageTransformerAdapter(Context context, List<TextView> list) {this.context = context;this.list = list;}@Overridepublic int getCount() {return Integer.MAX_VALUE;}@Overridepublic boolean isViewFromObject(View view, Object object) {return view == object;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {int actualPos = position % list.size();if (list.get(actualPos).getParent() != null) {((ViewPager) list.get(actualPos).getParent()).removeView(list.get(actualPos));}container.addView(list.get(actualPos));return list.get(actualPos);}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {TextView iv = (TextView) object;container.removeView(iv);}
}

MainActivity中增加了代码:

//这儿的1000,可以随便改,只要用户滑不出边界即可
int startPos = 1000 * viewList.size() + 1;
mViewPager.setCurrentItem(startPos);

效果如下图:

5、自动轮播,同时支持手势滑动

①自动轮播的功能决定使用handler发送消息实现
②当用户对轮播进行操作时,需要停止自动轮播的消息,这里决定在ViewPager的dispatchTouchEvent方法里面操作。
ps: 之所以不在onTouchEvent里面进行操作,是因为ViewPager对分发下来的事件进行了处理,在onTouchEvent中拦截不到ACTION_DOWN事件,长按事件也拦截不到。

代码如下:
①自定义LoopViewPager,继承自ViewPager,

/*** Desc:    自动切换的ViewPager,手势冲突已处理* Created by tiny on 2018/1/23.* Time: 14:38* Version:*/public class LoopViewPager extends ViewPager {public static final String TAG = LoopViewPager.class.getSimpleName();public LoopViewPager(Context context) {super(context);init();}public LoopViewPager(Context context, AttributeSet attrs) {super(context, attrs);init();}private void init() {autoPollTask = new AutoPollTask(this);}private static final long TIME_AUTO_POLL = 2000;private static AutoPollTask autoPollTask;private static boolean running; //标示是否正在自动轮询private static boolean canRun;//标示是否可以自动轮询,可在不需要的是否置falsestatic class AutoPollTask implements Runnable {private final WeakReference<ViewPager> mReference;//使用弱引用持有外部类引用->防止内存泄漏public AutoPollTask(ViewPager reference) {this.mReference = new WeakReference<>(reference);}@Overridepublic void run() {ViewPager viewPager = mReference.get();if (viewPager != null && running && canRun) {int currPos = viewPager.getCurrentItem();viewPager.setCurrentItem(currPos + 1, true);viewPager.postDelayed(autoPollTask, TIME_AUTO_POLL);}}}//开启:如果正在运行,先停止->再开启public void start() {if (running)stop();canRun = true;running = true;postDelayed(autoPollTask, TIME_AUTO_POLL);}public void stop() {running = false;removeCallbacks(autoPollTask);}/*** onTouchEvent中的事件被viewPager处理过了,有些拦截不到* 所以在这里拦截** @param ev* @return*/@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {//只要接收到事件,就停止滚动。if (running)stop();switch (ev.getAction()) {//当手指抬起或者划出页面时case MotionEvent.ACTION_UP:case MotionEvent.ACTION_OUTSIDE:if (canRun)start();break;}return super.dispatchTouchEvent(ev);}
}

②接下来将activity_main.xml中的ViewPager替换为LoopViewPager,并在MainActivity中添加如下代码:

mViewPager.start();

最后,为了节省资源,在MainActivity中加上下面代码。

@Override
protected void onStart() {super.onStart();if (mViewPager != null) {mViewPager.start();}
}@Override
protected void onStop() {super.onStop();if (mViewPager != null) {mViewPager.stop();}
}

最后附上福利:源码地址,求star。
https://github.com/tinyvampirepudge/LoopViewPagerGallary

手把手带你用viewpager实现gallary效果,外加无限循环,自动轮播相关推荐

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

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

  2. html轮播图循环效果,TremulaJS-跨设备多功能的无限循环js轮播图插件

    TremulaJS是一款非常酷的跨设备多功能的无限循环js轮播图插件.TremulaJS是一个客户端javascript UI组件,它基于贝兹曲线和物理动量效应制作各种效果,可以制作无限循环的图片流, ...

  3. Flutter PageView 实现的自动轮播图效果 Timer实现的自动轮播效果

    题记 -- 执剑天涯,从你的点滴积累开始,所及之处,必精益求精. Flutter是谷歌推出的最新的移动开发框架. [x1]微信公众号的每日提醒 随时随记 每日积累 随心而过 文章底部扫码关注 [x2] ...

  4. ViewPager实现左右无限循环效果

    ViewPager自身并不支持左右无限循环的功能,在网上找了很多天,发现基本都是一个原理,就是实现一种假的无限循环,取一种最大值的思路,这一种方案在上一篇中实现过,并没有真正达到左右无限循环,只是一般 ...

  5. android开发实例之viewpager无限循环+自动滚动,Android ViewPager实现无限循环的实例...

    Android ViewPager实现无限循环的实例 ViewPager自身并不支持左右无限循环的功能,这里就提供一种方案让Android ViewPager实现左右无限循环的功能,这里记录下: 用于 ...

  6. Android广告条效果--使用Volley实现网络图片的自动轮播(仿淘宝、网易广告页轮播效果)

    最近在做自定义控件时,发现一个极其常用的效果--广告条,即图片的自动轮播效果.现在市面上大多数的APP软件都在使用这种展示广告的效果.闲来无事,我简单翻看了一下自己的手机软件,几乎都使用了这种图片自动 ...

  7. HTML图片重叠变换,CSS实现图片无缝无限循环展示效果

    只是想练练手,看看能不能实现在页面上放置一个能无限循环滚动的图片横幅.事实证明,这并不是很难. 先看实际效果: 无限循环滚动的关键是确定宽图片的位置 首先,这个图片的设计需要有一点技巧,就是它的首位部 ...

  8. 微信小程序手把手教你实现类似Android中ViewPager控件效果

    微信小程序手把手教你实现类似Android中ViewPager控件效果 前言 需求分析 头部TAB 滑动的内容部分 最终版本 尾巴 前言 在做Android开发的时候,ViewPager是开发者使用频 ...

  9. 柱状图带立体效果_PS教程!手把手教你打造立体感欧美风人像大片效果(已打包好素材资料见文末)...

    在PS的众多技法中,磨皮教程种类繁多.本期教给大家的方法完全可以保留原片的细节和质感,既可以修掉面部不需要的瑕疵,又可以在保留皮肤质感的基础上,打造画面的立体感,而不是把人物的皮肤处理得如同镜面一般光 ...

最新文章

  1. [转]div 让文字或图片居中
  2. Java温故而知新(1)集合类
  3. Oracle数据库的认证方法、用户管理、权限管理和角色管理等
  4. BP神经网络算法推导
  5. Stanford UFLDL教程 栈式自编码算法
  6. Istio分层架构?80%的人有误解
  7. 构造函数怎么在主函数调用_C++ 虚基类及其派生类构造函数(学习笔记:第7章 12)...
  8. smarty二维foreach示例[顺代一维数组],再次加强版
  9. 【Elasticsearch】Request cannot be executed;I/O reactor status :STOPPED.
  10. Codeforces Round #439 (Div. 2)
  11. rostcm6情感分析案例分析_情感分析师在线指导情感挽回
  12. 如何获得学生版本的免费eviews9
  13. OSPF基础知识及配置命令
  14. linux内核编译串口驱动,ARM Linux下安装CH341串口驱动
  15. macbook删除windows后合并磁盘分区
  16. php图片虚化处理 api PHP实现生成模糊图片
  17. Java 基础类型 —— Short
  18. 简单的python爬虫程序:爬取斗鱼直播人气前五十的主播
  19. 使用git时代码被冲掉
  20. OpenCV:图片文字分割

热门文章

  1. ES搜索引擎-简单入门
  2. konfig:采用ConfigMap实现线上配置热更新
  3. 1000个微信小程序源码分享
  4. java体系的中间件适用于go吗,Go语言经典库使用分析(五)| Negroni 中间件(一)...
  5. linux编译符号那些事儿
  6. 关于「微信小程序」背后的故事
  7. 课堂在线录屏:EV录屏软件配置设置
  8. html页面如何获取已经存在的token,移动端通过携带token访问html页面
  9. Matlab函数gscatter使用
  10. Python编程PTA题解——验证“哥德巴赫猜想”