Tạo ảnh động cho đồ hoạ đối tượng có thể vẽ

Thử cách sử dụng 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.
Hình 1. Một ảnh động có thể vẽ.

Trong một số trường hợp, bạn cần phải tạo ảnh động. Điều này rất hữu ích nếu bạn muốn hiển thị một ảnh động tải tuỳ chỉnh bao gồm nhiều hình ảnh hoặc nếu bạn muốn một biểu tượng biến đổi sau hành động của người dùng. Android cung cấp 2 tuỳ chọn để tạo ảnh động cho đối tượng có thể vẽ.

Lựa chọn đầu tiên là sử dụng AnimationDrawable. Thao tác này cho phép bạn chỉ định nhiều tệp có thể vẽ tĩnh, lần lượt hiển thị từng tệp để tạo ảnh động. Lựa chọn thứ hai là sử dụng AnimatedVectorDrawable, cho phép bạn tạo ảnh động cho các thuộc tính của vectơ vẽ được.

Sử dụng AnimationDrawable

Một cách để tạo ảnh động là tải một chuỗi tài nguyên có thể vẽ, chẳng hạn như một cuộn phim. Lớp AnimationDrawable là cơ sở cho các loại ảnh động có thể vẽ này.

Bạn có thể xác định khung của ảnh động trong mã bằng cách sử dụng API lớp AnimationDrawable. Tuy nhiên, việc xác định khung này sẽ dễ dàng hơn bằng một tệp XML duy nhất liệt kê các khung tạo nên ảnh động. Tệp XML cho loại ảnh động này nằm trong thư mục res/drawable/ của dự án Android. Trong trường hợp này, hướng dẫn sẽ cung cấp thứ tự và thời lượng cho mỗi khung hình trong ảnh động.

Tệp XML bao gồm một phần tử <animation-list> làm nút gốc và một loạt nút <item> con mà mỗi nút xác định một khung — một tài nguyên có thể vẽ và thời lượng của tài nguyên đó. Dưới đây là tệp XML mẫu cho ảnh động Drawable:

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true">
    <item android:drawable="@drawable/rocket_thrust1" android:duration="200" />
    <item android:drawable="@drawable/rocket_thrust2" android:duration="200" />
    <item android:drawable="@drawable/rocket_thrust3" android:duration="200" />
</animation-list>

Ảnh động này chạy trong 3 khung. Khi bạn đặt thuộc tính android:oneshot của danh sách thành true, danh sách sẽ quay vòng một lần, sau đó dừng và giữ ở khung hình cuối cùng. Nếu bạn thiết lập android:oneshot thành false, vòng lặp ảnh động.

Nếu lưu XML này dưới dạng rocket_thrust.xml trong thư mục res/drawable/ của dự án, bạn có thể thêm tệp này làm hình nền vào View, sau đó gọi start() để phát. Dưới đây là ví dụ về một hoạt động trong đó ảnh động được thêm vào ImageView, sau đó thêm ảnh động khi chạm vào màn hình:

Kotlin

private lateinit var rocketAnimation: AnimationDrawable

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main)

    val rocketImage = findViewById<ImageView>(R.id.rocket_image).apply {
        setBackgroundResource(R.drawable.rocket_thrust)
        rocketAnimation = background as AnimationDrawable
    }

    rocketImage.setOnClickListener({ rocketAnimation.start() })
}

Java

AnimationDrawable rocketAnimation;

public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
  rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
  rocketAnimation = (AnimationDrawable) rocketImage.getBackground();

  rocketImage.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        rocketAnimation.start();
      }
  });
}

Điều quan trọng cần lưu ý là bạn không thể gọi phương thức start() được gọi trên AnimationDrawable trong phương thức onCreate() của Activity, vì AnimationDrawable chưa được đính kèm hoàn toàn vào cửa sổ. Để phát ảnh động ngay lập tức mà không cần tương tác, bạn có thể gọi ảnh động từ phương thức onStart() trong Activity. Phương thức này được gọi khi Android hiển thị khung hiển thị trên màn hình.

Để biết thêm thông tin về cú pháp XML cũng như các thẻ và thuộc tính có sẵn, hãy xem phần Tài nguyên ảnh động.

