Di chuyển khung hiển thị bằng ảnh động dựa trên cử chỉ hất

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 sử dụng Ảnh động trong Compose.

Ảnh động dựa trên cử chỉ hất sử dụng lực ma sát tỷ lệ thuận với tốc độ của một đối tượng. Sử dụng thuộc tính này để tạo ảnh động cho một thuộc tính của đối tượng và kết thúc ảnh động một cách từ từ. Nó có đà ban đầu, chủ yếu nhận được từ tốc độ của cử chỉ và giảm tốc độ dần. Ảnh động kết thúc khi vận tốc của ảnh động đủ thấp để không có thay đổi rõ ràng trên màn hình thiết bị.

Hình 1. Ảnh động hất

Để tìm hiểu về các chủ đề liên quan, hãy đọc các hướng dẫn sau:

Thêm thư viện AndroidX

Để sử dụng các ảnh động dựa trên vật lý, bạn phải thêm thư viện AndroidX vào dự án của mình như sau:

  1. Mở tệp build.gradle cho mô-đun ứng dụng của bạn.
  2. Thêm thư viện AndroidX vào phần dependencies.

    Groovy

            dependencies {
                implementation 'androidx.dynamicanimation:dynamicanimation:1.0.0'
            }
            

    Kotlin

            dependencies {
                implementation("androidx.dynamicanimation:dynamicanimation:1.0.0")
            }
            

Tạo ảnh động dựa trên cử chỉ hất

Lớp FlingAnimation cho phép bạn tạo một ảnh động hất cho một đối tượng. Để tạo một ảnh động hất, hãy tạo một thực thể của lớp FlingAnimation và cung cấp một đối tượng cũng như thuộc tính của đối tượng mà bạn muốn tạo ảnh động.

Kotlin

val fling = FlingAnimation(view, DynamicAnimation.SCROLL_X)

Java

FlingAnimation fling = new FlingAnimation(view, DynamicAnimation.SCROLL_X);

Đặt vận tốc

Vận tốc ban đầu xác định tốc độ thay đổi của một thuộc tính ảnh động khi bắt đầu ảnh động. Vận tốc bắt đầu mặc định được đặt thành 0 pixel/giây. Do đó, bạn phải xác định vận tốc ban đầu để đảm bảo ảnh động không kết thúc ngay lập tức.

Bạn có thể dùng một giá trị cố định làm vận tốc ban đầu hoặc dựa vào vận tốc của một cử chỉ chạm. Nếu chọn cung cấp một giá trị cố định, bạn nên xác định giá trị bằng dp mỗi giây, sau đó chuyển đổi thành pixel mỗi giây. Việc xác định giá trị theo dp mỗi giây cho phép vận tốc không phụ thuộc vào mật độ và kiểu dáng của thiết bị. Để biết thêm thông tin về cách chuyển đổi vận tốc ban đầu thành số pixel trên giây, hãy tham khảo phần Chuyển đổi dp trên giây thành số pixel trên giây trong Ảnh động lò xo.

Để đặt vận tốc, hãy gọi phương thức setStartVelocity() và truyền vận tốc theo pixel mỗi giây. Phương thức này trả về đối tượng hất mà vận tốc được đặt.

Lưu ý: Sử dụng các lớp GestureDetector.OnGestureListenerVelocityTracker để lần lượt truy xuất và tính toán vận tốc của cử chỉ chạm.

Đặt một dải giá trị ảnh động

Bạn có thể đặt giá trị tối thiểu và tối đa cho ảnh động khi muốn hạn chế giá trị thuộc tính trong một phạm vi nhất định. Điều khiển phạm vi này đặc biệt hữu ích khi bạn tạo ảnh động cho các thuộc tính có phạm vi vốn có, chẳng hạn như độ trong suốt (từ 0 đến 1).

Lưu ý: Khi giá trị của một ảnh động hất đạt đến giá trị tối thiểu hoặc tối đa, ảnh động sẽ kết thúc.

Để đặt giá trị tối thiểu và tối đa, hãy gọi các phương thức setMinValue()setMaxValue() tương ứng. Cả hai phương thức đều trả về đối tượng ảnh động mà bạn đã đặt giá trị.

