Băng chuyền có MotionLayout

Thử cách Compose
Jetpack Compose là bộ công cụ giao diện người dùng được đề xuất cho Android. Tìm hiểu cách thêm băng chuyền trong Compose.

Carousel là một đối tượng trình trợ giúp chuyển động để tạo các khung hiển thị băng chuyền tuỳ chỉnh cho thấy danh sách các phần tử mà người dùng có thể xem qua. So với những cách khác để triển khai các khung hiển thị như vậy, thành phần trợ giúp này cho phép bạn nhanh chóng tạo các thay đổi phức tạp về chuyển động và kích thước cho Carousel bằng cách tận dụng MotionLayout.

Tiện ích Carousel hỗ trợ danh sách có điểm bắt đầu và kết thúc, cũng như danh sách vòng tròn.

Cách hoạt động của băng chuyền có MotionLayout

Giả sử bạn muốn tạo một khung hiển thị Carousel theo chiều ngang, với mục ở giữa được phóng to:

Bố cục cơ bản này chứa một số thành phần hiển thị đại diện cho các mục Carousel:

Tạo một MotionLayout có 3 trạng thái sau và đặt mã nhận dạng cho các trạng thái đó:

  • trước
  • bắt đầu
  • tiếp theo

Nếu trạng thái start tương ứng với bố cục cơ sở, thì trong trạng thái previous và trạng thái next, các mục Carousel sẽ lần lượt được chuyển sang trái và sang phải.

Ví dụ: hãy lấy 5 khung hiển thị trong hình 3 và giả sử rằng ở trạng thái start, các khung hiển thị B, C và D có thể nhìn thấy, còn A và E nằm ngoài màn hình. Thiết lập trạng thái trước đó để vị trí của A, B, C và D là vị trí của B, C, D và E, với các thành phần hiển thị di chuyển từ trái sang phải. Ở trạng thái tiếp theo, điều ngược lại cần xảy ra, với B, C, D và E di chuyển đến vị trí của A, B, C và D, đồng thời các khung hiển thị di chuyển từ phải sang trái. Điều này được thể hiện trong hình 4:

Điều quan trọng là các khung hiển thị phải kết thúc chính xác tại nơi các khung hiển thị ban đầu bắt đầu. Carousel tạo ảo giác về một tập hợp vô hạn các phần tử bằng cách di chuyển các khung hiển thị thực trở lại vị trí ban đầu, nhưng khởi tạo lại chúng bằng nội dung mới phù hợp. Sơ đồ sau đây minh hoạ cơ chế này. Chú ý đến các giá trị "item #" (mục số):

Kiểu chuyển cảnh

Khi đã xác định 3 nhóm ràng buộc này trong tệp cảnh chuyển động, hãy tạo 2 hiệu ứng chuyển đổi (tiến và lùi) giữa các trạng thái bắt đầutiếp theo, cũng như các trạng thái bắt đầutrước đó. Thêm một trình xử lý OnSwipe để kích hoạt các hiệu ứng chuyển đổi nhằm phản hồi một cử chỉ, như trong ví dụ sau:

    <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>

Sau khi tạo cảnh chuyển động cơ bản này, hãy thêm một trình trợ giúp Carousel vào bố cục và tham chiếu các khung hiển thị theo cùng thứ tự mà bạn triển khai ảnh động trước và tiếp theo.

Đặt các thuộc tính sau cho trình trợ giúp Carousel:

  • app:carousel_firstView: khung hiển thị đại diện cho phần tử đầu tiên của Carousel – trong ví dụ này là C.
  • app:carousel_previousState: mã nhận dạng ConstraintSet của trạng thái trước.
  • app:carousel_nextState: mã nhận dạng ConstraintSet của trạng thái tiếp theo.
  • app:carousel_backwardTransition: mã nhận dạng Transition được áp dụng giữa trạng thái startprevious.
  • app:carousel_forwardTransition: mã nhận dạng Transition được áp dụng giữa các trạng thái startnext.

Ví dụ: bạn có nội dung như sau trong tệp XML bố cục:

    <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>

Thiết lập một đối tượng chuyển đổi Carousel trong mã:

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.
            }
        })

Java

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.
            }
        });

Ghi chú khác

Tuỳ thuộc vào mục hiện tại được "chọn" trong Carousel, có thể bạn cần ẩn các khung hiển thị đại diện cho các mục trước hoặc sau để tính toán chính xác startend của Carousel. Trình trợ giúp Carousel sẽ tự động xử lý việc này. Theo mặc định, trong những trường hợp này, hệ thống sẽ đánh dấu các khung hiển thị đó là View.INVISIBLE để bố cục tổng thể không thay đổi.

Có một chế độ thay thế trong đó trình trợ giúp Carousel đánh dấu những khung hiển thị đó là View.GONE. Bạn có thể đặt chế độ này bằng cách sử dụng thuộc tính sau:

app:carousel_emptyViewsBehavior="gone"

Ví dụ

Để xem thêm ví dụ về cách sử dụng trình trợ giúp Carousel, hãy xem các dự án mẫu trên GitHub.