目录
- 一、轮播图的简单介绍
- 二、轮播图的实现步骤
- 1.绘制轮播图页面
- 2.设置Viewpager2的子布局
- 3.编写ViewPager2的适配器
- 4.编写Carousel类具体实现轮播图
- 5.实现自动轮播
- 6.触摸时停止自动轮播
- 三、完整代码
一、轮播图的简单介绍
轮播图(Carousel)是一种在有限空间内循环展示多个内容项的UI组件,用户可以通过滑动或自动播放的方式浏览不同的内容,在有限的空间中展示更多的内容。
实现轮播图主要有两种方式,首尾添加法和取余法,这里主要讲解首尾添加法的实现。
二、轮播图的实现步骤
1.绘制轮播图页面
添加一个ViewPager2作为轮播图的容器,并添加LinearLayout放置指示图标
<?XML version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <androidx.viewpager2.widget.ViewPager2 android:id="@+id/viewpager2" android:layout_width="match_parent" android:layout_height="match_parent" > </androidx.viewpager2.widget.ViewPager2> <LinearLayout android:id="@+id/botttom_viewpager2" android:layout_width="wrajavascriptp_content" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginBottom="100dp" app:layout_constraintBottom_toBottomOf="@+id/viewpager2" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="@+id/viewpager2" > </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>
2.设置ViewPager2的子布局
新建xml文件,绘制ViewPager2的子布局
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/image" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop"/> </androidx.constraintlayout.widget.ConstraintLayout>
3.编写ViewPager2的适配器
因为ViewPager2实现基于RecyclerView,因此这里直接继承RecyclerView.Adapter
这里我们使用Glide来加载图片。
Glide 是一个专注于平滑滚动的 Android 图片加载库。
优点:
1.使用简单,并且支持多种图片格式,既可以获取网络资源又可以获取本地资源,不用处理网络请求、缓存、内存管理、图片解码等复杂逻辑;
2.性能优秀:自动管理 Bitmap 内存,防止内存溢出,可以自动根据ImageView调整图片大小,节省内存。
public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ImageViewHolder> { private List<Integer> images; private Context context; public ImageAdapter(List<Integer> images){ this.images=images; } public int getItemCount(){ if(images!=null){ return images.size(); } return 0; } public ImageViewHolder onCreateViewHolder(ViewGroup parent,int viewType){ context=parent.getContext(); View view= LayoutInflater.from(context).inflate(R.layout.layout,parent,false); return new ImageViewHolder(view); } public void onBindViewHolder(ImageViewHolder holder,int position){ Glide.with(context).load(images.get(position)).into(holder.imageView); } public static class ImageViewHolder extends RecyclerView.ViewHolder{ ImageView imageView; public ImageViewHolder(View view){ super(view); imageView=view.findViewById(R.id.image); } }
4.编写Carousel类具体实现轮播图
public class Carousel { private Context mContext; private LinearLayout dotLinearLayout; private List<ImageView> mImageList=new ArrayList<>();//标志点集合 private List<Integer> originalImages=new ArrayList<>();//轮播图图片资源id集合 private ViewPager2 viewPager2; public Carousel(Context mContext, LinearLayout dotLinearLayout, ViewPager2 viewPager2){ this.mContext=mContext; this.dotLinearLayout=dotLinearLayout; this.viewPager2=viewPager2; } public void initViews(int[] resourse){ //初始化轮播图图片资源id集合 for(int id:resourse){ originalImages.add(id); ImageView dotImageView=new ImageView(mContext);//制作标记点的ImageView if(originalImages.size()==1){ dotImageView.setImageResource(R.drawable.blue_dot);//加载第一张图片的标志 }else { dotImageView.setImageResource(R.drawable.grey_dot); } LinearLayout.LayoutParams dotImageLayoutParams=new LinearLayout.LayoutParams(60,60); dotImageLayoutParams.setMargins(5,0,5,0); //设置 dotImageView的布局参数 dotImageView.setLayoutParams(dotImageLayoutParams); mImageList.add(dotImageView); //将视图动态添加到布局容器 dotLinearLayout.addView(dotImageView); } //将最后一张图片添加到开头,将第一张图片添加到末尾,可以更好实现无限轮播的视觉效果 originalImages.add(0,originalImages.get(originalImages.size()-1)); originalImages.add(originalImages.get(1)); //设置适配器 ImageAdapter adapter=new ImageAdapter(originalImages); viewPager2.setAdapter(adapter); viewPager2.setCurrentItem(1,false); //设置ViewPager2的页面更改监听器,处理标志点和边界情况 viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { @Override public void onPageSelected(int position){ for(int i=0;i<mImageList.size();i++){ if(i==position-1){ mImageList.get(i).setImageResource(R.drawable.blue_dot); }else{ mImageList.get(i).setImageResource(R.drawable.grey_dot); } } //滑动到最后一个元素时跳转到第一个元素,滑动到第一个元素时跳转到最后一个元素 if(position==originalImages.size()-1){ viewPager2.setCurrentItem(1,false); } else if (position==0) { viewPager2.setCurrentItem(originalImages.size()-2,false); } } }); } }
在这里简单解释一下取余法的实现原理
取余法实现
设置一个很大的数,通过取余运算获取真实位置,以实现无限循环的效果
真实数据: [A, B, C] (3个元素) 虚拟位置: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... (无限) 通过取余: position % 3 = 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, ... 对应数据: A, B, C, A, B, C, A, B, C, A, ...
公式: 真实位置 = 虚拟位置 % 图片数量
开始时从中间位置开始,保证有足够的空间向左滑动,并且避免在边界处出现问题
优点:实现简单,不需要修改数据源
缺点:虽然虚拟位置很大,但RecyclerView会回收视图
5.实现自动轮播
使用Handler实现自动轮播效果,在初始化Carousel时同时注册Handler
private android.os.Handler handler; //设置是否自动播放 private boolean AUTO_SCROLL=false; public Carousel(Context mContext, LinearLayout dotLinearLayout, ViewPager2 viewPager2){ this.mContext=mContext; this.dotLinearLayout=dotLinearLayout; this.viewPager2=viewPager2; handler=new Handler(Looper.getMainLooper()); }
在Carousel中编写控制Handler的方法
//开启自动轮播 public void startAutoScrool(){ handler.removeCallbacks(autoScrollRunnable);//移除之前的回调,防止多次启用 handler.postDelayed(autoScrollRunnable,Banner_Time); AUTO_SCROLL=true; } //在Runnable中处理自动滚动 private final Runnable autoScrollRunnable=new Runnable() { @Override public void run() { int current=viewPager2.getCurrentItem(); if(current==originalImages.size()-2){ viewPager2.setCurrentItem(1,false); } else{ viewPager2.setCurrentItem(current+1); } handler.postDelayed(this,Banner_Time); } }; public void stopAutoScrool(){ handler.removeCallbacks(autoSc编程rollRunnable); AUTO_SCROLL=false; }
6.触摸时停止自动轮播
开启自动轮播后,用户就无法通过滑动参看想要的页面,因此我们还应实现触摸时停止自动轮播功能。
可以通过监听Viewpager2的滑动行为来实现触摸时停止自动轮播。
ViewPager2中定义了三种滚动状态:
三种滚动状态常量 // 在 ViewPager2 类中定义的常量 public static final int SCROLL_STATE_IDLE = 0; // 空闲状态,当前没有滚动操作,页面完全静止 public static final int SCROLL_STATE_DRAGGING = 1; // 拖动状态, 用户正在用手指拖动页面 public static final int SCROLL_STATE_SETTLING = 2; // 自动滑动状态,页面正在自动滑动到目标位置
我们通过对三种状态进行分别处理来实现想要的效果。
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { @Override public void onPageSelected(int position){ for(int i=0;i<mImageList.size();i++){ if(i==position-1){ mImageList.get(i).setImageResource(R.drawable.blue_dot); }else{ mImageList.get(i).setImageResource(R.drawable.grey_dot); } } if(position==originalImages.size()-1){ viewPager2.setCurrentItem(1,false); } else if (position==0) { viewPager2.setCurrentItem(originalImages.size()-2,false); } } @Override public void onPageScrollStateChanged(int state) { super.onPageScrollStateChanged(state); if(state==ViewPager2.SCROLL_STATE_DRAGGING){ handler.removeCallbacks(autoScrollRunnable);//在拖动时停止自动滚动 } //在页面静止时 else if (state==ViewPager2.SCROLL_STATE_IDLE&&AUTO_SCROLL) { handler.removeCallbacks(autoScrollRunnable); handler.postDelayed(autoScrollRunnable,Banner_Time); } } });
到这里我们就实现了简单轮播图的全部功能。
三、完整代码
下面是实现轮播图的完整代码,以作参考。
public class Carousel { private Context mContext; private LinearLayout dotLinearLayout; private List<ImageView> mImageList=new ArrayList<>(); private List<Integer> originalImages=new ArrayList<>(); private ViewPager2 viewPager2; private long Banner_Time=1000; private 编程客栈android.os.Handler handler; private boolean AUTO_SCROLL=false; public Carousel(Context mContext, LinearLayout dotLinearLayout, ViewPager2 viewPager2){ this.mContext=mContext; this.dotLinearLayout=dotLinearLayout; this.viewPager2=viewPager2; handler=new Handler(Looper.getMainLooper()); } public void initViews(int[] resourse){ for(int id:resourse){ originalImages.add(id); ImageView dotImageView=new ImageView(mContext); if(originalImages.size()==1){ dotImageView.setImageResource(R.drawable.blue_dot); }else { dotImageView.setImageResource(R.drawable.grey_dot); } LinearLayout.LayoutParams dotImageLayoutParams=new LinearLayout.LayoutParams(60,60); dotImageLayoutParams.setMargins(5,0,5,0); dotImageView.setLayoutParams(dotImageLayoutParams); mImageList.add(dotImageView); dotLinearLayout.addView(dotImageView); } originalImages.add(0,originalImages.get(originalImages.size()-1)); originalImages.add(originalImages.get(1)); ImageAdapter adapter=new ImageAdapter(originalImages); viewPager2.setAdapter(adapter); viewPager2.setCurrentItem(1,falhttp://www.devze.comse); viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { @Override public void onPageSelected(int position){ for(int i=0;i<mImageList.size();i++){ if(i==position-1){ mImageList.get(i).setImageResource(R.drawable.blue_dot); }else{ mImageList.get(i).setImageResource(R.drawable.grey_dot); } } if(position==originalImages.size()-1){ viewPager2.setCurrentItem(1,false); } else if (position==0) { viewPager2.setCurrentItem(originalImages.size()-2,false); } } @Override public void onPageScrollStateChanged(int state) { super.onPageScrollStateChanged(state); if(state==ViewPager2.SCROLL_STATE_DRAGGING){ handler.removeCallbacks(autoScrollRunnable); } else if (state==ViewPager2.SCROLL_STATE_IDLE&&AUTO_SCROLL) { handler.removeCallbacks(autoScrollRunnable); handler.postDelayed(autoScrollRunnable,Banner_Time); } } }); } public void startAutoScrool(){ handler.removeCallbacks(autoScrollRunnable); handler.postDelayed(autoScrollRunnable,Banner_Time); AUTO_SCROLL=true; } private final Runnable autoScrollRunnable=new Runnable() { @Override public void run() { int current=viewPager2.getCurrentItem(); if(current==originalImages.size()-2){ viewPager2.setCurrentItem(1,false); } else{ viewPager2.setCurrentItem(current+1); } handler.postDelayed(this,Banner_Time); } }; public void stopAutoScrool(){ handler.removeCallbacks(autoScrollRunnable); AUTO_SCROLL=false; } } public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ImageViewHolder> { private List<Integer> images; private Context context; public ImageAdapter(List<Integer> images){ this.images=images; } public int getItemCount(){ if(images!=null){ return images.size(); } return 0; } public ImageViewHolder onCreateViewHolder(ViewGroup parent,int viewType){ context=parent.getContext(); View view= LayoutInflater.from(context).inflate(R.layout.layout,parent,false); return new ImageViewHolder(view); } public void onBindViewHolder(ImageViewHolder holder,int position){ Glide.with(context).load(images.get(position)).into(holder.imageView); } public static class ImageViewHolder extends RecyclerView.ViewHolder{ ImageView imageView; python public ImageViewHolder(View view){ super(view); imageView=view.findViewById(R.id.image); } } }
最终效果展示如下
以上就是Android使用ViewPager2实现简单的轮播图的代码示例的详细内容,更多关于Android ViewPager2轮播图的资料请关注编程客栈(www.devze.com)其它相关文章!
精彩评论