Widget 的淡入淡出效果
在實現 UI 設計時,我們經常需要在螢幕上顯示或隱藏各種元素。如若這個過程只是讓某個元素快速地出現或者消失,使用者們肯定不買帳。我們一般會使用不透明動畫讓元素淡入淡出,以建立出更加流暢的使用者體驗。
在 Flutter 中,你可以使用 AnimatedOpacity
widget 來完成這個效果,請參見下面的步驟:
-
建立一個用來淡入淡出的方框。
-
定義一個
StatefulWidget
。 -
顯示一個用於切換可見狀態的按鈕
-
淡入淡出方框。
1. 建立一個用來淡入淡出的方框
首先是建立一個來淡入淡出的東西。在這個範例中,你將在螢幕上繪製一個綠色的方框。
Container(
width: 200,
height: 200,
color: Colors.green,
)
StatefulWidget
2. 定義一個 我們要對這個綠色的方框進行動畫。那麼為了表示這個方框的狀態是否可見,你需要使用 StatefulWidget
。
StatefulWidget
是一個類,它將會建立一個 State
物件。而這個 State
物件將包含與這個應用相關的一些資料,並且能夠更新它們。當你更新資料時,可以讓Flutter使用這些更改去重建使用者介面。
在這個範例中,我們將使用一個布林值來表示其是否可見。
要構造一個 StatefulWidget
,你需要建立兩個類:一個 StatefulWidget
類以及與其對應的 State
類。小提示:Android Studio 和 VSCode 的 Flutter 外掛都包含了 stful
片段,能夠快速生成該程式碼。
// The StatefulWidget's job is to take data and create a State class.
// In this case, the widget takes a title, and creates a _MyHomePageState.
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
super.key,
required this.title,
});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
// The State class is responsible for two things: holding some data you can
// update and building the UI using that data.
class _MyHomePageState extends State<MyHomePage> {
// Whether the green box should be visible.
bool _visible = true;
@override
Widget build(BuildContext context) {
// The green box goes here with some other Widgets.
}
}
3. 顯示一個用於切換可見狀態的按鈕
現在你已經有了一些資料能夠決定這個綠色方框是否可見,但是還需要一個方法來改變這些資料。在這個例子中,我們想讓方框在顯示與隱藏之間切換。
為此你將使用一個按鈕——當用戶按下按鈕時,資料將會在 true 和 false 之間進行切換。為了使改變生效,你需要使用 State
類別中的 setState()
方法,這會使 Flutter 重建這個 widget。
注意:如果你想要瞭解更多與使用者輸入相關的資料,請參閱 Cookbook 的 Gestures 部分。
FloatingActionButton(
onPressed: () {
// Call setState. This tells Flutter to rebuild the
// UI with the changes.
setState(() {
_visible = !_visible;
});
},
tooltip: 'Toggle Opacity',
child: const Icon(Icons.flip),
)
4. 淡入淡出方框
現在你的螢幕上已經有一個綠色的方框,以及一個可以透過改變 true
或 false
來切換方框可見性的按鈕。那麼該如何讓方框淡入淡出呢?答案是使用 AnimatedOpacity
widget。
AnimatedOpacity
小部件需要傳入三個引數:
-
opacity
:它的取值範圍從 0.0(不可見)到 1.0(完全可見)。 -
duration
:代表這個動畫需要持續多長時間。 -
child
:需要進行動畫的小部件。在這個例子中就是那個綠色的方框。
AnimatedOpacity(
// If the widget is visible, animate to 0.0 (invisible).
// If the widget is hidden, animate to 1.0 (fully visible).
opacity: _visible ? 1.0 : 0.0,
duration: const Duration(milliseconds: 500),
// The green box must be a child of the AnimatedOpacity widget.
child: Container(
width: 200,
height: 200,
color: Colors.green,
),
)
互動式範例
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
const appTitle = 'Opacity Demo';
return const MaterialApp(
title: appTitle,
home: MyHomePage(title: appTitle),
);
}
}
// The StatefulWidget's job is to take data and create a State class.
// In this case, the widget takes a title, and creates a _MyHomePageState.
class MyHomePage extends StatefulWidget {
const MyHomePage({
super.key,
required this.title,
});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
// The State class is responsible for two things: holding some data you can
// update and building the UI using that data.
class _MyHomePageState extends State<MyHomePage> {
// Whether the green box should be visible
bool _visible = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: AnimatedOpacity(
// If the widget is visible, animate to 0.0 (invisible).
// If the widget is hidden, animate to 1.0 (fully visible).
opacity: _visible ? 1.0 : 0.0,
duration: const Duration(milliseconds: 500),
// The green box must be a child of the AnimatedOpacity widget.
child: Container(
width: 200,
height: 200,
color: Colors.green,
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// Call setState. This tells Flutter to rebuild the
// UI with the changes.
setState(() {
_visible = !_visible;
});
},
tooltip: 'Toggle Opacity',
child: const Icon(Icons.flip),
),
);
}
}