大家好,前一篇文章我們已經可以顯示圖片了。Flutter中的動畫方式有很多,今天我準備用AnimatedContainer
來讓它改變透明度以及大小。
根據官方文件的敘述,AnimatedContainer
將自動在屬性的舊值和新值之間設置動畫,並且會按照設定好的曲線(Curve)以及時間(Duration),大家可以參考AnimatedContainer。
先讓我們來加入透明度變化,使用AnimatedOpacity
,基本上每一個這樣的Widget都必須帶duration
,它會讓數值變化在這個時間完成,並且根據不同Curve給他不同插值方式。
class _SplashScreenPageState extends State<SplashScreenPage> {
double logoOpacity = 1.0;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Center(
child: AnimatedOpacity(
opacity: logoOpacity,
duration: Duration(milliseconds: 500),
child: Image.asset("assets/netflix_logo.png")),
),
);
}
}
控制方式其實很簡單,只要更新我們的logoOpacity
變數的值就行了。
我們可以先Wrap一個手勢判斷做個點擊測試一下,參考GestureDetecter
(使用command + Enter 可以快速移除那一層Widget或在外面再包一個Widget)
Center(
child: GestureDetector(
onTap: (){
//點擊時,改變值並通知需要更新UI
setState(() {
logoOpacity = 0.0;
});
},
child: AnimatedOpacity(
opacity: logoOpacity,
duration: Duration(milliseconds: 500),
child: Image.asset("assets/netflix_logo.png")),
),
)
opacity
不能為null,且必須在0.0至1.0之間。
點擊之後讓logoPacity
為0.0,不要忘了來個setState
,不然它不會動的。
目前為止,我們點擊可以讓他正常消失,那如何讓它在一開啟App就自動消失呢?
我們可以在initState
裡做一些事,這些事情會發生在first build 之前。
詳細Flutter生命週期可以參考這篇Flutter從啟動到顯示
@override
void initState() {
super.initState();
//不起作用
setState(() {
logoOpacity = 0.0;
});
//方法一 在畫面第一次build之後,讓logoOpacity改變,似乎不理想
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
logoOpacity = 0.0;
});
//方法二 建立一個延遲`Future`任務,讓它在一秒之後執行
Future.delayed(Duration(seconds: 1), () {
setState(() {
logoOpacity = 0.0;
});
});
}
如果直接在initState
進行setState
是不會有作用的。
方法一,我想使用addPostFrameCallback
,但是app第一次build之後就開始動畫,產生App剛產生畫面,動畫已經播完的情況.(我通常使用addPostFrameCallback
在進入畫面就要顯示一個Dialog的情境)
方法二,使用延遲任務就比較沒問題,點開App一秒之後再讓logo漸變消失
基於前面的測試,再加入大小變化是不是也沒那麼難了呢!我們使用AnimatedContainer
控制大小,並加入Boolean
startAnimation來判斷我們什麼時候要開始動畫
class _SplashScreenPageState extends State<SplashScreenPage> {
bool startAnimation = false;
@override
void initState() {
super.initState();
//方法二
Future.delayed(Duration(seconds: 1), () {
setState(() {
startAnimation = true;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Center(
child: AnimatedOpacity(
opacity: startAnimation ? 0.0 : 1.0,
duration: Duration(milliseconds: 2000),
child: AnimatedContainer(
duration: Duration(milliseconds: 2000),
width: startAnimation ? 150.0 : 250.0,
child: Image.asset("assets/netflix_logo.png"))),
),
);
}
}
今天的進度就到這邊,下一篇我們來進入主頁面!
GitHub連結: flutter-netflix-clone