Tìm hiểu về Animations trong Flutter
Bài đăng này đã không được cập nhật trong 6 năm
Các khái niệm và class animation
Animation
Trong Flutter, Animation là một lớp trừu tượng, chỉ có biết giá trị hiện tại và trạng thái của nó (isCompleted và isDismissed ). Một trong những loại animation được sử dụng phổ biến là Animation <double>.
Một đối tượng Animation trong Flutter là tạo ra tuần tự các số được xen vào giữa hai giá trị trong một khoảng thời gian nhất định. Đầu ra của một đối tượng Animation có thể là tuyến tính, đường cong, hàm theo các bước hoặc bất kỳ ánh xạ nào khác mà bạn có thể nghĩ ra. Tùy thuộc vào cách đối tượng Animation được điều khiển, nó có thể chạy theo chiều ngược hoặc thậm chí chuyển hướng ở giữa.
Animations cũng có thể tích hợp vào trong các đối tượng khác ngoài kiểu double, chúng ta còn có thể sử dụng với Animation<Color> hoặc Animation<Size>. Một đối tượng Animation cũng có trạng thái của nó. Trạng thái đó được biểu hiện qua gía trị .value
.
Một đối tượng Animation không biết gì về các hàm render hoặc build ().
CurvedAnimation
Một CurvedAnimation miêu tả tiến trình động giống như một đường cong phi tuyến tính. Ví dụ
Khởi tạo hay định nghĩa một curvedAnimation như sau:
final CurvedAnimation curve =
CurvedAnimation(parent: controller, curve: Curves.easeIn);
Bạn có thể tự tạo một Curve riêng cho mình dựa vào lớp Curves
Ví dụ
class ShakeCurve extends Curve {
double transform(double t) {
return math.sin(t * math.PI * 2);
}
}
CurvedAnimation và AnimationController đều là kiểu Animation<double>, vì thế chúng ta có thể sử dụng thay thế cho nhau. CurvedAnimation sẽ chứa đối tượng nó đang thay đổi, bạn không cần một lớp con AnimationController để thực hiện một curve.
AnimationController
AnimationController là một đối tượng Animation đặc biệt tạo ra một giá trị mới bất cứ khi nào phần cứng sẵn sàng cho một khung mới. Mặc định, AnimationContoder tạo tuyến tính các số từ 0,0 đến 1,0 trong một khoảng thời gian nhất định. Ví dụ sẽ tạo ra một AnimationController
final AnimationController controller = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
AnimationController hỗ trợ phương thức để điều khiển animation.
- Điều khiển animation forward hoặc reverse, hoặc stop
- Đặt animation thành một value cụ thể.
- Định nghĩa các giá trị upperBound and lowerBound trong một animation.
- Tạo ra một fling animation với hiệu ứng sử dụng một mô phỏng vật lý.
Khi tạo AnimationController, bạn truyền cho nó một đối số vsync, ngăn animations tiêu tốn tài nguyên không cần thiết bên ngoài màn hình. Bạn có thể sử dụng đối tượng trạng thái của mình làm vsync bằng cách thêm SingleTickerProviderStateMixin vào định nghĩa lớp. Ví dụ
class _LogoAppState extends State<LogoApp> with SingleTickerProviderStateMixin {
...
}
Tween
Mặc định, đối tượng AnimationController có giá trị nằm trong khoảng từ 0,0 đến 1,0. Nếu bạn cần thay đổi khoảng giá trị khác hoặc một loại dữ liệu khác, bạn có thể sử dụng Tween .
Tween là một đối tượng không có trạng thái, chỉ có lưu giá trị begin
và end
. Công việc duy nhất của Tween là xác định ánh xạ từ phạm vi đầu vào sang phạm vi đầu ra. Phạm vi đầu vào thường là 0,0 đến 1,0.
Ví dụ sau cho phép ta thay đổi giá trị của một Tween<double> nằm trong khoảng từ -200.0 tới 0.0 :
final Tween doubleTween = Tween<double>(begin: -200.0, end: 0.0);
Tween kế thừa từ Animatable<T>, chứ không phải từ Animation<T>. Một Animatable tương tự như Animation hỗ trợ nhiều kiểu khác ngoài double
Ví dụ như ColorTween
final Tween colorTween =
ColorTween(begin: Colors.transparent, end: Colors.black54);
final Tween intTween = IntTween(begin: 0, end: 255);
Một đối tượng Tween không lưu trữ bất kỳ trạng thái. Thay vào đó, nó cung cấp phương thức evaluate(Animation<double> animation)
áp dụng chức năng ánh xạ cho giá trị hiện tại của animation. Giá trị hiện tại của đối tượng Animation có thể được tìm thấy trong phương thức .value
.
Tween.animate
Để sử dụng Tween, bạn cần gọi phương thức animate()
và đặt vào một AnimationController. Phương thức này trả về một Animation, chứ không phải Animatable
Ví dụ sau sẽ tạo ra các giá trị từ 0 -> 255 trong 500 ms cho một AnimationController
final AnimationController controller = AnimationController(
duration: const Duration(milliseconds: 500), vsync: this);
Animation<int> alpha = IntTween(begin: 0, end: 255).animate(controller);
Hiển thị AnimationController, CurvedAnimation và Tween.
final AnimationController controller = AnimationController(
duration: const Duration(milliseconds: 500), vsync: this);
final Animation curve =
CurvedAnimation(parent: controller, curve: Curves.easeOut);
Animation<int> alpha = IntTween(begin: 0, end: 255).animate(curve);
Animation notifications
Một đối tượng Animation có thể có Listeners và StatusListener, được định nghĩa bằng addListener ()
và addStatusListener ()
. Một Listener được gọi bất cứ khi nào giá trị của animation thay đổi. Hành vi phổ biến nhất của Listener là gọi setState () khi ứng dụng rebuild. StatusListener được gọi khi một animation bắt đầu, kết thúc, di chuyển về phía trước hoặc di chuyển ngược lại, như được định nghĩa bởi AnimationStatus.
Chúng ta sử dụng addListener
để lắng nghe thay đổi của một animation trong StatefulWidget
AnimationController controller = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
Animation<double> animation = Tween(begin: 0.0, end: 300.0).animate(controller)
..addListener(() {
setState(() {
// the state that has changed here is the animation object’s value
});
});
controller.forward();
Còn với AnimatedWidget, chúng ta cần phải sử dụng phương thức addStatusListener
để lắng nghe thay đổi của một animation
AnimationController controller = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
Animation<double> animation = Tween(begin: 0.0, end: 300.0).animate(controller);
animation.addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller.reverse();
} else if (status == AnimationStatus.dismissed) {
controller.forward();
}
});
controller.forward();
Summary
- Animation object là core class trong thư viện animation của Flutter.
- Animation object biết được trạng thái hiện tại của một animation (started, stopped, moving forward hoặc reverse), nhưng không biết gì về những gì xuất hiện trên màn hình.
- AnimationController quản lý Animation
- CurvedAnimation thể hiện tiến trình động giống như một đường cong phi tuyến tính.
- Tween sử dụng để thay đổi khoảng giá trị hoặc một loại dữ liệu khác cho một animation.
- Sử dụng Listeners và StatusListeners để theo dõi sự thay đổi trạng thái animation.
Ví dụ
Bạn có thể xem qua ví dụ dưới đây để hiểu thêm cách sử dụng các class : Animation, AnimationController, Tween
import 'package:flutter/animation.dart';
import 'package:flutter/material.dart';
class AnimatedLogo extends AnimatedWidget {
// The Tweens are static because they don't change.
static final _opacityTween = Tween<double>(begin: 0.1, end: 1.0);
static final _sizeTween = Tween<double>(begin: 0.0, end: 300.0);
AnimatedLogo({Key key, Animation<double> animation})
: super(key: key, listenable: animation);
Widget build(BuildContext context) {
final Animation<double> animation = listenable;
return Center(
child: Opacity(
opacity: _opacityTween.evaluate(animation),
child: Container(
margin: EdgeInsets.symmetric(vertical: 10.0),
height: _sizeTween.evaluate(animation),
width: _sizeTween.evaluate(animation),
child: FlutterLogo(),
),
),
);
}
}
class LogoApp extends StatefulWidget {
_LogoAppState createState() => _LogoAppState();
}
class _LogoAppState extends State<LogoApp> with TickerProviderStateMixin {
AnimationController controller;
Animation<double> animation;
initState() {
super.initState();
controller = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
animation = CurvedAnimation(parent: controller, curve: Curves.easeIn);
animation.addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller.reverse();
} else if (status == AnimationStatus.dismissed) {
controller.forward();
}
});
controller.forward();
}
Widget build(BuildContext context) {
return AnimatedLogo(animation: animation);
}
dispose() {
controller.dispose();
super.dispose();
}
}
void main() {
runApp(LogoApp());
}
Bài viết được dịch và tham khảo từ Flutter Animations
All rights reserved