Hệ thống ảnh động thuộc tính là một khung mạnh mẽ cho phép bạn tạo ảnh động cho hầu hết mọi thứ. Bạn có thể xác định ảnh động để thay đổi bất kỳ thuộc tính đối tượng nào theo thời gian, bất kể ảnh động có được vẽ vào màn hình hay không. Ảnh động thuộc tính thay đổi giá trị của một thuộc tính (một trường trong đối tượng) trong một khoảng thời gian chỉ định. Để tạo ảnh động cho nội dung nào đó, bạn cần chỉ định thuộc tính đối tượng mà bạn muốn tạo ảnh động, chẳng hạn như vị trí của đối tượng trên màn hình, thời lượng bạn muốn tạo ảnh động và các giá trị bạn muốn tạo ảnh động.
Hệ thống ảnh động thuộc tính cho phép bạn xác định các đặc điểm sau của ảnh động:
- Thời lượng: Bạn có thể chỉ định thời lượng của ảnh động. Độ dài mặc định là 300 mili giây.
- Loại nội suy thời gian: Bạn có thể chỉ định cách tính giá trị cho thuộc tính dưới dạng một hàm của thời gian hiện tại đã trôi qua của ảnh động.
- Số lượng và hành vi lặp lại: Bạn có thể chỉ định xem có lặp lại ảnh động khi hết thời lượng và số lần lặp lại ảnh động hay không. Bạn cũng có thể chỉ định xem bạn có muốn ảnh động phát ngược lại theo chiều ngược lại hay không. Khi bạn đặt ở chế độ đảo ngược, ảnh động sẽ tua đi rồi tua lại nhiều lần cho đến khi đạt đến số lần lặp lại.
- Tập hợp ảnh động: Bạn có thể nhóm ảnh động thành tập hợp logic phát cùng nhau hoặc theo tuần tự hoặc sau độ trễ được chỉ định.
- Độ trễ làm mới khung: Bạn có thể chỉ định tần suất làm mới khung hình của ảnh động. Chế độ mặc định được đặt là làm mới 10 mili giây một lần, nhưng tốc độ mà ứng dụng có thể làm mới khung hình sau cùng phụ thuộc vào mức độ bận rộn tổng thể của hệ thống và tốc độ hệ thống có thể phục vụ bộ tính giờ cơ bản.
Để xem ví dụ đầy đủ về ảnh động thuộc tính, hãy xem lớp ChangeColor
trong mẫu CustomTransition trên GitHub.
Cách hoạt động của ảnh động thuộc tính
Đầu tiên, hãy tìm hiểu cách hoạt động của ảnh động thông qua một ví dụ đơn giản. Hình 1 mô tả một đối tượng giả định được tạo ảnh động bằng thuộc tính x
, đại diện cho vị trí ngang của đối tượng đó trên màn hình. Thời lượng của ảnh động được đặt là 40 mili giây và khoảng cách di chuyển là 40 pixel. Cứ 10 mili giây (là tốc độ làm mới khung hình mặc định) thì đối tượng sẽ di chuyển theo chiều ngang 10 pixel. Khi kết thúc 40 mili giây, ảnh động sẽ dừng và đối tượng kết thúc ở vị trí ngang 40. Đây là ví dụ về ảnh động dùng loại nội suy tuyến tính, nghĩa là đối tượng di chuyển với tốc độ không đổi.
![](https://developer.android.com/static/images/animation/animation-linear.png?authuser=5&hl=vi)
Hình 1. Ví dụ về ảnh động tuyến tính
Bạn cũng có thể chỉ định ảnh động để có loại nội suy phi tuyến tính. Hình 2 minh hoạ một đối tượng giả định có tốc độ tăng tốc ở đầu ảnh động và giảm tốc ở cuối ảnh động. Đối tượng vẫn di chuyển 40 pixel trong 40 mili giây, nhưng phi tuyến tính. Ban đầu, ảnh động này tăng tốc đến điểm giữa chừng rồi giảm tốc từ điểm giữa chừng cho đến khi kết thúc ảnh động. Như Hình 2 cho thấy, khoảng cách đã di chuyển ở đầu và cuối của ảnh động nhỏ hơn ở giữa.
![](https://developer.android.com/static/images/animation/animation-nonlinear.png?authuser=5&hl=vi)
Hình 2. Ví dụ về ảnh động phi tuyến tính
Hãy cùng tìm hiểu chi tiết cách các thành phần quan trọng của hệ thống ảnh động thuộc tính sẽ tính toán ảnh động như minh hoạ ở trên. Hình 3 mô tả cách các lớp chính hoạt động cùng nhau.
![](https://developer.android.com/static/images/animation/valueanimator.png?authuser=5&hl=vi)
Hình 3. Cách tính ảnh động
Đối tượng ValueAnimator
theo dõi thời gian của ảnh động, chẳng hạn như thời lượng ảnh động và giá trị hiện tại của thuộc tính mà ảnh động đang tạo.
ValueAnimator
đóng gói một TimeInterpolator
(xác định loại nội suy ảnh động) và TypeEvaluator
(giúp xác định cách tính các giá trị cho thuộc tính là ảnh động). Ví dụ: trong Hình 2, TimeInterpolator
được sử dụng sẽ là AccelerateDecelerateInterpolator
và TypeEvaluator
sẽ là IntEvaluator
.
Để bắt đầu tạo ảnh động, hãy tạo ValueAnimator
và cung cấp giá trị bắt đầu và kết thúc cho thuộc tính bạn muốn tạo ảnh động, cùng với thời lượng của ảnh động. Khi bạn gọi start()
, ảnh động sẽ bắt đầu. Trong toàn bộ ảnh động, ValueAnimator
sẽ tính toán một phân số đã trôi qua trong khoảng từ 0 đến 1, dựa trên thời lượng của ảnh động và khoảng thời gian đã trôi qua. Phân số đã trôi qua biểu thị tỷ lệ phần trăm thời gian mà ảnh động đã hoàn tất, 0 có nghĩa là 0% và 1 có nghĩa là 100%. Ví dụ: trong Hình 1, phân số đã trôi qua tại t = 10 ms sẽ là 0, 25 vì tổng thời lượng là t = 40 ms.
Khi tính toán xong một phân số đã trôi qua, ValueAnimator
sẽ gọi TimeInterpolator
hiện đã được đặt để tính phân số nội suy. Phân số nội suy ánh xạ phân số đã trôi qua với một phân số mới có tính đến loại nội suy thời gian đã đặt. Ví dụ: trong Hình 2, vì ảnh động tăng tốc từ từ nên phân số nội suy khoảng 0,15 sẽ nhỏ hơn phân số đã trôi qua 0,25 ở t = 10 mili giây. Trong Hình 1, phân số nội suy luôn giống với phân số đã trôi qua.
Khi tính phân số nội suy, ValueAnimator
sẽ gọi TypeEvaluator
thích hợp để tính giá trị của thuộc tính mà bạn đang tạo ảnh động, dựa trên phân số nội suy, giá trị bắt đầu và giá trị kết thúc của ảnh động. Ví dụ: trong Hình 2, phân số nội suy là 0, 15 tại t = 10 ms, vì vậy giá trị của thuộc tính tại thời điểm đó sẽ là 0,15 × (40 – 0) hoặc 6.
Sự khác biệt giữa ảnh động thuộc tính và ảnh động khung hiển thị
Hệ thống ảnh động khung hiển thị cung cấp khả năng chỉ tạo ảnh động cho đối tượng View
. Vì vậy, nếu muốn tạo ảnh động cho các đối tượng không phải View
, bạn phải triển khai mã của riêng mình để làm như vậy. Hệ thống ảnh động khung hiển thị cũng bị hạn chế ở chỗ chỉ hiển thị một vài khía cạnh của đối tượng View
để tạo ảnh động, chẳng hạn như việc điều chỉnh tỷ lệ và xoay của Khung hiển thị chứ không phải màu nền.
Một nhược điểm khác của hệ thống ảnh động khung hiển thị là hệ thống này chỉ sửa đổi tại vị trí Khung hiển thị được vẽ chứ không phải chính Khung hiển thị thực tế. Ví dụ: nếu bạn tạo ảnh động cho một nút để di chuyển trên màn hình, nút đó sẽ được vẽ chính xác, nhưng vị trí thực tế mà bạn có thể nhấp vào nút đó không thay đổi. Vì vậy, bạn phải triển khai logic của riêng mình để xử lý việc này.
Với hệ thống ảnh động thuộc tính, các quy tắc ràng buộc này được loại bỏ hoàn toàn và bạn có thể tạo ảnh động bất kỳ thuộc tính nào của bất kỳ đối tượng nào (Khung hiển thị và không phải Khung hiển thị) và bản thân đối tượng đó sẽ thực sự được sửa đổi. Hệ thống ảnh động thuộc tính cũng mạnh mẽ hơn ở cách thực hiện ảnh động. Ở cấp độ cao, bạn chỉ định ảnh động cho các thuộc tính mà bạn muốn tạo ảnh động, chẳng hạn như màu sắc, vị trí hoặc kích thước và có thể xác định các khía cạnh của ảnh động như nội suy và đồng bộ hoá nhiều ảnh động.
Tuy nhiên, hệ thống ảnh động dạng khung hiển thị mất ít thời gian hơn để thiết lập và yêu cầu ít mã hơn để viết. Nếu ảnh động khung hiển thị hoàn thành mọi việc bạn cần làm, hoặc nếu mã hiện có của bạn hoạt động theo cách bạn muốn, thì bạn không cần sử dụng hệ thống ảnh động thuộc tính. Bạn cũng có thể sử dụng cả hai hệ thống ảnh động cho các tình huống khác nhau nếu phát sinh trường hợp sử dụng.
Tổng quan về API
Bạn có thể tìm thấy hầu hết các API của hệ thống ảnh động thuộc tính trong android.animation
. Vì hệ thống ảnh động khung hiển thị đã xác định nhiều bộ nội suy trong android.view.animation
, nên bạn cũng có thể sử dụng các bộ nội suy đó trong hệ thống ảnh động thuộc tính. Bảng sau đây mô tả các thành phần chính của hệ thống ảnh động thuộc tính.
Lớp Animator
cung cấp cấu trúc cơ bản để tạo ảnh động. Bạn thường không sử dụng trực tiếp lớp này vì lớp này chỉ cung cấp chức năng tối thiểu cần được mở rộng để hỗ trợ đầy đủ các giá trị ảnh động. Các lớp con sau đây sẽ mở rộng Animator
:
Bảng 1. Hoạ sĩ diễn hoạt
Lớp | Nội dung mô tả |
---|---|
ValueAnimator |
Công cụ định thời gian chính cho ảnh động thuộc tính cũng tính toán các giá trị cho thuộc tính để tạo ảnh động. Tệp này có tất cả chức năng cốt lõi để tính toán giá trị ảnh động và chứa thông tin chi tiết về thời gian của mỗi ảnh động, thông tin về việc một ảnh động có lặp lại hay không, trình nghe nhận được sự kiện cập nhật và khả năng đặt các kiểu tuỳ chỉnh để đánh giá. Có 2 phần để tạo ảnh động cho các thuộc tính: tính toán các giá trị được tạo ảnh động và đặt các giá trị đó trên các đối tượng và thuộc tính đang được tạo ảnh động. ValueAnimator không thực hiện phần thứ hai, vì vậy bạn phải theo dõi thông tin cập nhật đối với các giá trị do ValueAnimator tính toán và sửa đổi các đối tượng mà bạn muốn tạo ảnh động bằng logic của riêng mình. Hãy xem phần Tạo ảnh động bằng ValueAnimator để biết thêm thông tin. |
ObjectAnimator |
Một lớp con của ValueAnimator cho phép bạn thiết lập đối tượng mục tiêu và thuộc tính đối tượng để tạo ảnh động. Lớp này sẽ cập nhật thuộc tính tương ứng khi tính toán giá trị mới cho ảnh động. Bạn luôn muốn sử dụng ObjectAnimator , vì tính năng này giúp quá trình tạo ảnh động cho các giá trị trên đối tượng mục tiêu dễ dàng hơn nhiều. Tuy nhiên, đôi khi bạn muốn sử dụng trực tiếp ValueAnimator vì ObjectAnimator có một vài hạn chế khác, chẳng hạn như yêu cầu các phương thức truy cập cụ thể phải có trên đối tượng mục tiêu. |
AnimatorSet |
Cung cấp cơ chế nhóm các ảnh động lại với nhau để chúng chạy với nhau. Bạn có thể thiết lập các ảnh động để phát cùng nhau, theo tuần tự hoặc sau một độ trễ nhất định. Hãy xem phần Choreographing nhiều ảnh động bằng Bộ ảnh động để biết thêm thông tin. |
Trình đánh giá sẽ cho hệ thống ảnh động thuộc tính biết cách tính toán các giá trị cho một thuộc tính nhất định. Phương thức này lấy dữ liệu thời gian do một lớp Animator
cung cấp, giá trị bắt đầu và kết thúc của ảnh động rồi tính toán các giá trị ảnh động của thuộc tính dựa trên dữ liệu này. Hệ thống ảnh động thuộc tính cung cấp các trình đánh giá sau:
Bảng 2. Người đánh giá
Lớp/Giao diện | Nội dung mô tả |
---|---|
IntEvaluator |
Trình đánh giá mặc định để tính giá trị cho các thuộc tính int . |
FloatEvaluator |
Trình đánh giá mặc định để tính giá trị cho các thuộc tính float . |
ArgbEvaluator |
Trình đánh giá mặc định để tính toán các giá trị cho các thuộc tính màu được biểu thị dưới dạng giá trị thập lục phân. |
TypeEvaluator |
Một giao diện cho phép bạn tạo người đánh giá riêng. Nếu đang tạo ảnh động cho một thuộc tính đối tượng không phải là int , float hay màu sắc, bạn phải triển khai giao diện TypeEvaluator để chỉ định cách tính toán các giá trị ảnh động của thuộc tính đối tượng. Bạn cũng có thể chỉ định một TypeEvaluator tuỳ chỉnh cho int , float cũng như các giá trị màu sắc nếu muốn xử lý các kiểu đó khác với hành vi mặc định.
Hãy xem phần Sử dụng TypeEvaluator để biết thêm thông tin về cách viết công cụ đánh giá tuỳ chỉnh. |
Bộ nội suy thời gian xác định cách tính các giá trị cụ thể trong ảnh động dưới dạng một hàm thời gian. Ví dụ: bạn có thể chỉ định ảnh động diễn ra theo đường thẳng trên toàn bộ ảnh động, nghĩa là ảnh động di chuyển đồng đều trong toàn bộ thời gian, hoặc bạn có thể chỉ định ảnh động để sử dụng thời gian phi tuyến tính, chẳng hạn như tăng tốc ở đầu và giảm tốc ở cuối ảnh động. Bảng 3 mô tả các bộ nội suy có trong android.view.animation
. Nếu không có bộ nội suy nào được cung cấp phù hợp với nhu cầu của bạn, hãy triển khai giao diện TimeInterpolator
và tạo giao diện của riêng bạn. Hãy xem phần Sử dụng bộ nội suy để biết thêm thông tin về cách viết bộ nội suy tuỳ chỉnh.
Bảng 3. Bộ nội suy
Lớp/Giao diện | Nội dung mô tả |
---|---|
AccelerateDecelerateInterpolator |
Bộ nội suy có tốc độ thay đổi bắt đầu và kết thúc từ từ nhưng tăng tốc ở giữa. |
AccelerateInterpolator |
Bộ nội suy có tốc độ thay đổi bắt đầu từ từ rồi tăng tốc. |
AnticipateInterpolator |
Bộ nội suy có thay đổi bắt đầu lùi lại phía sau rồi hất về phía trước. |
AnticipateOvershootInterpolator |
Một bộ nội suy có thay đổi bắt đầu lùi lại phía sau, hất lên phía trước và vượt quá giá trị mục tiêu, cuối cùng quay lại giá trị cuối cùng. |
BounceInterpolator |
Bộ nội suy có thay đổi bật lên ở cuối. |
CycleInterpolator |
Bộ nội suy có ảnh động lặp lại trong một số chu kỳ được chỉ định. |
DecelerateInterpolator |
Một bộ nội suy có tốc độ thay đổi bắt đầu nhanh chóng rồi giảm tốc. |
LinearInterpolator |
Bộ nội suy có tốc độ thay đổi là hằng số. |
OvershootInterpolator |
Một bộ nội suy có thay đổi hất về phía trước và vượt quá giá trị cuối cùng, sau đó quay trở lại. |
TimeInterpolator |
Một giao diện cho phép bạn triển khai bộ nội suy của riêng mình. |
Tạo ảnh động bằng ValueAnimator
Lớp ValueAnimator
cho phép bạn tạo ảnh động cho các giá trị thuộc một số loại trong thời lượng của ảnh động bằng cách chỉ định một tập hợp các giá trị int
, float
hoặc màu sắc để tạo ảnh động. Bạn có được ValueAnimator
bằng cách gọi một trong các phương thức ban đầu: ofInt()
, ofFloat()
hoặc ofObject()
. Ví dụ:
Kotlin
ValueAnimator.ofFloat(0f, 100f).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f); animation.setDuration(1000); animation.start();
Trong mã này, ValueAnimator
bắt đầu tính toán giá trị của ảnh động (từ 0 đến 100) trong khoảng thời gian 1000 mili giây khi phương thức start()
chạy.
Bạn cũng có thể chỉ định loại tuỳ chỉnh để tạo ảnh động bằng cách thực hiện các bước sau:
Kotlin
ValueAnimator.ofObject(MyTypeEvaluator(), startPropertyValue, endPropertyValue).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue); animation.setDuration(1000); animation.start();
Trong mã này, ValueAnimator
bắt đầu tính toán các giá trị của ảnh động, từ startPropertyValue
đến endPropertyValue
, bằng cách sử dụng logic do MyTypeEvaluator
cung cấp trong thời gian 1000 mili giây, khi phương thức start()
chạy.
Bạn có thể sử dụng các giá trị của ảnh động bằng cách thêm AnimatorUpdateListener
vào đối tượng ValueAnimator
, như minh hoạ trong đoạn mã sau:
Kotlin
ValueAnimator.ofObject(...).apply { ... addUpdateListener { updatedAnimation -> // You can use the animated value in a property that uses the // same type as the animation. In this case, you can use the // float value in the translationX property. textView.translationX = updatedAnimation.animatedValue as Float } ... }
Java
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator updatedAnimation) { // You can use the animated value in a property that uses the // same type as the animation. In this case, you can use the // float value in the translationX property. float animatedValue = (float)updatedAnimation.getAnimatedValue(); textView.setTranslationX(animatedValue); } });
Trong phương thức onAnimationUpdate()
, bạn có thể truy cập giá trị ảnh động đã cập nhật và sử dụng giá trị đó trong thuộc tính của một trong các khung hiển thị. Để biết thêm thông tin về trình nghe, hãy xem phần Trình nghe ảnh động.
Tạo ảnh động bằng ObjectAnimator
ObjectAnimator
là một lớp con của ValueAnimator
(thảo luận ở phần trước) và kết hợp công cụ định thời gian và tính toán giá trị của ValueAnimator
với khả năng tạo ảnh động cho một thuộc tính được đặt tên của đối tượng mục tiêu. Điều này giúp việc tạo ảnh động cho mọi đối tượng trở nên dễ dàng hơn nhiều vì bạn không cần triển khai ValueAnimator.AnimatorUpdateListener
nữa, vì thuộc tính ảnh động sẽ tự động cập nhật.
Việc tạo thực thể cho ObjectAnimator
cũng tương tự như ValueAnimator
, nhưng bạn cũng chỉ định đối tượng và tên thuộc tính của đối tượng đó (dưới dạng Chuỗi) cùng với các giá trị để tạo ảnh động giữa:
Kotlin
ObjectAnimator.ofFloat(textView, "translationX", 100f).apply { duration = 1000 start() }
Java
ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f); animation.setDuration(1000); animation.start();
Để ObjectAnimator
cập nhật các thuộc tính chính xác, bạn phải làm như sau:
- Thuộc tính đối tượng mà bạn đang tạo ảnh động phải có một hàm setter (trong kiểu viết lạc đà) ở dạng
set<PropertyName>()
. VìObjectAnimator
tự động cập nhật thuộc tính trong khi tạo ảnh động, nên nó phải có thể truy cập vào thuộc tính bằng phương thức setter này. Ví dụ: nếu tên thuộc tính làfoo
, bạn cần có một phương thứcsetFoo()
. Nếu không có phương thức setter này, bạn có 3 lựa chọn:- Thêm phương thức setter vào lớp nếu bạn có quyền làm như vậy.
- Sử dụng một lớp trình bao bọc mà bạn có quyền thay đổi và yêu cầu trình bao bọc đó nhận giá trị bằng một phương thức setter hợp lệ và chuyển tiếp giá trị đó đến đối tượng ban đầu.
- Thay vào đó, hãy sử dụng
ValueAnimator
.
- Nếu bạn chỉ chỉ định một giá trị cho tham số
values...
ở một trong các phương thức ban đầu củaObjectAnimator
, thì giá trị này được giả định là giá trị cuối cùng của ảnh động. Do đó, thuộc tính đối tượng mà bạn đang tạo ảnh động phải có hàm getter dùng để lấy giá trị bắt đầu của ảnh động. Hàm getter phải có dạngget<PropertyName>()
. Ví dụ: nếu tên thuộc tính làfoo
, bạn cần có một phương thứcgetFoo()
. - Các phương thức getter (nếu cần) và setter của thuộc tính mà bạn đang tạo ảnh động phải hoạt động trên cùng một loại với giá trị bắt đầu và kết thúc mà bạn chỉ định cho
ObjectAnimator
. Ví dụ: bạn phải cótargetObject.setPropName(float)
vàtargetObject.getPropName()
nếu tạoObjectAnimator
sau:ObjectAnimator.ofFloat(targetObject, "propName", 1f)
- Tuỳ thuộc vào thuộc tính hoặc đối tượng mà bạn đang tạo ảnh động, bạn có thể cần gọi phương thức
invalidate()
trên Khung hiển thị để buộc màn hình tự vẽ lại bằng các giá trị ảnh động đã cập nhật. Bạn thực hiện việc này trong lệnh gọi lạionAnimationUpdate()
. Ví dụ: việc tạo ảnh động thuộc tính màu của đối tượng có thể vẽ chỉ gây ra cập nhật cho màn hình khi đối tượng đó tự vẽ lại. Tất cả phương thức setter thuộc tính trên Khung hiển thị, chẳng hạn nhưsetAlpha()
vàsetTranslationX()
sẽ vô hiệu hoá Khung hiển thị đúng cách. Vì vậy, bạn không cần vô hiệu hoá Khung hiển thị khi gọi các phương thức này với giá trị mới. Để biết thêm thông tin về trình nghe, hãy xem phần Trình nghe ảnh động.
Choreograph nhiều ảnh động bằng AnimatorSet
Trong nhiều trường hợp, bạn muốn phát ảnh động phụ thuộc vào thời điểm một ảnh động khác bắt đầu hoặc kết thúc. Hệ thống Android cho phép bạn gói các ảnh động lại với nhau vào một AnimatorSet
. Nhờ đó, bạn có thể chỉ định xem nên bắt đầu các ảnh động đồng thời, tuần tự hay sau một độ trễ đã chỉ định. Bạn cũng có thể lồng các đối tượng AnimatorSet
vào nhau.
Đoạn mã sau đây phát các đối tượng Animator
sau theo cách sau:
- Phát
bounceAnim
. - Chơi đồng thời
squashAnim1
,squashAnim2
,stretchAnim1
vàstretchAnim2
. - Phát
bounceBackAnim
. - Phát
fadeAnim
.
Kotlin
val bouncer = AnimatorSet().apply { play(bounceAnim).before(squashAnim1) play(squashAnim1).with(squashAnim2) play(squashAnim1).with(stretchAnim1) play(squashAnim1).with(stretchAnim2) play(bounceBackAnim).after(stretchAnim2) } val fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply { duration = 250 } AnimatorSet().apply { play(bouncer).before(fadeAnim) start() }
Java
AnimatorSet bouncer = new AnimatorSet(); bouncer.play(bounceAnim).before(squashAnim1); bouncer.play(squashAnim1).with(squashAnim2); bouncer.play(squashAnim1).with(stretchAnim1); bouncer.play(squashAnim1).with(stretchAnim2); bouncer.play(bounceBackAnim).after(stretchAnim2); ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(bouncer).before(fadeAnim); animatorSet.start();
Trình nghe ảnh động
Bạn có thể theo dõi các sự kiện quan trọng trong thời lượng của ảnh động bằng các trình nghe được mô tả bên dưới.
Animator.AnimatorListener
onAnimationStart()
– Được gọi khi ảnh động bắt đầu.onAnimationEnd()
– Được gọi khi ảnh động kết thúc.onAnimationRepeat()
– Được gọi khi ảnh động lặp lại.onAnimationCancel()
– Được gọi khi ảnh động bị huỷ. Ảnh động đã huỷ cũng gọionAnimationEnd()
, bất kể cách thức kết thúc.
ValueAnimator.AnimatorUpdateListener
-
onAnimationUpdate()
– được gọi trên mỗi khung của ảnh động. Hãy theo dõi sự kiện này để sử dụng các giá trị đã tính toán doValueAnimator
tạo ra trong một ảnh động. Để sử dụng giá trị này, hãy truy vấn đối tượngValueAnimator
đã truyền vào sự kiện để nhận giá trị ảnh động hiện tại bằng phương thứcgetAnimatedValue()
. Bạn bắt buộc phải triển khai trình nghe này nếu sử dụngValueAnimator
.Tuỳ thuộc vào thuộc tính hoặc đối tượng bạn đang tạo ảnh động, bạn có thể cần gọi
invalidate()
trên một Khung hiển thị để buộc vùng màn hình đó vẽ lại bằng các giá trị ảnh động mới. Ví dụ: việc tạo ảnh động cho thuộc tính màu của đối tượng Có thể vẽ chỉ gây ra nội dung cập nhật cho màn hình khi đối tượng đó tự vẽ lại. Tất cả phương thức setter thuộc tính trên Khung hiển thị, chẳng hạn nhưsetAlpha()
vàsetTranslationX()
sẽ vô hiệu hoá Khung hiển thị đúng cách. Vì vậy, bạn không cần vô hiệu hoá Khung hiển thị khi gọi các phương thức này với giá trị mới.
-
Nếu không muốn triển khai tất cả các phương thức của giao diện Animator.AnimatorListener
, bạn có thể mở rộng lớp AnimatorListenerAdapter
thay vì triển khai giao diện Animator.AnimatorListener
. Lớp AnimatorListenerAdapter
cung cấp các phương thức triển khai trống của các phương thức mà bạn có thể chọn để ghi đè.
Ví dụ: đoạn mã sau đây sẽ tạo một AnimatorListenerAdapter
chỉ cho lệnh gọi lại onAnimationEnd()
:
Kotlin
ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply { duration = 250 addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { balls.remove((animation as ObjectAnimator).target) } }) }
Java
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); fadeAnim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { balls.remove(((ObjectAnimator)animation).getTarget()); }
Tạo ảnh động cho các thay đổi về bố cục cho các đối tượng ViewGroup
Hệ thống ảnh động thuộc tính cung cấp khả năng tạo ảnh động cho các thay đổi đối với đối tượng ViewGroup cũng như cung cấp cách dễ dàng để tạo ảnh động cho chính các đối tượng View.
Bạn có thể tạo ảnh động cho các thay đổi về bố cục trong ViewGroup bằng lớp LayoutTransition
. Các thành phần hiển thị bên trong một ViewGroup có thể
trải qua một ảnh động xuất hiện và biến mất khi bạn thêm ảnh động vào hoặc
xoá khỏi ViewGroup hoặc khi bạn gọi phương thức
setVisibility()
của Chế độ xem bằng
VISIBLE
, INVISIBLE
hoặc
GONE
. Các Khung hiển thị còn lại trong ViewGroup cũng có thể tạo ảnh động vào vị trí mới của chúng khi bạn thêm hoặc xoá Khung hiển thị. Bạn có thể xác định các ảnh động sau trong đối tượng LayoutTransition
bằng cách gọi setAnimator()
và truyền vào một đối tượng Animator
có một trong các hằng số LayoutTransition
sau:
APPEARING
– Một cờ cho biết ảnh động chạy trên các mục đang xuất hiện trong vùng chứa.CHANGE_APPEARING
– Một cờ cho biết ảnh động chạy trên các mục sẽ thay đổi do một mục mới xuất hiện trong vùng chứa.DISAPPEARING
– Một cờ cho biết ảnh động chạy trên các mục đang biến mất khỏi vùng chứa.CHANGE_DISAPPEARING
– Một cờ cho biết ảnh động chạy trên các mục đang thay đổi do một mục biến mất khỏi vùng chứa.
Bạn có thể xác định ảnh động tuỳ chỉnh của riêng mình cho 4 loại sự kiện này để tuỳ chỉnh giao diện của các hiệu ứng chuyển đổi bố cục hoặc chỉ cần yêu cầu hệ thống ảnh động sử dụng các ảnh động mặc định.
Để đặt thuộc tính android:animateLayoutchanges
thành true
cho ViewGroup, hãy làm như sau:
<LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/verticalContainer" android:animateLayoutChanges="true" />
Việc đặt thuộc tính này thành true sẽ tự động tạo ảnh động cho các Khung hiển thị đã thêm hoặc bị xoá khỏi ViewGroup cũng như các Khung hiển thị còn lại trong ViewGroup.
Tạo ảnh động cho các thay đổi về trạng thái khung hiển thị bằng StateListAnimator
Lớp StateListAnimator
cho phép bạn xác định ảnh động sẽ chạy khi trạng thái của khung hiển thị thay đổi. Đối tượng này hoạt động như một trình bao bọc cho đối tượng Animator
, gọi ảnh động đó bất cứ khi nào trạng thái khung hiển thị được chỉ định (chẳng hạn như "đã nhấn" hoặc "lấy làm tâm điểm") thay đổi.
Bạn có thể xác định StateListAnimator
trong tài nguyên XML có phần tử <selector>
gốc và các phần tử con <item>
. Mỗi phần tử chỉ định một trạng thái xem khác nhau do lớp StateListAnimator
xác định. Mỗi <item>
chứa định nghĩa cho một tập hợp ảnh động thuộc tính.
Ví dụ: tệp sau đây sẽ tạo một trình tạo ảnh động danh sách trạng thái để thay đổi tỷ lệ x và y của khung hiển thị khi được nhấn:
res/xml/animate_scale.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- the pressed state; increase x and y size to 150% --> <item android:state_pressed="true"> <set> <objectAnimator android:propertyName="scaleX" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1.5" android:valueType="floatType"/> <objectAnimator android:propertyName="scaleY" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1.5" android:valueType="floatType"/> </set> </item> <!-- the default, non-pressed state; set x and y size to 100% --> <item android:state_pressed="false"> <set> <objectAnimator android:propertyName="scaleX" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1" android:valueType="floatType"/> <objectAnimator android:propertyName="scaleY" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1" android:valueType="floatType"/> </set> </item> </selector>
Để đính kèm trình tạo ảnh động danh sách trạng thái vào một khung hiển thị, hãy thêm thuộc tính
android:stateListAnimator
như sau:
<Button android:stateListAnimator="@xml/animate_scale" ... />
Giờ đây, các ảnh động xác định trong animate_scale.xml
sẽ được dùng khi trạng thái của nút này thay đổi.
Hoặc để chỉ định một ảnh động danh sách trạng thái cho một khung hiển thị trong mã, hãy sử dụng phương thức AnimatorInflater.loadStateListAnimator()
và chỉ định một ảnh động cho khung hiển thị bằng phương thức View.setStateListAnimator()
.
Hoặc thay vì tạo ảnh động cho các thuộc tính của khung hiển thị, bạn có thể phát một ảnh động có thể vẽ giữa các lần thay đổi trạng thái, bằng cách sử dụng AnimatedStateListDrawable
.
Một số tiện ích hệ thống trong Android 5.0 sử dụng các ảnh động này theo mặc định. Ví dụ sau cho thấy cách xác định AnimatedStateListDrawable
dưới dạng tài nguyên XML:
<!-- res/drawable/myanimstatedrawable.xml --> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- provide a different drawable for each state--> <item android:id="@+id/pressed" android:drawable="@drawable/drawableP" android:state_pressed="true"/> <item android:id="@+id/focused" android:drawable="@drawable/drawableF" android:state_focused="true"/> <item android:id="@id/default" android:drawable="@drawable/drawableD"/> <!-- specify a transition --> <transition android:fromId="@+id/default" android:toId="@+id/pressed"> <animation-list> <item android:duration="15" android:drawable="@drawable/dt1"/> <item android:duration="15" android:drawable="@drawable/dt2"/> ... </animation-list> </transition> ... </animated-selector>
Sử dụng TypeEvaluator
Nếu muốn tạo ảnh động cho một loại dữ liệu mà hệ thống Android không xác định, bạn có thể tạo công cụ đánh giá riêng bằng cách triển khai giao diện TypeEvaluator
. Các kiểu mà hệ thống Android xác định là int
, float
hoặc một màu sắc được hỗ trợ bởi trình đánh giá kiểu IntEvaluator
, FloatEvaluator
và ArgbEvaluator
.
Chỉ có một phương thức để triển khai trong giao diện TypeEvaluator
, đó là phương thức evaluate()
. Điều này cho phép trình tạo ảnh động mà bạn đang sử dụng trả về một giá trị thích hợp cho thuộc tính ảnh động tại thời điểm hiện tại của ảnh động. Lớp FloatEvaluator
minh hoạ cách thực hiện việc này:
Kotlin
private class FloatEvaluator : TypeEvaluator<Any> { override fun evaluate(fraction: Float, startValue: Any, endValue: Any): Any { return (startValue as Number).toFloat().let { startFloat -> startFloat + fraction * ((endValue as Number).toFloat() - startFloat) } } }
Java
public class FloatEvaluator implements TypeEvaluator { public Object evaluate(float fraction, Object startValue, Object endValue) { float startFloat = ((Number) startValue).floatValue(); return startFloat + fraction * (((Number) endValue).floatValue() - startFloat); } }
Lưu ý: Khi ValueAnimator
(hoặc ObjectAnimator
) chạy, công cụ này sẽ tính toán một phân số hiện đã trôi qua của ảnh động (giá trị nằm trong khoảng từ 0 đến 1), sau đó tính phiên bản nội suy của ảnh động đó tuỳ thuộc vào bộ nội suy mà bạn đang sử dụng. Phân số nội suy là kết quả mà TypeEvaluator
của bạn nhận được thông qua tham số fraction
, vì vậy, bạn không cần phải tính đến bộ nội suy khi tính các giá trị ảnh động.
Sử dụng bộ nội suy
Bộ nội suy 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. Ví dụ: bạn có thể chỉ định ảnh động diễn ra theo đường thẳng trên toàn bộ ảnh động, nghĩa là ảnh động di chuyển đồng đều trong toàn bộ thời gian, hoặc bạn có thể chỉ định ảnh động để sử dụng thời gian phi tuyến tính, chẳng hạn như sử dụng tính năng tăng tốc hoặc giảm tốc ở đầu hoặc cuối của ảnh động.
Bộ nội suy trong hệ thống ảnh động sẽ nhận một phân số từ Ảnh động biểu thị thời gian đã trôi qua của ảnh động. Bộ nội suy sửa đổi phân số này để trùng khớp với loại ảnh động mà nó muốn cung cấp. Hệ thống Android cung cấp một tập hợp các bộ nội suy phổ biến trong android.view.animation package
. Nếu không có lựa chọn nào phù hợp với nhu cầu của bạn, thì bạn có thể triển khai giao diện TimeInterpolator
và tạo giao diện của riêng mình.
Ví dụ: cách bộ nội suy mặc định AccelerateDecelerateInterpolator
và LinearInterpolator
tính các phân số nội suy được so sánh bên dưới.
LinearInterpolator
không ảnh hưởng đến phân số đã trôi qua. AccelerateDecelerateInterpolator
tăng tốc vào ảnh động và giảm tốc khỏi ảnh động đó. Các phương thức sau đây xác định logic cho các bộ nội suy này:
Bộ nội suy tăng tốc
Kotlin
override fun getInterpolation(input: Float): Float = (Math.cos((input + 1) * Math.PI) / 2.0f).toFloat() + 0.5f
Java
@Override public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; }
Bộ nội suy tuyến tính
Kotlin
override fun getInterpolation(input: Float): Float = input
Java
@Override public float getInterpolation(float input) { return input; }
Bảng sau đây trình bày giá trị gần đúng được tính toán bằng các bộ nội suy này đối với một ảnh động kéo dài 1000 mili giây:
mili giây đã trôi qua | Phân số đã qua/Phân số nội suy (Tuyến tính) | Phân số nội suy (Tăng tốc/Giảm tốc) |
---|---|---|
0 | 0 | 0 |
200 | 0,2 | 0,1 |
400 | 0,4 | 0,345 |
600 | 0,6 | 0,8 |
800 | 0,8 | 0,9 |
1000 | 1 | 1 |
Như bảng cho thấy, LinearInterpolator
thay đổi các giá trị
ở cùng tốc độ, 0,2 cho mỗi 200 mili giây truyền qua. AccelerateDecelerateInterpolator
thay đổi các giá trị nhanh hơn LinearInterpolator
trong khoảng từ 200 mili giây đến 600 mili giây và chậm hơn trong khoảng từ 600 mili giây đến 1000 mili giây.
Chỉ định khung hình chính
Đối tượng Keyframe
bao gồm một cặp thời gian/giá trị cho phép bạn xác định một trạng thái cụ thể tại một thời điểm cụ thể của ảnh động. Mỗi khung hình chính cũng có thể có bộ nội suy riêng để kiểm soát hành vi của ảnh động trong khoảng thời gian giữa thời gian của khung hình chính trước đó và thời gian của khung hình chính này.
Để tạo thực thể cho một đối tượng Keyframe
, bạn phải sử dụng một trong các phương thức ban đầu là ofInt()
, ofFloat()
hoặc ofObject()
để lấy kiểu Keyframe
thích hợp. Sau đó, bạn sẽ gọi phương thức ban đầu ofKeyframe()
để lấy đối tượng PropertyValuesHolder
. Sau khi có đối tượng, bạn có thể tạo ảnh động bằng cách truyền đối tượng PropertyValuesHolder
và đối tượng để tạo ảnh động. Đoạn mã sau đây minh hoạ cách thực hiện việc này:
Kotlin
val kf0 = Keyframe.ofFloat(0f, 0f) val kf1 = Keyframe.ofFloat(.5f, 360f) val kf2 = Keyframe.ofFloat(1f, 0f) val pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2) ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation).apply { duration = 5000 }
Java
Keyframe kf0 = Keyframe.ofFloat(0f, 0f); Keyframe kf1 = Keyframe.ofFloat(.5f, 360f); Keyframe kf2 = Keyframe.ofFloat(1f, 0f); PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2); ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation); rotationAnim.setDuration(5000);
Tạo ảnh động cho khung hiển thị
Hệ thống ảnh động thuộc tính cho phép hợp lý hoá ảnh động của các đối tượng Khung hiển thị và có một số ưu điểm so với hệ thống ảnh động trong khung hiển thị. Hệ thống ảnh động khung hiển thị đã chuyển đổi các đối tượng Khung hiển thị bằng cách thay đổi cách vẽ các đối tượng đó. Việc này đã được xử lý trong vùng chứa của từng Khung hiển thị vì bản thân Khung hiển thị đó không có thuộc tính nào để sử dụng. Điều này khiến Chế độ xem trở thành ảnh động nhưng không làm thay đổi đối tượng Chế độ xem đó. Điều này dẫn đến những hành vi như một đối tượng vẫn tồn tại ở vị trí ban đầu, mặc dù đối tượng đó được vẽ ở một vị trí khác trên màn hình. Trong Android 3.0, các thuộc tính mới cũng như các phương thức getter và setter tương ứng đã được thêm vào để loại bỏ hạn chế này.
Hệ thống ảnh động thuộc tính có thể tạo ảnh động cho Khung hiển thị trên màn hình bằng cách thay đổi các thuộc tính thực tế trong các đối tượng Khung hiển thị. Ngoài ra, Khung hiển thị cũng tự động gọi phương thức invalidate()
để làm mới màn hình bất cứ khi nào thuộc tính của màn hình thay đổi. Các thuộc tính mới trong lớp View
hỗ trợ ảnh động thuộc tính là:
translationX
vàtranslationY
: Các thuộc tính này kiểm soát vị trí của Chế độ xem dưới dạng một delta tính từ toạ độ bên trái và trên cùng do vùng chứa bố cục đặt.rotation
,rotationX
vàrotationY
: Những thuộc tính này kiểm soát việc xoay trong chế độ 2D (thuộc tínhrotation
) và 3D xung quanh điểm trung tâm.scaleX
vàscaleY
: Các thuộc tính này kiểm soát việc điều chỉnh tỷ lệ 2D của một Khung hiển thị xung quanh điểm trung tâm.pivotX
vàpivotY
: Các thuộc tính này kiểm soát vị trí của điểm trung tâm, nơi xảy ra các phép biến đổi xoay và điều chỉnh theo tỷ lệ. Theo mặc định, điểm trung tâm nằm ở giữa đối tượng.x
vày
: Đây là các thuộc tính tiện ích đơn giản để mô tả vị trí cuối cùng của Chế độ xem trong vùng chứa, dưới dạng tổng của các giá trị bên trái và giá trị trên cùng với các giá trị translationX và translationY.alpha
: Biểu thị độ trong suốt alpha trên Chế độ xem. Theo mặc định, giá trị này là 1 (không rõ ràng), với giá trị 0 thể hiện độ trong suốt hoàn toàn (không hiển thị).
Để tạo ảnh động cho một thuộc tính của đối tượng Khung hiển thị, chẳng hạn như màu sắc hoặc giá trị xoay của đối tượng đó, bạn chỉ cần tạo một trình tạo ảnh động thuộc tính và chỉ định thuộc tính Khung hiển thị mà bạn muốn tạo ảnh động. Ví dụ:
Kotlin
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f)
Java
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
Để biết thêm thông tin về cách tạo ảnh động, hãy xem các phần về ảnh động bằng ValueAnimator và ObjectAnimator.
Tạo ảnh động bằng ViewPropertyAnimator
ViewPropertyAnimator
cung cấp một cách đơn giản để tạo ảnh động song song nhiều thuộc tính của View
, sử dụng một đối tượng Animator
cơ bản. Phương thức này hoạt động giống như ObjectAnimator
, vì phương thức này sửa đổi các giá trị thực tế của các thuộc tính của khung hiển thị, nhưng hiệu quả hơn khi tạo ảnh động cho nhiều thuộc tính cùng một lúc. Ngoài ra, mã để sử dụng ViewPropertyAnimator
ngắn gọn và dễ đọc hơn nhiều. Các đoạn mã sau đây cho thấy sự khác biệt trong việc sử dụng nhiều đối tượng ObjectAnimator
, một ObjectAnimator
và ViewPropertyAnimator
khi đồng thời tạo ảnh động cho thuộc tính x
và y
của một khung hiển thị.
Nhiều đối tượng ObjectAnimator
Kotlin
val animX = ObjectAnimator.ofFloat(myView, "x", 50f) val animY = ObjectAnimator.ofFloat(myView, "y", 100f) AnimatorSet().apply { playTogether(animX, animY) start() }
Java
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f); ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f); AnimatorSet animSetXY = new AnimatorSet(); animSetXY.playTogether(animX, animY); animSetXY.start();
Một ObjectAnimator
Kotlin
val pvhX = PropertyValuesHolder.ofFloat("x", 50f) val pvhY = PropertyValuesHolder.ofFloat("y", 100f) ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start()
Java
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f); ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start();
Trình tạo hiệu ứng ViewPropertyAnimator
Kotlin
myView.animate().x(50f).y(100f)
Java
myView.animate().x(50f).y(100f);
Để biết thêm thông tin chi tiết về ViewPropertyAnimator
, hãy xem bài đăng trên blog dành cho nhà phát triển Android tương ứng.
Khai báo ảnh động trong XML
Hệ thống ảnh động thuộc tính cho phép bạn khai báo ảnh động thuộc tính bằng XML thay vì thực hiện việc này theo phương thức lập trình. Bằng cách xác định ảnh động trong XML, bạn có thể dễ dàng sử dụng lại ảnh động trong nhiều hoạt động và dễ dàng chỉnh sửa trình tự ảnh động.
Để phân biệt các tệp ảnh động sử dụng API ảnh động thuộc tính mới với các tệp sử dụng khung ảnh động dạng khung hiển thị cũ, kể từ Android 3.1, bạn nên lưu các tệp XML cho ảnh động thuộc tính trong thư mục res/animator/
.
Các lớp ảnh động thuộc tính sau đây có hỗ trợ khai báo XML với các thẻ XML sau:
ValueAnimator
–<animator>
ObjectAnimator
–<objectAnimator>
AnimatorSet
–<set>
Để tìm các thuộc tính mà bạn có thể dùng trong nội dung khai báo XML, hãy xem phần Tài nguyên ảnh động. Ví dụ sau đây phát 2 tập hợp ảnh động đối tượng theo tuần tự, trong đó tập hợp đầu tiên được lồng phát hai ảnh động đối tượng cùng nhau:
<set android:ordering="sequentially"> <set> <objectAnimator android:propertyName="x" android:duration="500" android:valueTo="400" android:valueType="intType"/> <objectAnimator android:propertyName="y" android:duration="500" android:valueTo="300" android:valueType="intType"/> </set> <objectAnimator android:propertyName="alpha" android:duration="500" android:valueTo="1f"/> </set>
Để chạy ảnh động này, bạn phải tăng cường tài nguyên XML trong mã thành đối tượng AnimatorSet
, sau đó đặt đối tượng mục tiêu cho tất cả các ảnh động trước khi bắt đầu bộ ảnh động. Việc gọi setTarget()
sẽ đặt một đối tượng mục tiêu duy nhất cho tất cả thành phần con của AnimatorSet
để thuận tiện. Mã sau đây minh hoạ cách thực hiện việc này:
Kotlin
(AnimatorInflater.loadAnimator(myContext, R.animator.property_animator) as AnimatorSet).apply { setTarget(myObject) start() }
Java
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.animator.property_animator); set.setTarget(myObject); set.start();
Bạn cũng có thể khai báo ValueAnimator
trong XML, như trong ví dụ sau:
<animator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:valueType="floatType" android:valueFrom="0f" android:valueTo="-100f" />
Để sử dụng ValueAnimator
trước đó trong mã, bạn phải tăng cường đối tượng, thêm AnimatorUpdateListener
, nhận giá trị ảnh động đã cập nhật rồi sử dụng giá trị đó trong thuộc tính của một trong các khung hiển thị của bạn, như minh hoạ trong mã sau:
Kotlin
(AnimatorInflater.loadAnimator(this, R.animator.animator) as ValueAnimator).apply { addUpdateListener { updatedAnimation -> textView.translationX = updatedAnimation.animatedValue as Float } start() }
Java
ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator); xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator updatedAnimation) { float animatedValue = (float)updatedAnimation.getAnimatedValue(); textView.setTranslationX(animatedValue); } }); xmlAnimator.start();
Để biết thông tin về cú pháp XML để xác định ảnh động thuộc tính, hãy xem phần Tài nguyên ảnh động .
Các ảnh hưởng có thể xảy ra đối với hiệu suất của giao diện người dùng
Các ảnh động cập nhật giao diện người dùng sẽ tạo thêm thao tác kết xuất cho mỗi khung hình mà ảnh động chạy trong đó. Vì lý do này, việc sử dụng ảnh động tốn nhiều tài nguyên có thể tác động tiêu cực đến hiệu suất của ứng dụng.
Thao tác cần thiết để tạo ảnh động cho giao diện người dùng sẽ được thêm vào giai đoạn ảnh động của quy trình kết xuất. Bạn có thể tìm hiểu xem ảnh động có ảnh hưởng đến hiệu suất của ứng dụng hay không bằng cách bật tính năng Phân tích trực quan kết xuất GPU và theo dõi giai đoạn ảnh động. Để biết thêm thông tin, hãy xem bài viết Hướng dẫn về kết xuất phân tích GPU.