[Android] ViewPager2 - Runnable 객체로 자동으로 이미지 slide 하기
탑툰을 클론코딩 하는 도중 이미지가 자동으로 slide 되는 UI를 구현해야 했다.
ViewPager2를 이용해서 구현해보도록 합시다
1. ViewPager2 선언
MainActivity에 HomeFragment가 존재하고, HomeFragment안에 ViewPager2를 다음과 같이 작성했습니다.
// fragment_home.xml
<?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" />
</androidx.constraintlayout.widget.ConstraintLayout>
2. ImageView가 포함된 페이지 레이아웃 만들기
ViewPager2의 각 페이지에 사용될 ImageView를 포함하는 레이아웃 XML 파일을 만들어야 합니다.
저는 사진만 들어가므로 ImageView 하나만 작성했습니다.
즉, Fragment에 뷰들을 관리하기 위해 ViewPager2를 작성했고, 뷰를 띄워줄 레이아웃을 지금 작성합니다.
// slide_image_row.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/slideImageRow"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" />
</FrameLayout>
3. SlideImageAdapter 구현
ViewPager2는 내부적으로 RecycleView의 구현을 사용하기에 RecyclerView를 구현할 때와 유사하게 어댑터를 구현해야 합니다. ViewHolder 패턴을 사용하기에 뷰를 재사용하고, 각 페이지에 해당하는 ImageView를 보관하고 관리합니다.
// SlideImageAdapter.java
public class SlideImageAdapter extends RecyclerView.Adapter<SlideImageAdapter.SlideImageViewHolder> {
private Context context;
private int[] images = new int[]{R.drawable.slide_add_1, R.drawable.slide_add_2, R.drawable.slide_add_3, R.drawable.slide_add_4, R.drawable.slide_add_5,
R.drawable.slide_add_6, R.drawable.slide_add_7};
// 이미지 파일 로컬에서 drawable에 저장함
SlideImageAdapter(Context context) {
this.context = context;
}
@NonNull
@Override
public SlideImageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
SlideImageRowBinding binding = SlideImageRowBinding.inflate(LayoutInflater.from(context),parent,false);
return new SlideImageViewHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull SlideImageViewHolder holder, int position) {
holder.binding.slideImageRow.setImageResource(images[position]);
} // 각 페이지에 대한 데이터를 뷰에 바인딩할 때 호출함
@Override
public int getItemCount() {
return images.length;
}
static class SlideImageViewHolder extends RecyclerView.ViewHolder {
SlideImageRowBinding binding;
SlideImageViewHolder(SlideImageRowBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
}
3. 자동 슬라이딩 구현
Runnable 객체는 자바의 멀티스레딩 기능 중 하나로, 별도의 스레드에서 실행할 코드 블록을 정의합니다.
// HomeFragment.java
public class HomeFragment extends Fragment {
private ViewPager2 slideViewPager;
private int currentItem = 0;
private FragmentHomeBinding binding;
private Handler sliderHandler = new Handler();
// Handler는 메시지나 Runnable 객체를 특정 시간 이후에 실행하도록 스케줄링함
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = FragmentHomeBinding.inflate(inflater, container, false);
slideViewPager = binding.slideViewPager;
slideViewPager.setAdapter(new SlideImageAdapter(getContext()));
// 자동 슬라이딩 구현
Runnable runnable = new Runnable() {
@Override
public void run() {
if (currentItem >= slideViewPager.getAdapter().getItemCount()) {
currentItem = 0;
}
slideViewPager.setCurrentItem(currentItem++, true);
// 전환할 페이지 인덱스와 애니메이션을 적용할지 여부(true)
sliderHandler.postDelayed(this, 3000);
// 3초 후 다음 이미지로 전환, 재귀적 호출
}
};
sliderHandler.postDelayed(runnable, 3000);
return binding.getRoot();
}
@Override
public void onDestroyView() {
super.onDestroyView();
sliderHandler.removeCallbacksAndMessages(null); // 리소스 정리
binding = null; // 메모리 누수 방지
}
}
결과
기능적인 부분에서는 이상이 없지만, 애니메이션 속도가 가끔 너무 빠르게 지나가는 경우가 있다.
또한 사용자가 직접 스와이프 하는 와중에도 이미지가 바뀌기도 한다.
다음에는 Runnable과 Handler, 부드럽게 애니메이션을 적용하는 방법을 공부해 포스팅 해보도록 하겠습니다.
다음은 ViewPager2 좌측 하단에 Indicator를 만들어보도록 하겠습니다.
https://ehdnsdlek.tistory.com/32
[Android] ViewPager2에 custom indicator 연결하기
https://ehdnsdlek.tistory.com/31 저번 게시글에는 ViewPager2를 이용해서 자동으로 Slide 되게끔 만들어 보았습니다. 거기에 추가로 좌측 하단에 Indicator를 만들어 보겠습니다 1. customView를 만들기 위해 클래
ehdnsdlek.tistory.com