当前位置: 首页 > news >正文

【Android】Viewpager2实现无限轮播图

【Android】Viewpager2实现无限轮播图

文章目录

  • 【Android】Viewpager2实现无限轮播图
    • 🏇先上效果图
    • 🎍使用步骤
      • 🏀step1 添加依赖
      • 🍔step2 自定义RecyclerView.Adapter
      • 🚗step3 在页面中使用
      • 关键点分析
        • 无限循环原理
      • 🍟如何自定义Indicator
      • 🛌内置IndicatorView使用方法介绍,没有提供任何自定义属性

🏇先上效果图

在这里插入图片描述

这就类似于常用软件首页的广告轮播图,这里只是简单显示了几张图片,当然你还可以自定义更精美的子项布局来实现想要的效果。

🎍使用步骤

🏀step1 添加依赖

首先在app/build.gradle文件中添加依赖:

implementation 'androidx.viewpager2:viewpager2:1.0.0'implementation 'me.relex:circleindicator:2.1.6'

🍔step2 自定义RecyclerView.Adapter

package com.example.viewpager2test;import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;public class CarouselAdapter extends RecyclerView.Adapter<CarouselAdapter.ViewHolder> {private final int[] imageResources; // 图片资源数组public CarouselAdapter(int[] imageResources) {this.imageResources = imageResources;}@NonNull@Overridepublic ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_carousel, parent, false);return new ViewHolder(view);}@Overridepublic void onBindViewHolder(@NonNull ViewHolder holder, int position) {holder.imageView.setImageResource(imageResources[position]);}@Overridepublic int getItemCount() {return imageResources.length;}static class ViewHolder extends RecyclerView.ViewHolder {ImageView imageView;ViewHolder(View view) {super(view);imageView = view.findViewById(R.id.imageView);}}
}

其实Viewpager2的底层是基于RecyclerView实现的,所以用法基本上差不多,都是要自定义适配器和子项布局,在适配器中实现布局加载,控件的初始化和数据绑定等操作。

🚗step3 在页面中使用

package com.example.viewpager2test;import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;
import java.util.ArrayList;
import java.util.List;public class MainActivity extends AppCompatActivity {private ViewPager2 viewPager;private LinearLayout indicatorLayout;private BannerAdapter adapter;private Handler handler = new Handler(Looper.getMainLooper());private Runnable autoScrollRunnable;private int currentPage = 0;private static final long AUTO_SCROLL_DELAY = 2000; // 3秒轮播间隔private static final int INITIAL_POSITION = 1000; // 初始位置@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);EdgeToEdge.enable(this);// 初始化视图viewPager = findViewById(R.id.viewPager);indicatorLayout = findViewById(R.id.indicatorLayout);// 创建图片资源列表List<Integer> images = new ArrayList<>();images.add(R.drawable.image1);images.add(R.drawable.image2);images.add(R.drawable.image3);images.add(R.drawable.image4);// 设置适配器adapter = new BannerAdapter(images);viewPager.setAdapter(adapter);// 设置初始位置(实现无限循环)viewPager.setCurrentItem(INITIAL_POSITION, false);currentPage = INITIAL_POSITION;// 添加指示器setupIndicators(images.size());// 设置页面变化监听器viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {@Overridepublic void onPageSelected(int position) {super.onPageSelected(position);currentPage = position;updateIndicators(position % images.size());}});// 设置自动轮播autoScrollRunnable = new Runnable() {@Overridepublic void run() {if (currentPage == adapter.getItemCount() - 1) {currentPage = INITIAL_POSITION;viewPager.setCurrentItem(currentPage, false);} else {viewPager.setCurrentItem(++currentPage, true);}handler.postDelayed(this, AUTO_SCROLL_DELAY);}};// 触摸暂停功能viewPager.setOnTouchListener((v, event) -> {stopAutoScroll();return false;});}@Overrideprotected void onResume() {super.onResume();startAutoScroll();}@Overrideprotected void onPause() {super.onPause();stopAutoScroll();}private void setupIndicators(int count) {indicatorLayout.removeAllViews();for (int i = 0; i < count; i++) {ImageView indicator = new ImageView(this);indicator.setImageResource(i == 0 ? R.drawable.indicator_active : R.drawable.indicator_inactive);LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(dpToPx(8), dpToPx(8));params.setMargins(dpToPx(4), 0, dpToPx(4), 0);indicator.setLayoutParams(params);indicatorLayout.addView(indicator);}}private void updateIndicators(int position) {for (int i = 0; i < indicatorLayout.getChildCount(); i++) {ImageView indicator = (ImageView) indicatorLayout.getChildAt(i);indicator.setImageResource(i == position ?R.drawable.indicator_active : R.drawable.indicator_inactive);}}private void startAutoScroll() {handler.postDelayed(autoScrollRunnable, AUTO_SCROLL_DELAY);}private void stopAutoScroll() {handler.removeCallbacks(autoScrollRunnable);}private int dpToPx(int dp) {float density = getResources().getDisplayMetrics().density;return Math.round(dp * density);}// 适配器类static class BannerAdapter extends RecyclerView.Adapter<BannerAdapter.ViewHolder> {private final List<Integer> images;public BannerAdapter(List<Integer> images) {this.images = images;}@NonNull@Overridepublic ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_banner, parent, false);return new ViewHolder(view);}@Overridepublic void onBindViewHolder(@NonNull ViewHolder holder, int position) {int realPosition = position % images.size();holder.imageView.setImageResource(images.get(realPosition));}@Overridepublic int getItemCount() {return Integer.MAX_VALUE; // 实现无限循环}static class ViewHolder extends RecyclerView.ViewHolder {ImageView imageView;public ViewHolder(@NonNull View itemView) {super(itemView);imageView = itemView.findViewById(R.id.imageView);}}}
}

