Android

关注公众号 jb51net

关闭
首页 > 软件编程 > Android > Android Viewpager2轮播图

Android Viewpager2实现无限轮播图效果

作者:豆鲨包

ViewPager2支持水平/垂直滚动及RTL,通过设置最大值和模运算实现无限轮播,自定义Adapter与IndicatorView可灵活配置动画、颜色等属性

ViewPager2是Android Jetpack组件的一部分,用于实现屏幕间平滑的水平滚动效果。相比其前身ViewPager,ViewPager2在性能上有所提升,且支持RTL(从右到左的布局)和垂直滚动等特性。其用法简洁,可以很容易地与RecyclerView Adapter集成,以展示大量数据集。

Android Viewpager2实现无限轮播图

🏇先上效果图

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

🎍使用步骤

🏀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
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_carousel, parent, false);
        return new ViewHolder(view);
    }
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.imageView.setImageResource(imageResources[position]);
    }
    @Override
    public 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; // 初始位置
    @Override
    protected 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() {
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
                currentPage = position;
                updateIndicators(position % images.size());
            }
        });
        // 设置自动轮播
        autoScrollRunnable = new Runnable() {
            @Override
            public 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;
        });
    }
    @Override
    protected void onResume() {
        super.onResume();
        startAutoScroll();
    }
    @Override
    protected 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
        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.item_banner, parent, false);
            return new ViewHolder(view);
        }
        @Override
        public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
            int realPosition = position % images.size();
            holder.imageView.setImageResource(images.get(realPosition));
        }
        @Override
        public 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() {
    @Override
    public 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);
    }
};
@Override
        public 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

到此这篇关于Android Viewpager2实现无限轮播图效果的文章就介绍到这了,更多相关Android Viewpager2轮播图内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文