通常Android的轮播图(俗名:Banner)都是用ViewPager实现的,但是我在实际项目运用中碰到了一些小问题,于是决定另寻思路,采用RecyclerView这个更优雅更强大的控件来实现轮播的功能,顺便复习下RecyclerView的相关知识。

实现

一般轮播图就两个重要的部分:可以无限左右滑动的图片流和图片位置的标示点,可能更简单的连指示点都省略了。主要的难点还是在前者,因为一个轮播图要播放的图片一般也就十来张,不做任何处理直接塞到RecyclerView里面,不仅稍微滑一下就没了而且开始还不能先往左边滑,所以我们需要在设置Adapter的总数时设置成一个比较大的数(可以是Integer.MAX_VALUE),然后在设置完图片数据后把RecyclerView的当前位置转到中间的一个数(为了保证从第一张开始播放,必须是图片总数的倍数,比如10000*size),这样item回收复用的时候,我们只要取当前位置和图片数量的余数,得到真正的图片位置。听起来有点复杂,还是直接看下代码吧:

private class RecyclerAdapter extends RecyclerView.Adapter {List<String> urlList;public void setData(List<String> urlList) {this.urlList = urlList;}@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {return new RecyclerView.ViewHolder(new ImageView(getContext())) { };}@Overridepublic void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {if (urlList == null || urlList.isEmpty())return;String url = urlList.get(position % bannerSize);Glide.with(getContext()).load(url).into((ImageView) holder.itemView);}@Overridepublic int getItemCount() {//如果只有一张图片就不滑动了return bannerSize < 2 ? 1 : Integer.MAX_VALUE;}}复制代码

至于自动滑动图片,就用Handler不断延迟发送消息就好了:

private Handler mHandler = new Handler(new Handler.Callback() {@Overridepublic boolean handleMessage(Message msg) {if (msg.what == WHAT_AUTO_PLAY) {mRecyclerView.smoothScrollToPosition(++currentIndex);refreshIndicator();mHandler.sendEmptyMessageDelayed(WHAT_AUTO_PLAY, autoPlayDuration);}return false;}});复制代码

好了,无限轮播解决了,接下来就是标示点了,既然无限轮播图都用RecyclerView解决了,那么标示点也用它来解决吧:

  private class IndicatorAdapter extends RecyclerView.Adapter {int currentPosition = 0;public void setPosition(int currentPosition) {this.currentPosition = currentPosition;}@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {return new RecyclerView.ViewHolder(new ImageView(getContext())) {};}@Overridepublic void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {ImageView bannerPoint = (ImageView) holder.itemView;bannerPoint.setImageDrawable(currentPosition == position ? mSelectedDrawable : mUnselectedDrawable);}@Overridepublic int getItemCount() {return bannerSize;}}复制代码

其实Adapter也很简单,设置一个当前位置的标识点,然后在图片改变的时候notifyDataSetChanged()就行了。
好了最后就剩下怎么监听RecyclerView的位置改变了(可没有像Viewpager的addOnPageChangeListener那么直接的方法),没办法直接分析RecyclerView.OnScrollListener中的回调方法吧:

 mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {@Overridepublic void onScrolled(RecyclerView recyclerView, int dx, int dy) {//解决连续滑动时指示器不更新的问题if (bannerSize < 2) return;int firstReal = mLinearLayoutManager.findFirstVisibleItemPosition();View viewFirst = mLinearLayoutManager.findViewByPosition(firstReal);float width = getWidth();if (width != 0 && viewFirst != null) {float right = viewFirst.getRight();float ratio = right / width;if (ratio > 0.8) {if (currentIndex != firstReal) {currentIndex = firstReal;refreshIndicator();}} else if (ratio < 0.2) {if (currentIndex != firstReal + 1) {currentIndex = firstReal + 1;refreshIndicator();}}}}@Overridepublic void onScrollStateChanged(RecyclerView recyclerView, int newState) {//连续滑动时可能不会回调int first = mLinearLayoutManager.findFirstVisibleItemPosition();int last = mLinearLayoutManager.findLastVisibleItemPosition();if (currentIndex != first && first == last) {currentIndex = first;refreshIndicator();}}});复制代码

看看成果

好了解决了这些东西,再加些自定义View常用的属性,回调方法,设置的接口,轮播图就做好了,我们来看看效果:

gif.gif

嗯,看着还不错,可是怎么有点怪?唉,这图片怎么滑动的这么快,而且还能停在中间,这个不是我们想要的`标准`轮播图。要解决这个问题就要用到RecyclerView的另一个功能:SnapHelper。SnapHelper旨在支持RecyclerView的对齐方式,也就是通过计算对齐RecyclerView中TargetView 的指定点或者容器中的任何像素点。自定义一个SnapHelper挺麻烦的,还好android已经为我们内置好了两个实现: LinearSnapHelper & PagerSnapHelper。其中PagerSnapHelper真是我们需要的可以把RecyclerView改的像Viewpager的工具。
new PagerSnapHelper().attachToRecyclerView(mRecyclerView);

gif.gif

现在看着顺畅多了:一次只能滑动一张图片,停止的时候图片的位置也对了。这样一个基础版的轮播图就做成了。因为本质是一个RecyclerView,我们可以RecyclerView.Itemanimator,来做出更多的动画效果(这个我目前就不太会了(T_T))。最后奉上github地址,里面有更完整代码,封装了很多自定义属性,欢迎star!

PS:进阶版请戳:

用RecyclerView打造一个轮播图(进阶版)

用RecyclerView打造一个轮播图相关推荐

  1. echarts formatter_牛X!用 Echarts 打造一个轮播图!

    最近,在B站上学习了一些Echarts的使用,分享给大家. 一个动态的柱状轮播图,本想着使用Pyecharts来实现的,奈何实现不了动态. 看来做酷炫的可视化大屏还是得上Echarts和D3. Ech ...

  2. [css] 用CSS实现一个轮播图

    [css] 用CSS实现一个轮播图 使用CSS实现的话,可以使用 animat属性和overflow:hidden 属性来做. 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放弃很容易, 但坚持一 ...

  3. html轮播图原理,30_用js实现一个轮播图效果,简单说下原理

    一.原理 将一些图片在一行中平铺,然后计算偏移量再利用定时器实现定时轮播. 步骤一:建立html基本布局 如下所示: 轮播图 1 2 3 4 5 < > 只有五张图片,却使用7张来轮播,这 ...

  4. 案例——封装一个轮播图插件

    说起插件,可能很多人搞不清楚插件和类库.组件.框架的区别,在这里,我先来简单的聊一聊它们之间的区别和联系 类库 提供一些真实项目中常用的方法,任何项目都可以把类库导入进来,调取里面的方法实现自己需要的 ...

  5. 用jq简单的去做一个轮播图

    在生活中我们会经常去在淘宝上购买商品,网页上有一个可以滑动的图片今天我们用jq去做一个轮播图 我们先做好一个盒子和轮播图的一个框架 <div class="zt"> & ...

  6. vue 实现无限轮播_用vue写一个轮播图效果

    轮播图在网站中几乎无处不在,占用地方少,交互性好.今天就来聊聊如何用vue实现一个轮播效果. 一.原理 在轮播图数组dataList中,定义一个变量currentIndex = 0表示第一张图片,默认 ...

  7. 小白怎么做一个轮播图?(思路+代码)

    在页面中写好结构和样式(根据情况而定) 外层用一个$(function(){})函数包裹起来,代表等页面的内容加载完成后再去执行jquery的功能代码. 获取到包裹ul,li的大盒子元素:const ...

  8. VUE如何快速做一个轮播图

    1. 第三方插件 https://github.com/surmon-china/vue-awesome-swiper npm install swiper vue-awesome-swiper -- ...

  9. 在vue脚手架中,学习实现一个轮播图(2-旋转木马)

    目录 效果展示: index.html: template: data: methods: mounted(): style: 效果展示: 轮播图(旋转木马) index.html: <styl ...

最新文章

  1. MyBatis——XML配置解析
  2. Go在Ubuntu 14.04 64位上的安装过程
  3. 958毕业,苦学Java,竟被二本毕业生吊打!网友:确实厉害!
  4. 第一个以比特币现金ICO的项目,筹集了3000万美元
  5. Python中*args 和**kwargs的用法
  6. 你所忽略的Linux系统安全及应用(最全面)
  7. 编写脚本自动部署反向代理、web、nfs
  8. mysql查询条件字段值末尾有空格的问题
  9. 适用于 Python 的 10 大最佳 IDE,你 Pick 哪一款?
  10. yytextview多种格式_iOS YYText的使用笔记一(YYTextView图文编辑器)
  11. 线性表—线性表的合并
  12. 解决Linux下chrome无法播放flash问题
  13. 检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 8000401a
  14. 网络操作系统属于计算机网络的资源子网吗,属于计算机网络的资源子网.pdf
  15. 产品经理通用标准工作流程
  16. Mentor.Graphics.FloTHERM.XT.2.3+Mentor.Graphics.Flowmaster.7.9.4
  17. Openstack 简单梳理,(自用 慎点)
  18. CVPR2021/邻域自适应/图像翻译-DRANet: Disentangling Representation and Adaptation Networks
  19. 计算机视觉笔记11.26
  20. 儿科微信端产品推广策划方案记录

热门文章

  1. MySQL主从复制原理应用基础
  2. websocket 之入门 (一)
  3. NFS服务器的安装与配置
  4. 2015第16周三知道做到
  5. HDU-不容易系列之(3)—— LELE的RPG难题
  6. 那些年,我深爱着的PPT(一)
  7. MFC中静态文本控件显示的几种实现方式
  8. 华思视频 CCNA 听而思
  9. CompletableFuture 创建异步对象
  10. 搭建自己的Docker Harbor