ViewPager, RecycleView implement carousel chart

1.ViewPager implements carousel graphics effects.

1) In layout, PageIndicatorView carousel View

 <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:orientation="vertical">

        <androidx.viewpager2.widget.ViewPager2
            android:id="@ + id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <com.example.viewpager.indicator.PageIndicatorView
            android:id="@ + id/indicator1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true" />
    </RelativeLayout>

2) In Activity

 List<String> list = new ArrayList<>();
        for (int i = 0; i < 5; i + + ) {
            list.add("pos: " + i);
        }
        viewPager = findViewById(R.id.viewpager);
        indicator1 = findViewById(R.id.indicator1);
        //Set whether ViewPager scrolls horizontally or vertically
        viewPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
        viewPager.setAdapter(new MyPageAdapter2(this, list));

        indicator1.initIndicator(list.size());

        viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                super.onPageScrolled(position, positionOffset, positionOffsetPixels);
            }

            @Override
            public void onPageSelected(int position) {
                 //When the page slides, switch the indicator
                if (indicator1.getChildCount() > 0) {
                    indicator1.setSelectedPage(position % indicator1.getChildCount());
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                super.onPageScrollStateChanged(state);
            }
        });

2.RecycleView implements carousel effect:

1) In Layout

 <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_marginTop="20dp">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@ + id/recycle_view"
            android:layout_width="match_parent"
            android:layout_height="200dp"/>

        <com.example.viewpager.indicator.PageIndicatorView
            android:id="@ + id/indicator2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true" />
    </RelativeLayout>

2) In Activity:

 recyclerView = findViewById(R.id.recycle_view);
        indicator2 = findViewById(R.id.indicator2);
        indicator2.initIndicator(list.size());
        
        LinearLayoutManager manager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        recyclerView.setLayoutManager(manager);
        recyclerView.setAdapter(new MyPageAdapter2(this, list));

        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                int firstReal = manager.findFirstVisibleItemPosition();
                View viewFirst = manager.findViewByPosition(firstReal);
                float width = viewFirst.getWidth();
                if (width != 0 & amp; & amp; viewFirst != null) {
                    float right = viewFirst.getRight();
                    float ratio = right / width;
                    if (ratio > 0.8) {
                        if (currentIndex != firstReal) {
                            currentIndex = firstReal;
                            indicator2.setSelectedPage(currentIndex);
                        }
                    } else if (ratio < 0.2) {
                        if (currentIndex != firstReal + 1) {
                            currentIndex = firstReal + 1;
                            indicator2.setSelectedPage(currentIndex);
                        }
                    }
                }
            }
        });

3. Sliding indicator:

public class PageIndicatorView extends LinearLayout {

    private Context mContext = null;
    private int dotSize = 5; // size of indicator (dp)
    private int margins = 5; // indicator spacing (dp)
    private List<View> indicatorViews = null; // Store indicators

    public PageIndicatorView(Context context) {
        this(context, null);
    }

    public PageIndicatorView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PageIndicatorView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        this.mContext = context;

        setGravity(Gravity.CENTER);
        setOrientation(HORIZONTAL);

        dotSize = Utils.dip2px(dotSize);
        margins = Utils.dip2px( margins);
    }

    /**
     * Initialization indicator, the first page is selected by default
     *
     * @param count The number of indicators, that is, the number of pages
     */
    public void initIndicator(int count) {

        if (indicatorViews == null) {
            indicatorViews = new ArrayList<>();
        } else {
            indicatorViews.clear();
            removeAllViews();
        }
        View view;
        LayoutParams params = new LayoutParams(dotSize, dotSize);
        params.setMargins(margins, margins, margins, margins);
        for (int i = 0; i < count; i + + ) {
            view = new View(mContext);
            view.setBackgroundResource(R.drawable.indicator_normal);
            addView(view, params);
            indicatorViews.add(view);
        }
        if (indicatorViews.size() > 0) {
            indicatorViews.get(0).setBackgroundResource(R.drawable.indicator_active);
        }
    }

    /**
     * Set selected page
     *
     * @param selected page index, starting from 0
     */
    public void setSelectedPage(int selected) {
        for (int i = 0; i < indicatorViews.size(); i + + ) {
            if (i == selected) {
                indicatorViews.get(i).setBackgroundResource(R.drawable.indicator_active);
            } else {
                indicatorViews.get(i).setBackgroundResource(R.drawable.indicator_normal);
            }
        }
    }

}

Two small dot codes:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="#fffc9d16" />
</shape>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="#FFD9D9D9" />
</shape>

Code download:

https://download.csdn.net/download/niuyongzhi/88408862