我正在嘗試在我的應用程式中創建一個自定義選單欄。現在,我遇到的最大問題是在 setState 發生后將狀態擴展到它的子級時傳遞狀態。
我考慮過繼承,但是從我嘗試過的所有繼承都需要行內。我無法創建一個小部件,其中子 [] 被臨時輸入建構式。
我目前的方法是使用 GlobalKey 更新插入 StateFul 的子小部件的狀態,同時直接更新它們。
我的 MenuBar 的子項宣告為:
List<MenuBarItem> menuItems;
MenuBarItem 是一個抽象介面類,我打算用它來限制可以作為選單項輸入到我的 MenuBar 的小部件。
abstract class iMenuItem extends Widget{}
class MenuBarItem extends StatefulWidget implements iMenuItem{
在這個腳本的一些迭代中,我有一個 bool isExpanded 作為 iMenuItem 的一部分,但確定它沒有必要。
這是我當前迭代的代碼:
我的主要:
void main() {
// runApp(MainApp());
//runApp(InherApp());
runApp(MenuBarApp());
}
class MenuBarApp extends StatelessWidget{
@override
Widget build(BuildContext context){
return MaterialApp(
home: Scaffold(
body: MenuBar(
menuItems: [
// This one does NOT work and is where I'm trying to get the
// value to update after a setState
MenuBarItem(
myText: 'Outsider',
),
],
),
),
);
}
}
我的代碼:
import 'package:flutter/material.dart';
/// Primary widget to be used in the main()
class MenuBar extends StatefulWidget{
List<MenuBarItem> menuItems;
MenuBar({
required this.menuItems,
});
@override
State<MenuBar> createState() => MenuBarState();
}
class MenuBarState extends State<MenuBar>{
bool isExpanded = false;
late GlobalKey<MenuBarContainerState> menuBarContainerStateKey;
@override
void initState() {
super.initState();
menuBarContainerStateKey = GlobalKey();
}
@override
Widget build(BuildContext context){
return MenuBarContainer(
menuItems: widget.menuItems,
);
}
}
class MenuBarContainer extends StatefulWidget{
List<MenuBarItem> menuItems;
late Key key;
MenuBarContainer({
required this.menuItems,
key,
}):super(key: key);
@override
MenuBarContainerState createState() => MenuBarContainerState();
}
class MenuBarContainerState extends State<MenuBarContainer>{
bool isExpanded = false;
@override
void initState() {
super.initState();
isExpanded = false;
}
@override
Widget build(BuildContext context){
List<Widget> myChildren = [
ElevatedButton(
onPressed: (){
setState((){
this.isExpanded = !this.isExpanded;
});
},
child: Text('Push Me'),
),
// This one works. No surprise since it's in-line
MenuBarItem(isExpanded: this.isExpanded, myText: 'Built In'),
];
myChildren.addAll(widget.menuItems);
return Container(
child: Column(
children: myChildren,
),
);
}
}
/// The item that will appear as a child of MenuBar
/// Uses the iMenuItem to limit the children to those sharing
/// the iMenuItem abstract/interface
class MenuBarItem extends StatefulWidget implements iMenuItem{
bool isExpanded;
String myText;
MenuBarItem({
key,
this.isExpanded = false,
required this.myText,
}):super(key: key);
@override
State<MenuBarItem> createState() => MenuBarItemState();
}
class MenuBarItemState extends State<MenuBarItem>{
@override
Widget build(BuildContext context){
GlobalKey<MenuBarState> _menuBarState;
return Row(
children: <Widget> [
Text('Current Status:\t${widget.isExpanded}'),
Text('MenuBarState GlobalKey:\t${GlobalKey<MenuBarState>().currentState?.isExpanded ?? false}'),
Text(widget.myText),
],
);
}
}
/// To give a shared class to any children that might be used by MenuBar
abstract class iMenuItem extends Widget{
}
我已經花了 3 天的時間,所以任何幫助將不勝感激。
謝謝!!
uj5u.com熱心網友回復:
我建議使用ChangeNotifier,ChangeNotifierProvider,Consumer和context.read管理的狀態。你必須添加這個包和這個匯入:import 'package:provider/provider.dart';。步驟:
- 設定一個
ChangeNotifier持有isExpanded值,用一個通知聽眾的設定器:
class MyNotifier with ChangeNotifier {
bool _isExpanded = false;
bool get isExpanded => _isExpanded;
set isExpanded(bool isExpanded) {
_isExpanded = isExpanded;
notifyListeners();
}
}
- 將上述內容作為 a 插入到
ChangeNotifierProvider您的小部件樹中MenuBar:
class MenuBarState extends State<MenuBar> {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => MyNotifier(),
child: MenuBarContainer(
menuItems: widget.menuItems,
));
}
}
在此之后,您可以輕松地isExpanded從 小部件樹中的任何位置讀取和寫入值ChangeNotifierProvider,例如:
ElevatedButton(
onPressed: () {
setState(() {
final myNotifier = context.read<MyNotifier>();
myNotifier.isExpanded = !myNotifier.isExpanded;
});
},
child: Text('Push Me'),
),
如果您想使用此狀態在isExpanded更改時自動構建某些內容,請使用Consumer,它會在每次更改時自動通知,例如:
class MenuBarItemState extends State<MenuBarItem> {
@override
Widget build(BuildContext context) {
return Consumer<MyNotifier>(builder: (context, myNotifier, child) {
return Row(
children: <Widget>[
Text('Current Status:\t${myNotifier.isExpanded}'),
Text(widget.myText),
],
);
});
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/369383.html
