Di chuyển khung hiển thị có ảnh động

Các đối tượng trên màn hình thường cần được định vị lại do sự tương tác của người dùng hoặc việc xử lý phía sau hậu trường. Thay vì cập nhật ngay vị trí của đối tượng, khiến đối tượng nhấp nháy từ vùng này sang vùng khác, hãy sử dụng ảnh động để di chuyển đối tượng từ vị trí bắt đầu đến vị trí kết thúc.

Một cách mà Android giúp bạn định vị lại các đối tượng khung hiển thị trên màn hình là sử dụng ObjectAnimator. Bạn cung cấp vị trí kết thúc mà bạn muốn đối tượng ổn định cũng như thời lượng của ảnh động. Bạn cũng có thể sử dụng bộ nội suy thời gian để kiểm soát việc tăng hoặc giảm tốc độ của ảnh động.

Thay đổi vị trí khung hiển thị bằng ObjectAnimator

API ObjectAnimator cung cấp cách thay đổi các thuộc tính của khung hiển thị có thời lượng chỉ định. Lớp này chứa các phương thức tĩnh để tạo các thực thể của ObjectAnimator tuỳ thuộc vào loại thuộc tính bạn đang tạo ảnh động. Khi định vị lại thành phần hiển thị trên màn hình, hãy sử dụng các thuộc tính translationXtranslationY.

Dưới đây là ví dụ về ObjectAnimator di chuyển khung hiển thị đến một vị trí cách bên trái màn hình 100 pixel trong 2 giây:

Kotlin

ObjectAnimator.ofFloat(view, "translationX", 100f).apply {
    duration = 2000
    start()
}

Java

ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f);
animation.setDuration(2000);
animation.start();

Ví dụ này sử dụng phương thức ObjectAnimator.ofFloat(), vì giá trị dịch phải là số thực có độ chính xác đơn. Tham số đầu tiên là khung hiển thị bạn muốn tạo ảnh động. Thông số thứ hai là thuộc tính mà bạn đang tạo ảnh động. Vì khung hiển thị cần di chuyển theo chiều ngang, nên thuộc tính translationX sẽ được sử dụng. Tham số cuối cùng là giá trị kết thúc của ảnh động. Trong ví dụ này, giá trị 100 cho biết vị trí có nhiều pixel tính từ bên trái màn hình.

Phương thức tiếp theo chỉ định thời lượng của ảnh động, tính bằng mili giây. Trong ví dụ này, ảnh động chạy trong 2 giây (2000 mili giây).

Phương thức cuối cùng khiến ảnh động chạy để cập nhật vị trí của khung hiển thị trên màn hình.

Để biết thêm thông tin về cách sử dụng ObjectAnimator, hãy xem bài viết Tạo ảnh động bằng cách sử dụng ObjectAnimator.

Thêm chuyển động cong

Mặc dù việc sử dụng ObjectAnimator rất thuận tiện, nhưng theo mặc định, thuộc tính này sẽ định vị lại khung hiển thị dọc theo một đường thẳng giữa điểm xuất phát và điểm kết thúc. Material Design dựa trên các đường cong để chuyển động trong không gian của các đối tượng trên màn hình và bắt đầu của ảnh động. Việc sử dụng chuyển động cong vừa mang lại cho ứng dụng một cảm giác cụ thể vừa giúp ảnh động trở nên thú vị hơn.

Xác định đường dẫn của riêng bạn

Lớp ObjectAnimator có các hàm khởi tạo cho phép bạn tạo ảnh động cho toạ độ bằng cách sử dụng hai hoặc nhiều thuộc tính cùng một lúc với một đường dẫn. Ví dụ: trình tạo ảnh động sau đây sử dụng đối tượng Path để tạo ảnh động cho các thuộc tính X và Y của khung hiển thị:

Kotlin

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    val path = Path().apply {
        arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true)
    }
    val animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path).apply {
        duration = 2000
        start()
    }
} else {
    // Create animator without using curved path
}

