长风吴彦祖 發表於 2025-10-13 09:17:02

Android使用ViewPager2实现简单的轮播图的代码示例

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>一、轮播图的简单介绍</li><li>二、轮播图的实现步骤</li><ul class="second_class_ul"><li>1.绘制轮播图页面</li><li>2.设置ViewPager2的子布局</li><li>3.编写ViewPager2的适配器</li><li>4.编写Carousel类具体实现轮播图</li><li>5.实现自动轮播</li><li>6.触摸时停止自动轮播</li></ul><li>三、完整代码</li><ul class="second_class_ul"></ul></ul></div><p class="maodian"></p><h2>一、轮播图的简单介绍</h2>
<p><strong>轮播图</strong>(Carousel)是一种在有限空间内循环展示多个内容项的UI组件,用户可以通过滑动或自动播放的方式浏览不同的内容,在有限的空间中展示更多的内容。</p>
<p>实现轮播图主要有两种方式,首尾添加法和取余法,这里主要讲解首尾添加法的实现。</p>
<p class="maodian"></p><h2>二、轮播图的实现步骤</h2>
<p class="maodian"></p><h3>1.绘制轮播图页面</h3>
<p>添加一个ViewPager2作为轮播图的容器,并添加LinearLayout放置指示图标</p>
<div class="jb51code"><pre class="brush:xml;">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;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"&gt;

    &lt;androidx.viewpager2.widget.ViewPager2
      android:id="@+id/viewpager2"
      android:layout_width="match_parent"
      android:layout_height="match_parent" &gt;
    &lt;/androidx.viewpager2.widget.ViewPager2&gt;
&lt;LinearLayout
    android:id="@+id/botttom_viewpager2"
    android:layout_width="wrap_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"
   &gt;
&lt;/LinearLayout&gt;

&lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;
</pre></div>
<p class="maodian"></p><h3>2.设置ViewPager2的子布局</h3>
<p>新建xml文件,绘制ViewPager2的子布局</p>
<div class="jb51code"><pre class="brush:xml;">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"&gt;

    &lt;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"/&gt;
&lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;

</pre></div>
<p class="maodian"></p><h3>3.编写ViewPager2的适配器</h3>
<p>因为ViewPager2实现基于RecyclerView,因此这里直接继承RecyclerView.Adapter</p>
<p>这里我们使用Glide来加载图片。</p>
<blockquote><p><strong>Glide</strong>&nbsp;是一个专注于平滑滚动的 Android 图片加载库。</p>
<p><strong>优点:</strong></p>
<p>1.使用简单,并且支持多种图片格式,既可以获取网络资源又可以获取本地资源,不用处理网络请求、缓存、内存管理、图片解码等复杂逻辑;</p>
<p>2.性能优秀:自动管理 Bitmap 内存,防止内存溢出,可以自动根据ImageView调整图片大小,节省内存。</p></blockquote>
<div class="jb51code"><pre class="brush:java;">public class ImageAdapter extends RecyclerView.Adapter&lt;ImageAdapter.ImageViewHolder&gt; {
    private List&lt;Integer&gt; images;
    private Context context;
    public ImageAdapter(List&lt;Integer&gt; 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);
      }
    }

</pre></div>
<p class="maodian"></p><h3>4.编写Carousel类具体实现轮播图</h3>
<div class="jb51code"><pre class="brush:java;">public class Carousel {
    private Context mContext;
    private LinearLayout dotLinearLayout;
    private List&lt;ImageView&gt; mImageList=new ArrayList&lt;&gt;();//标志点集合
    private List&lt;Integer&gt; originalImages=new ArrayList&lt;&gt;();//轮播图图片资源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&lt;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);
                }
            }
      });
    }
}
</pre></div>
<p>在这里简单解释一下取余法的实现原理</p>
<p><strong>取余法实现</strong></p>
<p>设置一个很大的数,通过取余运算获取真实位置,以实现无限循环的效果</p>
<div class="jb51code"><pre class="brush:java;">      真实数据: (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, ...
</pre></div>
<p>公式: 真实位置 = 虚拟位置 % 图片数量</p>
<p>开始时从中间位置开始,保证有足够的空间向左滑动,并且避免在边界处出现问题</p>
<p>优点:实现简单,不需要修改数据源</p>
<p>缺点:虽然虚拟位置很大,但RecyclerView会回收视图</p>
<p class="maodian"></p><h3>5.实现自动轮播</h3>
<p>使用Handler实现自动轮播效果,在初始化Carousel时同时注册Handler</p>
<div class="jb51code"><pre class="brush:java;">    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());
    }
</pre></div>
<p>在Carousel中编写控制Handler的方法</p>
<div class="jb51code"><pre class="brush:java;"> //开启自动轮播
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(autoScrollRunnable);
      AUTO_SCROLL=false;
    }
</pre></div>
<p class="maodian"></p><h3>6.触摸时停止自动轮播</h3>
<p>开启自动轮播后,用户就无法通过滑动参看想要的页面,因此我们还应实现触摸时停止自动轮播功能。</p>
<p>可以通过监听Viewpager2的滑动行为来实现触摸时停止自动轮播。</p>
<p>ViewPager2中定义了三种滚动状态:</p>
<div class="jb51code"><pre class="brush:java;">三种滚动状态常量
// 在 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;// 自动滑动状态,页面正在自动滑动到目标位置
</pre></div>
<p>我们通过对三种状态进行分别处理来实现想要的效果。</p>
<div class="jb51code"><pre class="brush:java;"> viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageSelected(int position){
                for(int i=0;i&lt;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&amp;&amp;AUTO_SCROLL) {
                  handler.removeCallbacks(autoScrollRunnable);
                  handler.postDelayed(autoScrollRunnable,Banner_Time);
                }
            }
      });
</pre></div>
<p>到这里我们就实现了简单轮播图的全部功能。</p>
<p class="maodian"></p><h2>三、完整代码</h2>
<p>下面是实现轮播图的完整代码,以作参考。</p>
<div class="jb51code"><pre class="brush:java;">public class Carousel {
    private Context mContext;
    private LinearLayout dotLinearLayout;
    private List&lt;ImageView&gt; mImageList=new ArrayList&lt;&gt;();
    private List&lt;Integer&gt; originalImages=new ArrayList&lt;&gt;();
    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,false);
      viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageSelected(int position){
                for(int i=0;i&lt;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&amp;&amp;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&lt;ImageAdapter.ImageViewHolder&gt; {
    private List&lt;Integer&gt; images;
    private Context context;
    public ImageAdapter(List&lt;Integer&gt; 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);
      }
    }
}
</pre></div>
<p>最终效果展示如下</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202510/2025101391627501.gif" /></p>
<p>以上就是Android使用ViewPager2实现简单的轮播图的代码示例的详细内容,更多关于Android ViewPager2轮播图的资料请关注琼殿技术社区其它相关文章!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>Android&nbsp;Viewpager2实现无限轮播图效果</li><li>Android实现自动变换大小的组件ViewPager2</li><li>Android ViewPager2 + Fragment 联动效果的实现思路</li><li>Android&nbsp;ViewPager2&nbsp;使用及自定义指示器视图实现</li><li>Android如何使用ViewPager2实现页面滑动切换效果</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: Android使用ViewPager2实现简单的轮播图的代码示例