Sử dụng AnimatedVectorDrawable

Vectơ vẽ được là một loại đối tượng có thể vẽ có thể mở rộng mà không bị phân thành điểm ảnh hoặc bị mờ. Lớp AnimatedVectorDrawable AnimatedVectorDrawableCompat cho khả năng tương thích ngược cho phép bạn tạo ảnh động cho các thuộc tính của vectơ vẽ được, chẳng hạn như xoay vectơ hoặc thay đổi dữ liệu đường dẫn để biến nó thành một hình ảnh khác.

Bạn thường xác định các vectơ vẽ được ở dạng động trong 3 tệp XML:

  • Một vectơ vẽ được bằng phần tử <vector> trong res/drawable/.
  • Một vectơ vẽ được ở dạng động bằng phần tử <animated-vector> trong res/drawable/.
  • Một hoặc nhiều ảnh động đối tượng có phần tử <objectAnimator> trong res/animator/.

Vectơ ảnh động có thể vẽ có thể tạo ảnh động cho các thuộc tính của phần tử <group><path>. Phần tử <group> xác định một tập hợp các đường dẫn hoặc nhóm con, còn phần tử <path> xác định các đường dẫn cần vẽ.

Khi xác định một vectơ vẽ được mà bạn muốn tạo ảnh động, hãy sử dụng thuộc tính android:name để gán tên duy nhất cho các nhóm và đường dẫn, để bạn có thể tham chiếu đến các vectơ đó từ định nghĩa trình tạo ảnh động của mình. Ví dụ:

res/drawable/Vectordrawable.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="64dp"
    android:width="64dp"
    android:viewportHeight="600"
    android:viewportWidth="600">
    <group
        android:name="rotationGroup"
        android:pivotX="300.0"
        android:pivotY="300.0"
        android:rotation="45.0" >
        <path
            android:name="v"
            android:fillColor="#000000"
            android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
    </group>
</vector>

Định nghĩa vectơ vẽ được ở dạng động đề cập đến các nhóm và đường dẫn trong vectơ vẽ được theo tên:

res/drawable/animatorvedrawable.xml

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
  android:drawable="@drawable/vectordrawable" >
    <target
        android:name="rotationGroup"
        android:animation="@animator/rotation" />
    <target
        android:name="v"
        android:animation="@animator/path_morph" />
</animated-vector>

Định nghĩa ảnh động đại diện cho đối tượng ObjectAnimator hoặc AnimatorSet. Trình tạo ảnh động đầu tiên trong ví dụ này xoay nhóm mục tiêu 360 độ:

res/animator/rotation.xml

<objectAnimator
    android:duration="6000"
    android:propertyName="rotation"
    android:valueFrom="0"
    android:valueTo="360" />

Trình tạo ảnh động thứ hai trong ví dụ này biến đổi đường dẫn của vectơ vẽ được từ hình dạng này sang hình dạng khác. Các đường dẫn phải tương thích để biến đổi: các đường dẫn này phải có cùng số lượng lệnh và cùng số lượng tham số cho mỗi lệnh.

res/animator/path_morph.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="3000"
        android:propertyName="pathData"
        android:valueFrom="M300,70 l 0,-70 70,70 0,0   -70,70z"
        android:valueTo="M300,70 l 0,-70 70,0  0,140 -70,0 z"
        android:valueType="pathType" />
</set>

Sau đây là kết quả AnimatedVectorDrawable:

Hình 2. Một AnimatedVectorDrawable.

Bản xem trước vectơ vẽ được ở dạng động (AVD)

Công cụ vectơ vẽ được ở dạng động trong Android Studio cho phép bạn xem trước các tài nguyên động có thể vẽ. Công cụ này giúp bạn xem trước các tài nguyên <animation-list>, <animated-vector><animated-selector> trong Android Studio, đồng thời giúp bạn dễ dàng tinh chỉnh ảnh động tuỳ chỉnh.

Người dùng xem trước và phát ảnh động trong Android Studio
Hình 3. Công cụ vectơ vẽ được ở dạng động trong Android Studio.

Để biết thêm thông tin, hãy xem tài liệu tham khảo API cho AnimatedVectorDrawable.