Android如何使用RecyclerView打造首页轮播图
作者:24K纯帅豆 发布时间:2022-06-08 13:15:39
本文实例为大家分享了Android使用RecyclerView打造首页轮播图的具体代码,供大家参考,具体内容如下
先看看效果图:
停在中间自动翻页
序言:最近接到一个任务,做一个类似上面自动翻页的功能。可以看到,这一屏中有三张图片显示出来了,有两张没有显示完全,看到设计图的时候第一反应是可以用viewpager来实现,但是任务却跟你开了一个天大的玩笑,要求是以最左边的图片为基准,也就是说,左边的图片也得显示完全,就像下图所示,后来仔细想想viewpager好像没有这样的功能,也有可能是我不知道,我也没有找到这样的文章或者信息,希望知道的简友私戳交流一下,感激不尽,好了,言归正传
停在左边
在开始之前呢,首先介绍一个Google最新(其实在24.2.0版本的时候就已经发布了)发布的一个东西SnapHelper,这玩意儿是对RecyclerView功能的一个拓展,有兴趣的同学可以去看看它的源码,SnapHelper的实现原理是监听RecyclerView.OnFlingListener中的onFling接口,可以使RecyclerView实现类似ViewPager的功能,无论怎么滑动最终停留在某页正中间,那它和ViewPager的区别是什么呢?就是ViewPager不能一次连续滑动多张图片,而且不能定制(停在左边,还是停在右边)。下面我们一起来看看吧!
首先导入所需要的包,最低版本是v7-24.2.0,低了就没有这个类了:
compile 'com.android.support:appcompat-v7:24.2.0'
compile 'com.android.support:recyclerview-v7:24.2.0'
这里系统自带有一个类LinearSnapHelper,LinearSnapHelper继承自SnapHelper,这个默认是让视图停在中间的,你只需要将RecyclerView和LinearSnapHelper绑定在一起就行了:
LinearSnapHelper mLinearSnapHelper = new LinearSnapHelper();
mLinearSnapHelper.attachToRecyclerView(mRecyclerview);
效果如下:
当然了,SnapHelper的功能绝不仅仅在此,你还可以定制化,让他停在左边,或者右边,而你不需要重新继承SnapHelper,直接继承LinearSnapHelper就可以了,这里面有很多写好的方法,然后你再重写里面的两个方法:
* (1)、calculateDistanceToFinalSnap:当拖拽或滑动结束时会回调该方法,返回一个out = int[2],out[0]x轴,out[1] y轴 ,这个值就是需要修正的你需要的位置的偏移量。 *
* (2)、findSnapView:这个方法用来获取特定的视图,当返回null时,表示没有获取到任何视图 。*
完整的代码:
public class LeftSnapHelper extends LinearSnapHelper {
private OrientationHelper mHorizontalHelper;
/**
* 当拖拽或滑动结束时会回调该方法,该方法返回的是一个长度为2的数组,out[0]表示横轴,x[1]表示纵轴,这两个值就是你需要修正的位置的偏移量
*
* @param layoutManager
* @param targetView
* @return
*/
@Override
public int[] calculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View targetView) {
//注:由于是横向滚动,在这里我们只考虑横轴的值
int[] out = new int[2];
if (layoutManager.canScrollHorizontally()) {
out[0] = distanceToStart(targetView, getHorizontalHelper(layoutManager));
} else {
out[0] = 0;
}
return out;
}
/**
* 这个方法是计算偏移量
*
* @param targetView
* @param helper
* @return
*/
private int distanceToStart(View targetView, OrientationHelper helper) {
return helper.getDecoratedStart(targetView) - helper.getStartAfterPadding();
}
@Override
public View findSnapView(RecyclerView.LayoutManager layoutManager) {
return findStartView(layoutManager, getHorizontalHelper(layoutManager));
}
/**
* 找到第一个显示的view
* @param layoutManager
* @param helper
* @return
*/
private View findStartView(RecyclerView.LayoutManager layoutManager,
OrientationHelper helper) {
if (layoutManager instanceof LinearLayoutManager) {
int firstChild = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
int lastChild = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
if (firstChild == RecyclerView.NO_POSITION) {
return null;
}
//这是为了解决当翻到最后一页的时候,最后一个Item不能完整显示的问题
if (lastChild == layoutManager.getItemCount() - 1) {
return layoutManager.findViewByPosition(lastChild);
}
View child = layoutManager.findViewByPosition(firstChild);
//得到此时需要左对齐显示的条目
if (helper.getDecoratedEnd(child) >= helper.getDecoratedMeasurement(child) / 2
&& helper.getDecoratedEnd(child) > 0) {
return child;
} else {
return layoutManager.findViewByPosition(firstChild + 1);
}
}
return super.findSnapView(layoutManager);
}
/**
* 获取视图的方向
*
* @param layoutManager
* @return
*/
private OrientationHelper getHorizontalHelper(@NonNull RecyclerView.LayoutManager layoutManager) {
if (mHorizontalHelper == null) {
mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
}
return mHorizontalHelper;
}
}
当然了,你也可以让它停在右边:只需要在上面的基础上修改findSnapView方法即可:
public class RightSnapHelper extends LinearSnapHelper {
private OrientationHelper mHorizontalHelper;
/**
* 当拖拽或滑动结束时会回调该方法,该方法返回的是一个长度为2的数组,out[0]表示横轴,x[1]表示纵轴,这两个值就是你需要修正的位置的偏移量
*
* @param layoutManager
* @param targetView
* @return
*/
@Override
public int[] calculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View targetView) {
//注:由于是横向滚动,在这里我们只考虑横轴的值
int[] out = new int[2];
if (layoutManager.canScrollHorizontally()) {
out[0] = distanceToEnd(targetView, getHorizontalHelper(layoutManager));
} else {
out[0] = 0;
}
return out;
}
/**
* 这个方法是计算偏移量
*
* @param targetView
* @param helper
* @return
*/
private int distanceToEnd(View targetView, OrientationHelper helper) {
return helper.getDecoratedEnd(targetView) - helper.getEndAfterPadding();
}
@Override
public View findSnapView(RecyclerView.LayoutManager layoutManager) {
return findEndView(layoutManager, getHorizontalHelper(layoutManager));
}
/**
* 找到第一个显示的view
*
* @param layoutManager
* @param helper
* @return
*/
private View findEndView(RecyclerView.LayoutManager layoutManager, OrientationHelper helper) {
if (layoutManager instanceof LinearLayoutManager) {
int lastChild = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
if (lastChild == RecyclerView.NO_POSITION) {
return null;
}
View child = layoutManager.findViewByPosition(lastChild);
//得到此时需要右对齐显示的条目
if (helper.getDecoratedStart(child) >= helper.getDecoratedMeasurement(child) / 2
&& helper.getDecoratedStart(child) > 0) {
return child;
} else {
return layoutManager.findViewByPosition(lastChild - 1);
}
}
return super.findSnapView(layoutManager);
}
/**
* 获取视图的方向
*
* @param layoutManager
* @return
*/
private OrientationHelper getHorizontalHelper(@NonNull RecyclerView.LayoutManager layoutManager) {
if (mHorizontalHelper == null) {
mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
}
return mHorizontalHelper;
}
}
效果:
停在右边
那如何让它能无限的滑动呢?
这个当然是要在Adapter里面“做手脚”了,让获取Item总数的方法返回Integer.MAX_VALUE就可以了:
@Override
public int getItemCount() {
return Integer.MAX_VALUE;
}
然后在onBindViewHolder中获取list中的值时相应的取余就好了:
@Override
public void onBindViewHolder(RecyclerViewHolder holder, int position) {
Glide.with(mContext).load(mList.get(position % mList.size())
.getImageUrl()).placeholder(R.mipmap.ic_launcher)
.into(holder.ivImage);
holder.tvName.setText(mList.get(position % mList.size()).getName());
}