Đặt độ ma sát

Phương thức setFriction() cho phép bạn thay đổi độ ma sát của ảnh động. Tham số này xác định tốc độ giảm của vận tốc trong một ảnh động.

Lưu ý: Nếu bạn không đặt lực ma sát khi bắt đầu ảnh động, thì ảnh động sẽ sử dụng giá trị lực ma sát mặc định là 1.

Phương thức này trả về đối tượng có ảnh động sử dụng giá trị ma sát mà bạn cung cấp.

Mã mẫu

Ví dụ dưới đây minh hoạ một thao tác hất theo chiều ngang. Vận tốc được ghi lại từ trình theo dõi vận tốc là velocityX và các giới hạn cuộn được đặt thành 0 và maxScroll. Lực ma sát được đặt thành 1,1.

Kotlin

FlingAnimation(view, DynamicAnimation.SCROLL_X).apply {
    setStartVelocity(-velocityX)
    setMinValue(0f)
    setMaxValue(maxScroll)
    friction = 1.1f
    start()
}

Java

FlingAnimation fling = new FlingAnimation(view, DynamicAnimation.SCROLL_X);
fling.setStartVelocity(-velocityX)
        .setMinValue(0)
        .setMaxValue(maxScroll)
        .setFriction(1.1f)
        .start();

Đặt mức thay đổi tối thiểu có thể nhìn thấy

Khi tạo hiệu ứng cho một thuộc tính tuỳ chỉnh không được xác định bằng pixel, bạn nên đặt mức thay đổi tối thiểu của giá trị hiệu ứng mà người dùng có thể thấy. Nó xác định một ngưỡng hợp lý để kết thúc ảnh động.

Bạn không cần gọi phương thức này khi tạo hiệu ứng cho DynamicAnimation.ViewProperty vì thay đổi hiển thị tối thiểu được lấy từ thuộc tính. Ví dụ:

  • Giá trị thay đổi tối thiểu có thể nhìn thấy mặc định là 1 pixel cho các thuộc tính của khung hiển thị, chẳng hạn như TRANSLATION_X, TRANSLATION_Y, TRANSLATION_Z, SCROLL_XSCROLL_Y.
  • Đối với ảnh động sử dụng hiệu ứng xoay, chẳng hạn như ROTATION, ROTATION_XROTATION_Y, mức thay đổi tối thiểu có thể thấy là MIN_VISIBLE_CHANGE_ROTATION_DEGREES hoặc 1/10 pixel.
  • Đối với ảnh động sử dụng độ mờ, mức thay đổi tối thiểu có thể thấy là MIN_VISIBLE_CHANGE_ALPHA hoặc 1/256.

Để đặt mức thay đổi tối thiểu có thể nhìn thấy cho một ảnh động, hãy gọi phương thức setMinimumVisibleChange() và truyền một trong các hằng số tối thiểu có thể nhìn thấy hoặc một giá trị mà bạn cần tính cho một thuộc tính tuỳ chỉnh. Để biết thêm thông tin về cách tính giá trị này, hãy tham khảo phần Tính giá trị thay đổi tối thiểu có thể thấy.

Kotlin

anim.minimumVisibleChange = DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE

Java

anim.setMinimumVisibleChange(DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE);

Lưu ý: Bạn chỉ cần truyền một giá trị khi tạo hiệu ứng cho một thuộc tính tuỳ chỉnh không được xác định bằng pixel.

Tính giá trị thay đổi tối thiểu có thể nhìn thấy

Để tính giá trị thay đổi tối thiểu có thể thấy cho một thuộc tính tuỳ chỉnh, hãy sử dụng công thức sau:

Thay đổi tối thiểu có thể nhìn thấy = Phạm vi giá trị thuộc tính tuỳ chỉnh / Phạm vi hoạt ảnh tính bằng pixel

Ví dụ: thuộc tính mà bạn muốn tạo ảnh động sẽ tiến từ 0 đến 100. Điều này tương ứng với mức thay đổi 200 pixel. Theo công thức, giá trị thay đổi tối thiểu có thể nhìn thấy là 100 / 200, tức là 0,5 pixel.