【问题标题】:Flutter - How to change the body widget of parent, while passing a value, from child?Flutter - 如何在传递值的同时从子级更改父级的主体小部件?
【发布时间】:2021-04-29 06:35:39
【问题描述】:

所以,我有一个“主页”页面,它有一个脚手架、appbar、body 和 bottomNavigationBar。 正文作为小部件从列表中加载,具体取决于在底部导航栏上单击的内容。 我希望能够在当前加载到父正文中的子小部件中按下某些内容,并将父的正文小部件更改为另一个子小部件,同时也将值传递给子小部件。 可以把它想象成在浏览器中按下 iframe 中的链接,只是 iframe 发生变化,您可以传递像 ?id=12 这样的值。

这是“主页”:

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _selectedIndex = 0;
  final List<Widget> _children = [
    Page1(),
    Page2(),
    Page3(),
    Page4()
  ];
  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
              actions: <Widget>[
                TextButton(
                  onPressed: () {},
                  child: Text("Log Out", style: TextStyle(color: Colors.white)),
                ),
              ],
              backgroundColor: Colors.blue.shade900,
            ),
      body: _children[_selectedIndex],
      bottomNavigationBar: BottomNavigationBar(
              items: const <BottomNavigationBarItem>[
                BottomNavigationBarItem(
                  icon: Icon(Icons.work),
                  label: 'Page 1',
                ),
                BottomNavigationBarItem(
                  icon: Icon(Icons.inventory),
                  label: 'Page 2',
                ),
                BottomNavigationBarItem(
                  icon: Icon(Icons.alt_route),
                  label: 'Page 3',
                ),
                BottomNavigationBarItem(
                  icon: Icon(Icons.article),
                  label: 'Page 4',
                ),
              ],
              currentIndex: _selectedIndex,
              onTap: _onItemTapped,
              type: BottomNavigationBarType.fixed,
            ),
    );
  }
}

这是由 _children[_selectedIndex] 通过按下底部导航栏中的按钮之一来定义的子小部件

class Page1 extends StatefulWidget {
  @override
  _Page1State createState() => _Page1State();
}

class _Page1State extends State<Page1> {

  @override
  Widget build(BuildContext context) {
    return Text("Click Here",onPressed:(){
    //objective here is to open Page5 in the body of HomePage(not in _children list of homepage, and pass it some value (ie. id 12))
            },
        ),
    );
  }
}

为了举例说明,这就是我希望在 Page5 中的内容(应该加载到 HomePage 的正文中

class Page5 extends StatefulWidget {
  @override
  _Page5State createState() => _Page5State();
}

class _Page5State extends State<Page5> {
  int _variableFromPage1;
  @override
  Widget build(BuildContext context) {
    return Text(_variableFromPage1);
  }
}

谁能建议最好的方法?

【问题讨论】:

    标签: flutter flutter-navigation flutter-state


    【解决方案1】:

    您可以定义自定义回调函数,如以下代码示例。

    class HomePage extends StatefulWidget {      
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      int _selectedIndex = 0;
      int _selectedID = 0;
    
      List<Widget> _children;
    
      void _onItemTapped(int index) {
        setState(() {
          _selectedIndex = index;
        });
      }
    
      @override
      void initState() {
        super.initState();
    
        _children = [
          Page1(
            callback: (value) {
              setState(() {
                _selectedID = value;
              });
            },
          ),
          Page2(),
        ];
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: (_selectedIndex == 0 && _selectedID > 0)
              ? Page5(id: _selectedID)
              : _children[_selectedIndex],
          bottomNavigationBar: BottomNavigationBar(
            items: const <BottomNavigationBarItem>[
              BottomNavigationBarItem(
                icon: Icon(Icons.work),
                label: 'Page 1',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.inventory),
                label: 'Page 2',
              ),
            ],
            currentIndex: _selectedIndex,
            onTap: _onItemTapped,
            type: BottomNavigationBarType.fixed,
          ),
        );
      }
    }
    
    typedef IntCallback(int value);
    
    class Page1 extends StatelessWidget {
      Page1({Key key, @required this.callback}) : super(key: key);
    
      final IntCallback callback;
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: InkWell(
            onTap: () {
              callback(12);
            },
            child: Text("Page1 ::: id >>> 12"),
          ),
        );
      }
    }
    
    class Page2 extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Center(
          child: Text("Page2"),
        );
      }
    }
    
    class Page5 extends StatelessWidget {
      Page5({Key key, @required this.id}) : super(key: key);
      
      final int id;
    
      @override
      Widget build(BuildContext context) {
        return Center(child: Text("Page5 ::: id $id"));
      }
    }
    

    【讨论】:

    • 我很快就会试试这个,看起来这就是我正在寻找的解决方案。很快就会通知您!
    • 好的,希望对你有帮助。 :)
    【解决方案2】:

    你试试这个方法

    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatefulWidget {
      // This widget is the root of your application.
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      int _selectedIndex = 0;
      final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
      Route<dynamic> generateRoute(RouteSettings settings) {
        switch (settings.name) {
            case "Home":
            return MaterialPageRoute(builder: (context) => Home());
          
          case "Settings":
              return MaterialPageRoute(builder: (context) => Settings());
         
          default:
             return MaterialPageRoute(builder: (context) => Default());
         
        }
      }
    
      void _onItemTapped(int index) {
        switch (index) {
          case 1:
            _navigatorKey.currentState!
                .pushNamedAndRemoveUntil("Home", (route) => false);
            break;
          case 2:
            _navigatorKey.currentState!
                .pushNamedAndRemoveUntil("Settings", (route) => false);
            break;
          default:
            _navigatorKey.currentState!
                .pushNamedAndRemoveUntil("Default", (route) => false);
        }
        setState(() {
          _selectedIndex = index;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          debugShowCheckedModeBanner: false,
          home: Scaffold(
            body: Navigator(key: _navigatorKey, onGenerateRoute: generateRoute),
            bottomNavigationBar: BottomNavigationBar(
              type: BottomNavigationBarType.fixed,
              items: <BottomNavigationBarItem>[
                BottomNavigationBarItem(
                  icon: Icon(Icons.home),
                  label: 'Home',
                ),
                BottomNavigationBarItem(
                  icon: Icon(Icons.settings),
                  label: 'Setting',
                ),
              ],
              showSelectedLabels: true,
              showUnselectedLabels: false,
              currentIndex: _selectedIndex,
              selectedItemColor: Colors.white,
              unselectedItemColor: Color(0xFF9e9e9e),
              iconSize: 16,
              backgroundColor: Color.fromRGBO(58, 66, 86, 1.0),
              onTap: _onItemTapped,
            ),
          ),
        );
      }
    }
    

    【讨论】:

    • 也许我误解了,但这仅处理我正在工作的底部导航栏的导航...我的问题是从正文小部件中单击以更改正文的内容,无需切换整个页面。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-16
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多