[英]How to update state of parent widget from child
I have been trying to make a custom drawer using Animated Container.我一直在尝试使用动画容器制作自定义抽屉。 When I put each animated container as a child in AnimatedSwitcher (Menu, Cheatsheet, Reference) conditionally, it displays everything.当我有条件地将每个动画容器作为孩子放入 AnimatedSwitcher(菜单、备忘单、参考)时,它会显示所有内容。 THERE IS NO UPDATE when I segregate each animated container in a stateful widget and then pass it to the child of AnimatedSwitcher.当我在有状态小部件中隔离每个动画容器然后将其传递给 AnimatedSwitcher 的子级时,没有更新。 I am not sure what I am doing wrong.我不确定我做错了什么。
Here is the main.dart for reference, I am passing the DrawerControllerMain in line 87这是 main.dart 供参考,我在第 87 行传递了 DrawerControllerMain
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:regex_query/Drawers/main_drawer.dart';
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.black87,
backgroundColor: const Color(0xFFEFFFFD),
drawerTheme: const DrawerThemeData(
backgroundColor: Color(0xFF85F4FF),
elevation: 20,
),
),
darkTheme: ThemeData(),
initialRoute: '/',
routes: {
'/': (context) => const RegexQuery(),
},
));
}
class RegexQuery extends StatefulWidget {
const RegexQuery({Key? key}) : super(key: key);
@override
State<RegexQuery> createState() => _RegexQueryState();
}
class _RegexQueryState extends State<RegexQuery> {
final Color _backgroundColor = const Color(0xFFEFFFFD);
bool expanded = true;
@override
Widget build(BuildContext context) {
final _screenSize = MediaQuery.of(context).size;
final _screenWidth = _screenSize.width;
final _screenHeight = _screenSize.height;
return Scaffold(
backgroundColor: _backgroundColor,
body: Column(
children: [
SizedBox(
child: AppBar(
backgroundColor: const Color(0xFFC8FFDE),
centerTitle: true,
title: Text(
'Regex Query Tool',
style: GoogleFonts.stalinistOne(
textStyle:
const TextStyle(color: Colors.black87, fontSize: 30)),
),
leading: Text(
'.*',
style: GoogleFonts.xanhMono(
textStyle:
const TextStyle(color: Colors.black87, fontSize: 45)),
),
actions: [
Text(
'*. ',
style: GoogleFonts.xanhMono(
textStyle:
const TextStyle(color: Colors.black87, fontSize: 45)),
),
],
toolbarHeight: 1000,
),
width: _screenWidth,
height: 50,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [DrawerControllerMain()]),
],
),
);
}
}
Here is the file main_drawer.dart这是文件 main_drawer.dart
import 'dart:html';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:regex_query/main.dart' as main;
class DrawerControllerMain extends StatefulWidget {
const DrawerControllerMain({Key? key}) : super(key: key);
@override
State<DrawerControllerMain> createState() => _DrawerControllerMainState();
}
class _DrawerControllerMainState extends State<DrawerControllerMain> {
bool expanded = true;
Map<String, bool> drawerControllerMapping = {
"Menu": true,
"Cheatsheet": false,
"References": false,
};
@override
Widget build(BuildContext context) {
return AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
child: drawerControllerMapping['Cheatsheet'] == true
? CheatsheetDrawer(
drawerControllerMapping: drawerControllerMapping,
function: () {
setState(() {
drawerControllerMapping['Cheatsheet'] = true;
});
},
)
:
// References Drawer...
drawerControllerMapping['References'] == true
? ReferenceDrawer(
drawerControllerMapping: drawerControllerMapping,
function: () {
setState(() {
drawerControllerMapping['References'] = true;
});
},
)
: MenuDrawer(
drawerControllerMapping: drawerControllerMapping,
function: () {
setState(() {
drawerControllerMapping['Menu'] = true;
});
},
));
}
}
class MenuDrawer extends StatefulWidget {
Map drawerControllerMapping;
final Function function;
MenuDrawer(
{Key? key, required this.drawerControllerMapping, required this.function})
: super(key: key);
@override
State<MenuDrawer> createState() => _MenuDrawerState();
}
class _MenuDrawerState extends State<MenuDrawer> {
@override
Widget build(BuildContext context) {
final _screenSize = MediaQuery.of(context).size;
final _screenWidth = _screenSize.width;
final _screenHeight = _screenSize.height;
bool expanded = true;
const _drawerColor = Color(0xFFD6FFF4);
void drawerUpScale() {
setState(() {
expanded = !expanded;
});
}
return AnimatedContainer(
key: const Key('1'),
duration: const Duration(milliseconds: 250),
curve: Curves.easeOutExpo,
height: _screenHeight - 50,
width: expanded ? 450 : 65,
decoration: const BoxDecoration(color: _drawerColor),
child: Column(children: [
ListTile(
leading: const Icon(
Icons.menu,
size: 30,
),
title: expanded
? const Text(
'Menu',
)
: null,
onTap: () {
drawerUpScale();
},
),
ListTile(
leading: const Icon(
Icons.view_column_outlined,
size: 30,
),
title: expanded
? const Text(
'Cheatsheet',
)
: null,
onTap: () {
setState(() {
widget.function;
});
},
),
ListTile(
leading: const Icon(
Icons.auto_stories_sharp,
size: 30,
),
title: expanded
? const Text(
'References',
)
: null,
onTap: () {
setState(() {
widget.function;
});
},
),
]),
);
}
}
class ReferenceDrawer extends StatefulWidget {
var drawerControllerMapping;
final Function function;
ReferenceDrawer(
{Key? key, required this.drawerControllerMapping, required this.function})
: super(key: key);
@override
State<ReferenceDrawer> createState() => _ReferenceDrawerState();
}
class _ReferenceDrawerState extends State<ReferenceDrawer> {
@override
Widget build(BuildContext context) {
final _screenSize = MediaQuery.of(context).size;
final _screenWidth = _screenSize.width;
final _screenHeight = _screenSize.height;
bool expanded = true;
const _drawerColor = Color(0xFFD6FFF4);
void drawerUpScale() {
setState(() {
expanded = !expanded;
});
}
return AnimatedContainer(
key: Key('2'),
duration: const Duration(milliseconds: 250),
curve: Curves.easeOutExpo,
height: _screenHeight - 50,
width: expanded ? 450 : 65,
decoration: const BoxDecoration(color: _drawerColor),
child: Column(children: [
ListTile(
leading: const Icon(
Icons.arrow_back_ios_new_rounded,
size: 30,
),
onTap: () {
setState(() {
this.widget.drawerControllerMapping['References'] = false;
});
}),
ListTile(
leading: const Icon(
Icons.auto_stories_sharp,
size: 30,
),
title: expanded
? const Text(
'References',
)
: null,
onTap: () {
drawerUpScale();
},
),
]),
);
}
}
class CheatsheetDrawer extends StatefulWidget {
var drawerControllerMapping;
final Function function;
CheatsheetDrawer(
{Key? key, this.drawerControllerMapping, required this.function})
: super(key: key);
@override
State<CheatsheetDrawer> createState() => _CheatsheetDrawerState();
}
class _CheatsheetDrawerState extends State<CheatsheetDrawer> {
@override
Widget build(BuildContext context) {
final _screenSize = MediaQuery.of(context).size;
final _screenWidth = _screenSize.width;
final _screenHeight = _screenSize.height;
bool expanded = true;
const _drawerColor = Color(0xFFD6FFF4);
void drawerUpScale() {
setState(() {
expanded = !expanded;
});
}
return AnimatedContainer(
key: Key('2'),
duration: const Duration(milliseconds: 250),
curve: Curves.easeOutExpo,
height: _screenHeight - 50,
width: expanded ? 450 : 65,
decoration: const BoxDecoration(color: _drawerColor),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListTile(
leading: const Icon(
Icons.arrow_back_ios_new_rounded,
size: 30,
),
onTap: () {
setState(() {
this.widget.drawerControllerMapping['Cheatsheet'] = false;
});
},
),
ListTile(
leading: const Icon(
Icons.view_column_outlined,
size: 30,
),
title: expanded
? const Text(
'Cheatsheet',
)
: null,
onTap: () {
drawerUpScale();
},
),
const SizedBox(
height: 20,
),
InkWell(
onTap: () => print('Character Classes'),
child: Container(
child: const Text('Character Classes'),
color: Colors.indigo,
padding:
const EdgeInsets.only(top: 10, bottom: 10, left: 20),
width: 450,
)),
ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: [
// ListTile(title: Container(child: const Text('Character Classes'), color: Colors.indigo, padding: const EdgeInsets.only(top: 10, bottom: 10),), tileColor: Colors.indigo,),
ListTile(
title: Table(
defaultVerticalAlignment:
TableCellVerticalAlignment.middle,
columnWidths: const <int, TableColumnWidth>{
0: FixedColumnWidth(5),
1: FixedColumnWidth(100),
},
children: const [
TableRow(decoration: BoxDecoration(), children: [
Text(
'.',
style: TextStyle(fontSize: 20),
),
Text('Any Character except newline'),
]),
TableRow(decoration: BoxDecoration(), children: [
Text(r'\w \d \s'),
Text('word, digit, whitespace'),
]),
TableRow(decoration: BoxDecoration(), children: [
Text(r'\W \D \S'),
Text('NOT word, digit, whitespace'),
]),
TableRow(decoration: BoxDecoration(), children: [
Text('[abc]'),
Text(
'any of a, b, or c',
),
]),
TableRow(decoration: BoxDecoration(), children: [
Text('[^abc]'),
Text('not a, b, or c'),
]),
TableRow(decoration: BoxDecoration(), children: [
Text('[a-g]'),
Text('character between a & g'),
]),
],
),
),
InkWell(
onTap: () => print('Anchors'),
child: Container(
child: const Text('Anchors'),
color: Colors.indigo,
padding: const EdgeInsets.only(
top: 10, bottom: 10, left: 20),
width: 450,
)),
ListTile(
title: Table(
defaultVerticalAlignment:
TableCellVerticalAlignment.middle,
columnWidths: const <int, TableColumnWidth>{
0: FixedColumnWidth(5),
1: FixedColumnWidth(100),
},
children: const [
TableRow(decoration: BoxDecoration(), children: [
Text(r'^ , $'),
Text('Start / End of the string'),
]),
TableRow(decoration: BoxDecoration(), children: [
Text(r'\b \B'),
Text('word, not-word boundary'),
]),
],
),
),
InkWell(
onTap: () => print('Escaped Characters'),
child: Container(
child: const Text('Escaped Characters'),
color: Colors.indigo,
padding: const EdgeInsets.only(
top: 10, bottom: 10, left: 20),
width: 450,
)),
ListTile(
title: Table(
defaultVerticalAlignment:
TableCellVerticalAlignment.middle,
columnWidths: const <int, TableColumnWidth>{
0: FixedColumnWidth(5),
1: FixedColumnWidth(100),
},
children: const [
TableRow(decoration: BoxDecoration(), children: [
Text(r'\. \* \\'),
Text('escaped special characters'),
]),
TableRow(decoration: BoxDecoration(), children: [
Text(r'\t \n \r'),
Text('tab, linefeed, carriage return'),
]),
],
),
),
InkWell(
onTap: () => print('Groups and LookAround'),
child: Container(
child: const Text('Groups and LookAround'),
color: Colors.indigo,
padding: const EdgeInsets.only(
top: 10, bottom: 10, left: 20),
width: 450,
)),
ListTile(
title: Table(
defaultVerticalAlignment:
TableCellVerticalAlignment.middle,
columnWidths: const <int, TableColumnWidth>{
0: FixedColumnWidth(5),
1: FixedColumnWidth(100),
},
children: const [
TableRow(decoration: BoxDecoration(), children: [
Text('(abc)'),
Text('capture group'),
]),
TableRow(decoration: BoxDecoration(), children: [
Text(r'\1'),
Text('back-reference to group #1'),
]),
TableRow(decoration: BoxDecoration(), children: [
Text(r'(?:abc)'),
Text('non-capturing group'),
]),
TableRow(decoration: BoxDecoration(), children: [
Text('(?=abc)'),
Text(
'positive lookahead',
),
]),
TableRow(decoration: BoxDecoration(), children: [
Text('(?!abc)'),
Text('negative lookahead'),
]),
],
),
),
InkWell(
onTap: () => print('Tapped Quantifiers and Alterations'),
child: Container(
child: const Text('Quantifiers and ALterations'),
color: Colors.indigo,
padding: const EdgeInsets.only(
top: 10, bottom: 10, left: 20),
width: 450,
)),
ListTile(
title: Table(
defaultVerticalAlignment:
TableCellVerticalAlignment.middle,
columnWidths: const <int, TableColumnWidth>{
0: FixedColumnWidth(5),
1: FixedColumnWidth(100),
},
children: const [
TableRow(decoration: BoxDecoration(), children: [
Text('a* a+ a?'),
Text('0 or more, 1 or more, 0 or 1'),
]),
TableRow(decoration: BoxDecoration(), children: [
Text(r'a{5} a{2,}'),
Text('exactly five, two or more'),
]),
TableRow(decoration: BoxDecoration(), children: [
Text(r'a{1,3}'),
Text('between one & three'),
]),
TableRow(decoration: BoxDecoration(), children: [
Text('a+? a{2,}?'),
Text(
'match as few as possible',
),
]),
TableRow(decoration: BoxDecoration(), children: [
Text('ab|cd'),
Text('match ab or cd'),
]),
],
),
),
],
),
]),
),
);
}
}
There are multiple ways to solve such a task.有多种方法可以解决这样的任务。 The easiest would be to use a callback function, which you pass in as an argument to the child widget.最简单的方法是使用回调 function,将其作为参数传递给子小部件。
You could also try to lift state up using some state library like BLoC or Provider.您也可以尝试使用 BLoC 或 Provider 等 state 库来提升 state。 You then build the parent when the state changes.然后在 state 更改时构建父级。
Some examples for the callback approach: https://medium.com/nerd-for-tech/lifting-state-up-and-callbacks-7a19d0bdbe53回调方法的一些示例: https://medium.com/nerd-for-tech/lifting-state-up-and-callbacks-7a19d0bdbe53
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.