Java

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  Path path = new Path();
  path.arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true);
  ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
  animator.setDuration(2000);
  animator.start();
} else {
  // Create animator without using curved path
}

Ảnh động vòng cung này sẽ trông như sau:

Hình 1. Ảnh động đường dẫn cong.

Interpolator là cách triển khai một đường cong gia tốc. Vui lòng xem tài liệu về Material Design để biết thêm thông tin về khái niệm gia tốc đường cong. Interpolator xác định cách tính các giá trị cụ thể trong ảnh động dưới dạng hàm thời gian. Hệ thống cung cấp tài nguyên XML cho 3 đường cong cơ bản trong thông số kỹ thuật của Material Design:

  • @interpolator/fast_out_linear_in.xml
  • @interpolator/fast_out_slow_in.xml
  • @interpolator/linear_out_slow_in.xml

Sử dụng bộ nội suy đường dẫn

Lớp PathInterpolator là một bộ nội suy được giới thiệu trong Android 5.0 (API 21). Thuộc tính này dựa trên đường cong Bézier hoặc đối tượng Path. Các ví dụ về Android trong tài liệu về Material Design để gia tốc sử dụng PathInterpolator.

PathInterpolator có các hàm khởi tạo dựa trên nhiều loại đường cong Bézier. Tất cả các đường cong Bézier lần lượt có điểm bắt đầu và điểm kết thúc cố định tại (0,0)(1,1). Các đối số hàm khởi tạo khác phụ thuộc vào loại đường cong Bézier được tạo.

Ví dụ: đối với đường cong Bézier bậc hai, bạn chỉ cần cung cấp toạ độ X và Y của một điểm điều khiển:

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    PathInterpolator(0.67f, 0.33f)
} else {
    LinearInterpolator()
}

Java

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  myInterpolator = new PathInterpolator(0.67f, 0.33f);
} else {
  myInterpolator = new LinearInterpolator();
}

Điều này tạo ra một đường cong gia tốc bắt đầu nhanh chóng và giảm tốc khi gần đến điểm cuối.

Tương tự như vậy, hàm khởi tạo Bézier lập phương có điểm bắt đầu và điểm kết thúc cố định, nhưng cần có 2 điểm điều khiển:

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f)
} else {
    LinearInterpolator()
}

Java

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  myInterpolator = new PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f);
} else {
  myInterpolator = new LinearInterpolator();
}

Đây là cách triển khai đường cong làm giảm tốc độ nhấn mạnh trong Material Design.

Để kiểm soát tốt hơn, bạn có thể dùng Path tuỳ ý để xác định đường cong:

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  val path = Path().apply {
    moveTo(0.0f, 0.0f)
    cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f)
  }
  PathInterpolator(path)
} else {
  LinearInterpolator()
}

Java

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  Path path = new Path();
  path.moveTo(0.0f, 0.0f);
  path.cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f);
  myInterpolator = new PathInterpolator(path);
} else {
  myInterpolator = new LinearInterpolator();
}

Thao tác này tạo ra cùng một đường cong gia tốc như ví dụ về Bézier lập phương, nhưng thay vào đó sử dụng Path.

Bạn cũng có thể xác định bộ nội suy đường dẫn dưới dạng tài nguyên XML:

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:controlX1="0.5"
    android:controlY1="0.7"
    android:controlX2="0.1f"
    android:controlY2="1.0f"/>

Sau khi tạo một đối tượng PathInterpolator, bạn có thể truyền đối tượng đó đến phương thức Animator.setInterpolator(). Animator sử dụng bộ nội suy để xác định thời gian hoặc đường cong đường dẫn khi bắt đầu.

Kotlin

val animation = ObjectAnimator.ofFloat(view, "translationX", 100f).apply {
    interpolator = myInterpolator
    start()
}

Java

ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f);
animation.setInterpolator(myInterpolator);
animation.start();