在Flutter 中父組件調用子組件的方法可以通過GlobalKey
實現,而子組件調用父組件方法可以通過回調函數實現。
父組件
class _MyHomePageState extends State<MyHomePage> {final GlobalKey<LoadPencilState> loadPencilKey = GlobalKey<LoadPencilState>();// 動畫狀態bool isRun = false;@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary,title: Text(widget.title),),body: SizedBox(width: 350,child: Column(children: [LoadPencil(backgroundColor: Colors.blue,key: loadPencilKey,changeState: (state) {setState(() {isRun = state;});},),ElevatedButton(onPressed: () {if (isRun == true) {loadPencilKey.currentState?.stop();} else {loadPencilKey.currentState?.start();}},child: isRun == true ? const Text("停止") : const Text("開始")),],),));}
}
子組件
import 'package:flutter/material.dart';class LoadPencil extends StatefulWidget {final Color backgroundColor;final Function(bool state) changeState;const LoadPencil({super.key, required this.backgroundColor, required this.changeState});@overrideState<StatefulWidget> createState() => LoadPencilState();
}class LoadPencilState extends State<LoadPencil>with SingleTickerProviderStateMixin {// 定義動畫控制器對象late AnimationController _controller;// 定義一個動畫對象late Animation _animation;double _size = 0;@overridevoid initState() {super.initState();_controller = AnimationController(vsync: this,duration: const Duration(seconds: 2),);final Tween tween = Tween(begin: 0, end: 300);_animation = tween.animate(_controller);// 監聽動畫幀的變化,在每一幀中更新UI_animation.addListener(() {setState(() {_size = _animation.value.toDouble();});});// 監聽動畫的狀態,當動畫正序完成后反向執行動畫_controller.addStatusListener((status) {// 動畫狀態status的值有:dismissed(動畫停止在開始處)、forward(正向運行)、reverse(反向運行)、completed(動畫停止在結束處)if (status == AnimationStatus.completed) {_controller.reverse();} else if (status == AnimationStatus.dismissed) {_controller.forward();}});}@overridevoid dispose() {super.dispose();//釋放動畫_controller.dispose();}@overrideWidget build(BuildContext context) {return Container(width: _size,height: 2,color: widget.backgroundColor,);}// 啟動start() {_controller.forward();// 向父組件通信widget.changeState(true);}// 終止stop() {_controller.stop();// 向父組件通信widget.changeState(false);}
}
有一個需要注意的地方是,在使用GlobalKey<>
設置類型時,這個類型子組件的State
,而不是子組件本身
final GlobalKey<LoadPencilState> loadPencilKey = GlobalKey<LoadPencilState>();