猜你喜欢
- 前言map的迭代删除,和我们常见的list,set不太一样,不能直接获取Iteraotr对象,提供的删除方法也是单个的,根据key进行删除,
- 这个其实很简单,思路是这样的,就是拿view的宽度,除以点的点的宽度+二个点 之间的间距,就可以算出大概能画出几个点
- 框架:半成品软件。可以在框架的基础上进行软件开发,简化编码。反射就是把Java类中的各个成员映射成一个个的Java对象。即在运行状态中,对于
- 说明:1、集合类型参数化;2、可根据集合中的对象的各个属性进行排序,传入属性名称即可;注:属性必须实现了IComparable接口,C#中i
- 阻塞、无饥饿、无障碍、无锁、无等待几种。阻塞一个线程是阻塞的,那么在其他线程释放资源之前,当前线程无法继续执行。当我们使用synchroni
- 开发 Web 应用的思路实现一个简单的 JSP/Servlet。搭建创建 Web 应用工程的环境。创建 Web 应用工程。Web 应用工程的
- 一. 编写.cs文件注:要想编译dll中注释可用,则代码中的注释要用“ /// ” 来进行注释,否则
- Android开发,触控无处不在。对于一些 不咋看源码的同学来说,多少对这块都会有一些疑惑。View事件的分发机制,不仅在做业务需求中会碰到
- 本文实例讲述了C#键盘鼠标钩子的实现方法。分享给大家供大家参考。具体实现方法如下:using System;using System.Col
- 前言最近在做一个公共相关的内容,公告里边的内容,打算做成配置化的。但是考虑到存储到数据库,需要建立数据库表;存储到配置组件中,担心配置组件存
- public class MainActivity extends Activity { private Handler hand
- 前言java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也不能做出来非常好用,
- CountDownLatch在日常开发中经常会遇到需要在主线程中开启多个线程去并行执行任务,并且主线程需要等待所有子线程执行完毕后再进行汇总
- 2015年Google IO大会分布了DataBinding库,能够更快捷便利的实现MVVM结构模式。但是,通过对DataBinding的学
- 由于公司项目的需求,需要绘制一条竖直的间断线作为分割线。这个可坑了爹了,以前只搞过水平的间断线,只要通过shape也可以简单的画出来,但是千
- 1、导入资源2、JSP代码<div class="page-container">  
- 本文研究的主要是Java ArrayList扩容问题实例详解的相关内容,具体介绍如下。首先我们需要知道ArrayList里面的实质的其实是一
- 前言SQL注入漏洞作为WEB安全的最常见的漏洞之一,在java中随着预编译与各种ORM框架的使用,注入问题也越来越少。新手代码审计者往往对J
- 上帝之火本系列讲述的是开源实时监控告警解决方案Prometheus,这个单词很牛逼。每次我都能联想到带来上帝之火的希腊之神,普罗米修斯。而这
- 这是一个演示如何使用java执行定时任务的实例,本实例开始运行后不会自动结束,请在运行本实例后手动结束程序。package com.hong