본문 바로가기

[Android/Java] 안드로이드 ViewPager2 이미지 슬라이드 만들기

꿈꾸는블로그왕 2020. 11. 11.

이미지 슬라이드는 온라인 쇼핑몰에서 고객에게 다양한 상품이미지를 보여줄때 흔히 사용됩니다.

 

이를 구현하기 위해 ViewPager2를 사용하도록 하겠습니다.

 

완성된 모습은 다음과 같습니다.

 

Gradle 추가

ViewPager2를 사용하기 위해 Gradle에 아래와 같이 Dependency를 추가해줘야 합니다.

추가로 이미지 로딩을 위해 Glide 라이브러리를 추가했습니다.

dependencies {
	// ViewPager2
	implementation "androidx.viewpager2:viewpager2:1.0.0"
    
	// Glide
	implementation 'com.github.bumptech.glide:glide:4.9.0'
	annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
}

 

 

ViewPage2 사용하기

activity_main.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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

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

    <View
        android:id="@+id/viewFadingEdge"
        android:layout_width="match_parent"
        android:layout_height="55dp"
        android:background="@drawable/bg_fading_edge"
        app:layout_constraintBottom_toBottomOf="@id/sliderViewPager" />

    <LinearLayout
        android:id="@+id/layoutIndicators"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center"
        android:paddingBottom="8dp"
        app:layout_constraintBottom_toBottomOf="@id/viewFadingEdge"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

ViewPager2를 레이아웃 파일에 추가했습니다. 

View는이미지 아래에 흐릿한 효과를 보여주기 위해 사용했습니다.

LinearLayout를 사용하여 이미지가 변경될 때 위치를 보여주는 Indicator를 보여줄 예정입니다. 해당 레이아웃 자식 뷰는 액티비티에서 추가 할 예정입니다.

 

 

ViewPager2는 RecyclerView를 기반으로 만들어진 위젯이기 때문에 RecyclerView에 필요한 아이템 레이아웃과 Adapter를 아래와 같이 작성합니다.

 

item_slider.xml 

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/imageSlider"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:contentDescription="@string/app_name"
    android:scaleType="centerCrop" />

 

ImageSliderAdapter.java

public class ImageSliderAdapter extends RecyclerView.Adapter<ImageSliderAdapter.MyViewHolder> {
    private Context context;
    private String[] sliderImage;

    public ImageSliderAdapter(Context context, String[] sliderImage) {
        this.context = context;
        this.sliderImage = sliderImage;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_slider, parent, false);
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        holder.bindSliderImage(sliderImage[position]);
    }

    @Override
    public int getItemCount() {
        return sliderImage.length;
    }

    public class MyViewHolder extends RecyclerView.ViewHolder {

        private ImageView mImageView;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            mImageView = itemView.findViewById(R.id.imageSlider);
        }

        public void bindSliderImage(String imageURL) {
            Glide.with(context)
                    .load(imageURL)
                    .into(mImageView);
        }
    }
}

sliderImage 배열에 URL을 담을 예정입니다.

Glide 라이브러리를 사용하여 ImageView에 이미지를 로딩합니다.

 

 

그럼 이제 MainActivity 파일에서 구현해보도록 하겠습니다.

 

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private ViewPager2 sliderViewPager;
    private LinearLayout layoutIndicator;

    private String[] images = new String[] {
            "https://cdn.pixabay.com/photo/2019/12/26/10/44/horse-4720178_1280.jpg",
            "https://cdn.pixabay.com/photo/2020/11/04/15/29/coffee-beans-5712780_1280.jpg",
            "https://cdn.pixabay.com/photo/2020/03/08/21/41/landscape-4913841_1280.jpg",
            "https://cdn.pixabay.com/photo/2020/09/02/18/03/girl-5539094_1280.jpg",
            "https://cdn.pixabay.com/photo/2014/03/03/16/15/mosque-279015_1280.jpg"
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sliderViewPager = findViewById(R.id.sliderViewPager);
        layoutIndicator = findViewById(R.id.layoutIndicators);

        sliderViewPager.setOffscreenPageLimit(1);
        sliderViewPager.setAdapter(new ImageSliderAdapter(this, images));

        sliderViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
                setCurrentIndicator(position);
            }
        });

        setupIndicators(images.length);
    }

    private void setupIndicators(int count) {
        ImageView[] indicators = new ImageView[count];
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);

        params.setMargins(16, 8, 16, 8);

        for (int i = 0; i < indicators.length; i++) {
            indicators[i] = new ImageView(this);
            indicators[i].setImageDrawable(ContextCompat.getDrawable(this,
                    R.drawable.bg_indicator_inactive));
            indicators[i].setLayoutParams(params);
            layoutIndicator.addView(indicators[i]);
        }
        setCurrentIndicator(0);
    }

    private void setCurrentIndicator(int position) {
        int childCount = layoutIndicator.getChildCount();
        for (int i = 0; i < childCount; i++) {
            ImageView imageView = (ImageView) layoutIndicator.getChildAt(i);
            if (i == position) {
                imageView.setImageDrawable(ContextCompat.getDrawable(
                        this,
                        R.drawable.bg_indicator_active
                ));
            } else {
                imageView.setImageDrawable(ContextCompat.getDrawable(
                        this,
                        R.drawable.bg_indicator_inactive
                ));
            }
        }
    }
}

이미지는 픽사베이 사이트를 통해서 가져옵니다. https://pixabay.com/

 

 

setOffScreenPageLimit() 함수를 통해서 ViewPager가 상태를 유지할 수 있는 페이지의 갯수를 지정할 수 있습니다. setAdapter()함수를 통해 어댑터를 연결해 줍니다. registerOnPageChangeCallback() 함수를 사용하여 페이지가 변경되었을때 콜백을 받아 Indicator를 변경할 수 있도록 했습니다. 해당 페이지가 selected 되었을때 setCurrentIndicator() 함수 해당 위치를 전달하여 Indicator가 변경될 수 있도록 했습니다.

 

setupIndicators() 함수는 이미지의 갯수를 만큼 ImageView를 생성하여, LinearLayout에 addView()를 통해 추가합니다.

 

아래는 이미지 아래 흐릿한 효과를 주기위한 Drawable 파일입니다.

 

bg_fading_edge.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <gradient
        android:angle="270"
        android:startColor="@android:color/transparent"
        android:endColor="#111111" />

</shape>

 

Indicator가 활성/비활성화에 따라 색상 및 크기를 다르게 설정합니다.

bg_indicator_active.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">

    <size
        android:width="12dp"
        android:height="12dp" />

    <solid
        android:color="#6200EE" />

</shape>

bg_indicator_inactive.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">

    <size
        android:width="8dp"
        android:height="8dp" />

    <solid
        android:color="#eeeeee" />

</shape>

 

댓글