简体   繁体   English

如何从子更新父小部件的 state

[英]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.

相关问题 Flutter:如何从子小部件更新子(和父)小部件的 state(父小部件得到更新,子小部件没有) - Flutter: How to update state of child (and parent) widget from child widget (parent widget gets update, child does not) 如何从其子 Widget 更新 Parent Widget 的状态,同时在 Flutter 中更新 Child 的状态? - How to update the state of Parent Widget from its Child Widget while also updating the Child's state in Flutter? 如何从子小部件更新父小部件的状态并将其反映在子小部件中? - How to update state of parent widget from child widget and reflect it in child widget? 父小部件中的 State 更新未反映在子小部件中 - State update in parent widget not reflected in child widget 如何从 flutter 中的父小部件访问所有孩子的 state? - How to access all of child's state from Parent Widget in flutter? 如何从父小部件更改一个子小部件的状态,其中子部件是单独文件中的单独类? - How to change state of one child widget from parent widget where the child is a separate class in a separate file? Flutter:从子小部件设置父小部件状态 - Flutter: set parent widget state from child widget 如何从无状态父小部件调用有状态子小部件的状态函数? - How to call state functions of a stateful child widget from a stateless parent widget? Flutter - 如何从子小部件调用父小部件函数,同时还使用变量保持状态? - Flutter - How do I call a Parent widget function from child widget while also maintaining the state with a variable? 如何在更新父有状态小部件时更新子有状态小部件 - How to Update child stateful widget on update parent stateful widget
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM