欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android Viewpager2實(shí)現(xiàn)無(wú)限輪播圖效果

 更新時(shí)間:2025年09月19日 11:45:58   作者:豆鯊包  
ViewPager2支持水平/垂直滾動(dòng)及RTL,通過(guò)設(shè)置最大值和模運(yùn)算實(shí)現(xiàn)無(wú)限輪播,自定義Adapter與IndicatorView可靈活配置動(dòng)畫、顏色等屬性

ViewPager2是Android Jetpack組件的一部分,用于實(shí)現(xiàn)屏幕間平滑的水平滾動(dòng)效果。相比其前身ViewPager,ViewPager2在性能上有所提升,且支持RTL(從右到左的布局)和垂直滾動(dòng)等特性。其用法簡(jiǎn)潔,可以很容易地與RecyclerView Adapter集成,以展示大量數(shù)據(jù)集。

Android Viewpager2實(shí)現(xiàn)無(wú)限輪播圖

??先上效果圖

這就類似于常用軟件首頁(yè)的廣告輪播圖,這里只是簡(jiǎn)單顯示了幾張圖片,當(dāng)然你還可以自定義更精美的子項(xiàng)布局來(lái)實(shí)現(xiàn)想要的效果。

??使用步驟

??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; // 圖片資源數(shù)組
    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);
        }
    }
}

其實(shí)Viewpager2的底層是基于RecyclerView實(shí)現(xiàn)的,所以用法基本上差不多,都是要自定義適配器和子項(xiàng)布局,在適配器中實(shí)現(xiàn)布局加載,控件的初始化和數(shù)據(jù)綁定等操作。

??step3 在頁(yè)面中使用

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);
        // 創(chuàng)建圖片資源列表
        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);
        // 設(shè)置適配器
        adapter = new BannerAdapter(images);
        viewPager.setAdapter(adapter);
        // 設(shè)置初始位置(實(shí)現(xiàn)無(wú)限循環(huán))
        viewPager.setCurrentItem(INITIAL_POSITION, false);
        currentPage = INITIAL_POSITION;
        // 添加指示器
        setupIndicators(images.size());
        // 設(shè)置頁(yè)面變化監(jiān)聽(tīng)器
        viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
                currentPage = position;
                updateIndicators(position % images.size());
            }
        });
        // 設(shè)置自動(dòng)輪播
        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; // 實(shí)現(xiàn)無(wú)限循環(huán)
        }
        static class ViewHolder extends RecyclerView.ViewHolder {
            ImageView imageView;
            public ViewHolder(@NonNull View itemView) {
                super(itemView);
                imageView = itemView.findViewById(R.id.imageView);
            }
        }
    }
}

關(guān)鍵點(diǎn)分析

無(wú)限循環(huán)原理
// 自動(dòng)輪播系統(tǒng)
autoScrollRunnable = new Runnable() {
    @Override
    public void run() {
        if (currentPage == adapter.getItemCount() - 1) {
            currentPage = INITIAL_POSITION;
            viewPager.setCurrentItem(currentPage, false); // 無(wú)動(dòng)畫跳轉(zhuǎn)
        } else {
            viewPager.setCurrentItem(++currentPage, true); // 平滑滾動(dòng)
        }
        handler.postDelayed(this, AUTO_SCROLL_DELAY);
    }
};
@Override
        public int getItemCount() {
            return Integer.MAX_VALUE; // 實(shí)現(xiàn)無(wú)限循環(huán)
        }

通過(guò)設(shè)置Integer的最大值(2147483646)達(dá)到無(wú)限循環(huán)效果,同時(shí)通過(guò)setCurrentItem(INITIAL_POSITION)設(shè)定初始位置在索引等于1000的位置確保起始點(diǎn)在中間位置,每次輪播時(shí)通過(guò)position % images.size()計(jì)算實(shí)際索引獲取真實(shí)圖片位置。

??如何自定義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);
        }
    }

??內(nèi)置IndicatorView使用方法介紹,沒(méi)有提供任何自定義屬性

方法名描述
setIndicatorRadius(float indicatorRadius)設(shè)置圓點(diǎn)半徑
setIndicatorSpacing(float indicatorSpacing)設(shè)置圓點(diǎn)間距
setIndicatorStyle(@IndicatorStyle int indicatorStyle)設(shè)置圓點(diǎn)切換動(dòng)畫,內(nèi)置五種切換動(dòng)畫
setIndicatorColor(@ColorInt int indicatorColor)設(shè)置默認(rèn)的圓點(diǎn)顏色
setIndicatorSelectorColor(@ColorInt int indicatorSelectorColor)設(shè)置選中的圓點(diǎn)顏色
setParams(RelativeLayout.LayoutParams params)設(shè)置IndicatorView在banner中的位置,默認(rèn)底部居中,距離底部10dp
setIndicatorRatio(float indicatorRatio)設(shè)置indicator比例,拉伸圓為矩形,設(shè)置越大,拉伸越長(zhǎng),默認(rèn)1.0
setIndicatorSelectedRadius(float indicatorSelectedRadius)設(shè)置選中的圓角,默認(rèn)和indicatorRadius值一致,可單獨(dú)設(shè)置選中的點(diǎn)大小
setIndicatorSelectedRatio(float indicatorSelectedRatio)設(shè)置選中圓比例,拉伸圓為矩形,控制該比例,默認(rèn)比例和indicatorRatio一致,默認(rèn)值1.0
atorRatio(float indicatorRatio)設(shè)置indicator比例,拉伸圓為矩形,設(shè)置越大,拉伸越長(zhǎng),默認(rèn)1.0
setIndicatorSelectedRadius(float indicatorSelectedRadius)設(shè)置選中的圓角,默認(rèn)和indicatorRadius值一致,可單獨(dú)設(shè)置選中的點(diǎn)大小
setIndicatorSelectedRatio(float indicatorSelectedRatio)設(shè)置選中圓比例,拉伸圓為矩形,控制該比例,默認(rèn)比例和indicatorRatio一致,默認(rèn)值1.0

到此這篇關(guān)于Android Viewpager2實(shí)現(xiàn)無(wú)限輪播圖效果的文章就介紹到這了,更多相關(guān)Android Viewpager2輪播圖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論