Android

[Android] ViewPager2에 custom indicator 연결하기

도우 2024. 3. 18. 19:16
반응형

https://ehdnsdlek.tistory.com/31

저번 게시글에는 ViewPager2를 이용해서 자동으로 Slide 되게끔 만들어 보았습니다.
거기에 추가로 좌측 하단에 Indicator를 만들어 보겠습니다

좌측 하단에 Indicator가 추가된 모습

 

 

1. customView를 만들기 위해 클래스 만들기

기초 코드는 https://black-jin0427.tistory.com/95 여기서 가져왔습니다.

// CircleIndicator.java

public class CircleIndicator extends LinearLayout {

    private Context mContext;

    private int mDefaultCircle;
    private int mSelectCircle;

    private List<ImageView> imageDot = new ArrayList<>();

    // 4.5dp를 픽셀 단위로 바꿉니다.
    private final float temp = TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, 4.5f, getResources().getDisplayMetrics());

    public CircleIndicator(Context context) {
        super(context);
        mContext = context;
    }

    public CircleIndicator(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
    }

    /**
     * 기본 점 생성
     * @param count 점의 갯수
     * @param defaultCircle 기본 점의 이미지
     * @param selectCircle 선택된 점의 이미지
     * @param position 선택된 점의 포지션
     */
    public void createDotPanel(int count, int defaultCircle, int selectCircle, int position) {
        this.removeAllViews();

        mDefaultCircle = defaultCircle;
        mSelectCircle = selectCircle;

        for (int i = 0; i < count; i++) {
            ImageView dot = new ImageView(mContext);
            dot.setPadding((int) temp, 0, (int) temp, 0);
            imageDot.add(dot);

            this.addView(dot);
        }

        // 인덱스 선택
        selectDot(position);
    }

    /**
     * 선택된 점 표시
     * @param position
     */
    public void selectDot(int position) {
        for (int i = 0; i < imageDot.size(); i++) {
            if (i == position) {
                imageDot.get(i).setImageResource(mSelectCircle);
            } else {
                imageDot.get(i).setImageResource(mDefaultCircle);
            }
        }
    }
}

 

2. CustomView 추가하기

자신의 패키지 이름에 맞춰서 코드를 수정해서 사용하시면 됩니다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/slideViewPager"
        android:layout_width="match_parent"
        android:layout_height="220dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.example.toptoon.CircleIndicator // 자신의 패키지에 맞게 수정하기
        android:id="@+id/slideIndicator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginBottom="8dp"
        android:background="@android:color/transparent"
        app:layout_constraintBottom_toBottomOf="@id/slideViewPager"
        app:layout_constraintStart_toStartOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

 

3. Indicator 레이아웃 작성하기

res/drawable 폴더에 생성하시면 됩니다.

// indicator_selected.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@color/red" /> <!-- 주황색 지정 -->
    <size android:width="20dp"
        android:height="10dp"/>

</shape>
// indicator_unselected.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@color/gray" /> <!-- 회색 지정 -->
    <size android:width="10dp"
        android:height="10dp"/>
</shape>

 

4. ViewPager2와 Indicator 연결하기

CircleIndicator의 createDotPanel 메소드를 사용해서 인디케이터를 초기화 합니다.
여기서 인디케이터 점의 수(imagesLength)와 drawable 리소스를 지정합니다.

또한 ViewPager2에 어댑터를 설정해주어야 합니다. SlideImageAdapter 인스턴스를 생성하고,
slideViewPager.setAdapter(adapter)를 통해 ViewPager2에 설정합니다.

 

@Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        binding = FragmentHomeBinding.inflate(inflater, container, false);

        SlideImageAdapter adapter = new SlideImageAdapter(getContext());
        slideViewPager = binding.slideViewPager;
        slideViewPager.setAdapter(adapter);

	int imagesLength = adapter.getImageArrayLength(); // 이미지 개수 가져오기

        // 인디케이터 초기화
        CircleIndicator circleIndicator = binding.slideIndicator;
        // 실제 이미지 수에 맞게 점 개수를 조정
        circleIndicator.createDotPanel(imagesLength, R.drawable.indicator_unselected, R.drawable.indicator_selected, 0);


        slideViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
       		@Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
                // 실제 페이지 인덱스를 계산합니다.
                // 무한 스크롤을 구현하는 경우가 아니라면, position을 직접 사용할 수 있습니다.
                int realPosition = position % slideViewPager.getAdapter().getItemCount();
                // 선택된 페이지에 해당하는 인디케이터 점을 강조 표시합니다.
                circleIndicator.selectDot(realPosition);
            }

            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                // 스크롤 중 이벤트를 처리할 필요가 있다면 여기에 로직을 추가합니다.
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                // 페이지 스크롤 상태 변경 이벤트를 처리할 필요가 있다면 여기에 로직을 추가합니다.
            }
        });



        return binding.getRoot();
    }

}

 

반응형