Chào bạn, có thể bạn hoặc bất kỳ anh em nào code Flutter cũng đều biết việc Flutter rất mạnh về khoản Animation. Mình tin là ít nhiều gì bạn cũng đã thêm 1 vài Animation cơ bản vào project của bản thân rồi. Do đó, hôm nay mình viết bài này để giới thiệu thêm cho bạn cách làm 1 Animation khác cũng khá thú vị không kém nhé. Ok LET'S GET STARTED.
1. Chuẩn bị:
Bạn có thể tạo 1 project Flutter mới hoặc bạn có thể clone started-project demo (nhánh main) của mình phía bên dưới:
Giờ mình sẽ phân tích một xíu về UI nhé! UI chúng ta sẽ bao gồm các thành phần như sau:
Black-hole.
Heart broken
2 nút Button.
Mình sẽ đi thực hiện từng cái một trước nhé! Đầu tiên là Black-hole. Bạn có đoán ra được UI đó code như thế nào không 😄. Ok cái đó chỉ là cái hình thui nhé, không cần phải code đâu hehe. Mình sẽ add cái hình đó vào project của chúng ta. Có bạn sẽ thắc mắc tại sao mình add có 1 hình đúng k? Thui demo mà lấy 1 hình là đủ r nha cả nhà ^^
Tiếp theo mình sẽ điều chỉnh lại UI màn hình Home Page lại 1 xíu và add thêm 2 nút Button, và TickerProviderStateMixin
là cái không thể thiếu khi muốn thực hiện Animation nào đó trên 1 màn hình StatefulWidget bất kỳ.
2. Black-hole Animation:
Chúng ta sẽ bắt đầu với Black-hole Animation nhé! Ý tưởng là khi chúng ta nhấn vào Button "-" (mình sẽ gọi là Minus Button) thì Black-hole sẽ xuất hiện chốc lát sau đó biến mất. Lúc này Twen
widget sẽ vô cùng hữu ích cho chúng ta. Mình sẽ show cho bạn xem code lúc này mình đã update những gì nha!
Mình sẽ giải thích xíu về đoạn code ở trên nhé! Đầu tiên nói về biến holeSizeTween
, ý đồ ở đây các bạn cũng có thể đoán ra được mình muốn có sự thay đổi về kích thước của cái Card từ 0 (begin) cho đến end là cardSize * 1.5
(bạn có thể thay đổi cardSize tuỳ thích nhé!).
Tiếp theo mình khởi tạo holeAnimationController
để control Animation của Black-hole và tất nhiên để đảm bảo việc holeAnimationController
lúc nào cũng lắng nghe đc bất kì thay đổi nào nên mình sẽ đặt listener cho nó ở hàm initState và đừng quên dispose nha các bạn.
Ok chúng ta đã xong phần set up Animation rồi đó. Ok giờ mình sẽ đưa Animation vào UI Home Page. Ở phần body, mình đặt tấm hình mình đã import ở trên vào giữa màn hình.
Sau đó, mình sẽ add function _onPressMinusButton
theo đúng ý đồ mình đã mô tả ở trên là khi mình nhấn Minus Button thì Black-hole sẽ hiện ra một xíu (mình sẽ set nó khoảng 200 milliseconds) và sau đó mình reverse lại Animation (mục đích để nó biến mất).
3. Heart Broken Animation:
Đầu tiên, chúng ta cùng nhau tạo HeartBrokenWidget
(Mình sẽ gọi là Card ở vài chỗ cho đỡ nhạy cảm :v). nhé! Bạn tạo file mới và đặt tên là heart_broken_widget.dart và thực hiện UI Heart Broken đơn giản mình tận dụng lại Icon có sẵn của Flutter.
Tiếp theo, mình sẽ điều chỉnh lại code UI HomePage của chúng ta lại xíu nhé! Mình sẽ thêm Stack Widget bọc bên ngoài Black-hole Animation ở trên và thêm HeartBrokenWidget
vào Stack.
Mình cố tình cho Alignment.bottomCenter để đẩy cái Black-hole Animaton về bottom.
Kế tiếp, mình sẽ thưc hiện Animation cho HeartBrokenWidget
của chúng ta. Ý đồ như mình nói ở trên khi nhấn Minus Button thì Black-hole sẽ hiện ra một xíu và đồng thời HeartBrokenWidget
sẽ rớt xuống theo. Vì thế, mình cũng dùng đúng kỹ thuật Tween như đã sử dụng ở trên.
Ngoài ra, để đảm bảo UI của chúng ta hoạt động đúng như ý đồ, mình bọc thêm 1 cái SizedBox Widget để đảm bảo Black-Hole Animaton không bị rớt xuống cuối thiết bị và update lại code xíu.
Bạn có để ý đến 2 cái TODO ở hình trên không? Mình sẽ update lại tham số cho chính xác và tiếp theo, mình update lại function _onPressMinusButton
để có thể chạy Animation cho HeartBrokenWidget
Mình sẽ giải thích một chút lại đoạn code trên. Đầu tiên mình sẽ ra lệnh cho Black-hole Animation thực hiện, sau đó tới HeartBrokenWidget
thực hiện. Sau đó, mình sẽ delay lại một xíu rồi yêu cầu reverse lại Black-hole Animation.
Tuy nhiên lúc này mình phát sinh nhu cầu muốn reverse lại cái Card nên mình sẽ gắn chức năng vào cho Button "+" (mình sẽ gọi là Add Button).
4. CustomClipper & hoàn thiện Animation:
Đến đây thì chúng ta đã gần xong UI Animation mà chúng ta mong muốn rồi đấy. Tuy nhiên, bạn có thể thấy là lúc Card rớt xuống nó vẫn chưa tạo cảm giác là rớt vào Black-hole. Vì vậy, mình sẽ sử dụng ClipPath
và CustomClipper
để hoàn thiện Animation của chúng ta.
Sau đó, mình sẽ wrap Stack ở trên với ClipPath và assign BlackHoleClipper
như clipper.
Ok vậy là cuối cùng chúng ta cũng đã hoàn tất được Animation 🎉. Cảm ơn bạn đã xem đến đây và bạn có thể lấy source code ở bên dưới nhé!