关键点分析

无限循环原理
// 自动轮播系统
autoScrollRunnable = new Runnable() {@Overridepublic void run() {if (currentPage == adapter.getItemCount() - 1) {currentPage = INITIAL_POSITION;viewPager.setCurrentItem(currentPage, false); // 无动画跳转} else {viewPager.setCurrentItem(++currentPage, true); // 平滑滚动}handler.postDelayed(this, AUTO_SCROLL_DELAY);}
};
@Overridepublic int getItemCount() {return Integer.MAX_VALUE; // 实现无限循环}

通过设置Integer的最大值(2147483646)达到无限循环效果,同时通过setCurrentItem(INITIAL_POSITION)设定初始位置在索引等于1000的位置确保起始点在中间位置,每次轮播时通过position % images.size()计算实际索引获取真实图片位置。

🍟如何自定义Indicator

private void setupIndicators(int count) {indicatorLayout.removeAllViews();for (int i = 0; i < count; i++) {ImageView indicator = new ImageView(this);indicator.setImageResource(i == 0 ? R.drawable.indicator_active : R.drawable.indicator_inactive);LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(dpToPx(8), dpToPx(8));params.setMargins(dpToPx(4), 0, dpToPx(4), 0);indicator.setLayoutParams(params);indicatorLayout.addView(indicator);}}private void updateIndicators(int position) {for (int i = 0; i < indicatorLayout.getChildCount(); i++) {ImageView indicator = (ImageView) indicatorLayout.getChildAt(i);indicator.setImageResource(i == position ?R.drawable.indicator_active : R.drawable.indicator_inactive);}}

🛌内置IndicatorView使用方法介绍,没有提供任何自定义属性

方法名描述
setIndicatorRadius(float indicatorRadius)设置圆点半径
setIndicatorSpacing(float indicatorSpacing)设置圆点间距
setIndicatorStyle(@IndicatorStyle int indicatorStyle)设置圆点切换动画,内置五种切换动画
setIndicatorColor(@ColorInt int indicatorColor)设置默认的圆点颜色
setIndicatorSelectorColor(@ColorInt int indicatorSelectorColor)设置选中的圆点颜色
setParams(RelativeLayout.LayoutParams params)设置IndicatorView在banner中的位置,默认底部居中,距离底部10dp
setIndicatorRatio(float indicatorRatio)设置indicator比例,拉伸圆为矩形,设置越大,拉伸越长,默认1.0
setIndicatorSelectedRadius(float indicatorSelectedRadius)设置选中的圆角,默认和indicatorRadius值一致,可单独设置选中的点大小
setIndicatorSelectedRatio(float indicatorSelectedRatio)设置选中圆比例,拉伸圆为矩形,控制该比例,默认比例和indicatorRatio一致,默认值1.0
atorRatio(float indicatorRatio)设置indicator比例,拉伸圆为矩形,设置越大,拉伸越长,默认1.0
setIndicatorSelectedRadius(float indicatorSelectedRadius)设置选中的圆角,默认和indicatorRadius值一致,可单独设置选中的点大小
setIndicatorSelectedRatio(float indicatorSelectedRatio)设置选中圆比例,拉伸圆为矩形,控制该比例,默认比例和indicatorRatio一致,默认值1.0

文章转载自:

http://laclMOFL.cjxqx.cn
http://bsehfj78.cjxqx.cn
http://vODhAneN.cjxqx.cn
http://cTprjy2B.cjxqx.cn
http://5n1sRi5x.cjxqx.cn
http://E2XWneM6.cjxqx.cn
http://BGUUhNl3.cjxqx.cn
http://ceIk1J6a.cjxqx.cn
http://hX5vWqx0.cjxqx.cn
http://1SDSJJF2.cjxqx.cn
http://0itF8YZv.cjxqx.cn
http://b4YMWswX.cjxqx.cn
http://EA5cLXcd.cjxqx.cn
http://dVL77NmH.cjxqx.cn
http://SZTJO8VD.cjxqx.cn
http://Ul8c8C71.cjxqx.cn
http://TEjaWivf.cjxqx.cn
http://xKlL8eiP.cjxqx.cn
http://NXvDVIPw.cjxqx.cn
http://x0Ba5f7z.cjxqx.cn
http://pkzgw7ep.cjxqx.cn
http://e4mafC8s.cjxqx.cn
http://O9K6EbE0.cjxqx.cn
http://kaZ3tx8m.cjxqx.cn
http://03QBhwdD.cjxqx.cn
http://Hubt5Fub.cjxqx.cn
http://04QPMwPy.cjxqx.cn
http://iHspAvou.cjxqx.cn
http://WJSmlTwV.cjxqx.cn
http://clYOfu4E.cjxqx.cn
http://www.dtcms.com/a/383280.html

相关文章:

  • 【前端教程】从基础到优化:一个登录页面的完善过程
  • 一文入门python中的进程、线程和协程
  • Tempus Fugit: 3靶场
  • XXL-JOB-Admin后台手动执行任务传参过长被截断问题解决
  • 【AI推理部署】Docker篇02—Docker 快速入手
  • 【C语言描述】《数据结构和算法》一 绪论与时间、空间复杂度
  • 服务器 - 从一台服务器切换至另一台服务器(损失数十条访客记录)
  • 【Android】View 交互的事件处理机制
  • 软考中级信息安全与病毒防护知识点
  • 贪心算法应用:量子密钥路径选择问题详解
  • 【算法】【链表】160.相交链表--通俗讲解
  • v-model与.aync的区别
  • 淘宝返利app的前端性能优化:从资源加载到首屏渲染的全链路优化
  • 【LeetCode】38. 外观数列
  • ZYNQ7020 Bank划分
  • 【2025】Office核心组件Microsoft word,Excel,PowerPoint详细使用指南
  • ARM编译器的__inline和 __forceinline
  • Zookeeper介绍与部署(Linux)
  • [硬件电路-216]:电场是什么?只有正电荷或只有负电荷,能产生电场吗?
  • pthread_mutex_lock函数深度解析
  • 【记录】初赛复习 Day1
  • 深入理解跳表(Skip List):原理、实现与应用
  • SciKit-Learn 全面分析 20newsgroups 新闻组文本数据集(文本分类)
  • 使用 Neo4j 和 Ollama 在本地构建知识图谱
  • 【愚公系列】《人工智能70年》018-语音识别的历史性突破(剑桥语音的黄金十年)
  • Debezium日常分享系列之:MongoDB 新文档状态提取
  • Linux 日志分析:用 ELK 搭建个人运维监控平台
  • docker内如何用ollama启动大模型
  • Flask学习笔记(二)--路由和变量
  • FlashAttention(V3)深度解析:从原理到工程实现-Hopper架构下的注意力机制优化革命