MotionLayout으로 캐러셀

Compose 방식으로 시도
Jetpack Compose는 Android에 권장되는 UI 도구 키트입니다. Compose에서 캐러셀을 추가하는 방법을 알아보세요.

Carousel은 사용자가 대략적으로 살펴볼 수 있는 요소 목록을 표시하는 맞춤 캐러셀 뷰를 빌드하는 모션 도우미 객체입니다. 이 도우미를 사용하면 MotionLayout를 활용하여 이러한 뷰를 구현하는 다른 방법과 비교할 때 Carousel의 복잡한 동작과 크기 변경을 빠르게 만들 수 있습니다.

Carousel 위젯은 시작과 끝이 있는 목록과 원형 래핑 목록을 지원합니다.

MotionLayout을 사용한 캐러셀의 작동 방식

가운데 항목이 확대된 가로 Carousel 뷰를 빌드한다고 가정해 보겠습니다.

이 기본 레이아웃에는 Carousel 항목을 나타내는 여러 뷰가 포함되어 있습니다.

다음 세 가지 상태로 MotionLayout을 만들고 ID를 부여합니다.

  • 이전
  • start
  • 다음

시작 상태가 기본 레이아웃에 해당하는 경우 이전 상태와 다음 상태에서 Carousel 항목이 각각 왼쪽과 오른쪽으로 하나씩 이동합니다.

예를 들어 그림 3의 5개 뷰를 살펴보세요. 시작 상태에서 B, C, D 뷰는 표시되고 A와 E는 화면 밖에 있다고 가정합니다. A, B, C, D의 위치가 B, C, D, E의 위치가 되도록 이전 상태를 설정합니다. 뷰는 왼쪽에서 오른쪽으로 이동합니다. 다음 상태에서는 B, C, D, E가 A, B, C, D가 있던 위치로 이동하고 뷰가 오른쪽에서 왼쪽으로 이동하는 등 반대 상황이 발생해야 합니다. 이는 그림 4에 나와 있습니다.

뷰가 원래 뷰가 시작되는 위치에서 정확히 시작해야 합니다. Carousel실제 뷰를 원래 위치로 다시 이동하지만 새 일치 콘텐츠로 다시 초기화하여 요소의 무한 컬렉션이라는 착각을 일으킵니다. 다음 다이어그램은 이 메커니즘을 보여줍니다. '상품 번호' 값에 유의하세요.)

화면전환

모션 장면 파일에 정의된 이 세 가지 제약 조건 세트를 사용하여 startnext 상태 간의 전환(앞으로)과 startprevious 상태 간의 전환(뒤로)을 만듭니다. 다음 예와 같이 동작에 대한 응답으로 전환을 트리거하는 OnSwipe 핸들러를 추가합니다.

    <Transition
        motion:constraintSetStart="@id/start"
        motion:constraintSetEnd="@+id/next"
        motion:duration="1000"
        android:id="@+id/forward">
        <OnSwipe
            motion:dragDirection="dragLeft"
            motion:touchAnchorSide="left" />
    </Transition>

    <Transition
        motion:constraintSetStart="@+id/start"
        motion:constraintSetEnd="@+id/previous"
        android:id="@+id/backward">
        <OnSwipe
            motion:dragDirection="dragRight"
            motion:touchAnchorSide="right" />
    </Transition>

이 기본 모션 장면을 만든 후 Carousel 도우미를 레이아웃에 추가하고 이전 및 다음 애니메이션을 구현하는 것과 동일한 순서로 뷰를 참조합니다.

Carousel 도우미에 다음 속성을 설정합니다.

  • app:carousel_firstView: Carousel의 첫 번째 요소를 나타내는 뷰입니다. 이 예에서는 C입니다.
  • app:carousel_previousState: 이전 상태의 ConstraintSet ID입니다.
  • app:carousel_nextState: 다음 상태의 ConstraintSet ID입니다.
  • app:carousel_backwardTransition: 시작 상태와 이전 상태 사이에 적용된 Transition ID입니다.
  • app:carousel_forwardTransition: start 상태와 next 상태 사이에 적용된 Transition ID입니다.

예를 들어 레이아웃 XML 파일에 다음과 같은 내용이 있습니다.

    <androidx.constraintlayout.motion.widget.MotionLayout ... >

        <ImageView  android:id="@+id/imageView0" .. />
        <ImageView  android:id="@+id/imageView1" .. />
        <ImageView  android:id="@+id/imageView2" .. />
        <ImageView  android:id="@+id/imageView3" .. />
        <ImageView  android:id="@+id/imageView4" .. />

        <androidx.constraintlayout.helper.widget.Carousel
            android:id="@+id/carousel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:carousel_forwardTransition="@+id/forward"
            app:carousel_backwardTransition="@+id/backward"
            app:carousel_previousState="@+id/previous"
            app:carousel_nextState="@+id/next"
            app:carousel_infinite="true"
            app:carousel_firstView="@+id/imageView2"
            app:constraint_referenced_ids="imageView0,imageView1,imageView2,imageView3,imageView4" />

    </androidx.constraintlayout.motion.widget.MotionLayout>

코드에서 Carousel 어댑터를 설정합니다.

Kotlin

carousel.setAdapter(object : Carousel.Adapter {
            override fun count(): Int {
              // Return the number of items in the Carousel.
            }

            override fun populate(view: View, index: Int) {
                // Implement this to populate the view at the given index.
            }

            override fun onNewItem(index: Int) {
                // Called when an item is set.
            }
        })

자바

carousel.setAdapter(new Carousel.Adapter() {
            @Override
            public int count() {
                // Return the number of items in the Carousel.
            }

            @Override
            public void populate(View view, int index) {
                // Populate the view at the given index.
            }

            @Override
            public void onNewItem(int index) {
                 // Called when an item is set.
            }
        });

추가 참고사항

Carousel에서 현재 '선택된' 항목에 따라 이전 또는 이후 항목을 나타내는 뷰를 숨겨 Carousel 시작을 올바르게 고려해야 할 수 있습니다. Carousel 도우미는 이를 자동으로 처리합니다. 기본적으로 이러한 상황에서 뷰를 View.INVISIBLE로 표시하므로 전체 레이아웃이 변경되지 않습니다.

Carousel 도우미가 대신 이러한 뷰를 View.GONE로 표시하는 대체 모드를 사용할 수 있습니다. 다음 속성을 사용하여 이 모드를 설정할 수 있습니다.

app:carousel_emptyViewsBehavior="gone"

캐러셀 도우미를 사용하는 더 많은 예는 GitHub의 예시 프로젝트를 참고하세요.