dart 根据选定的导航更改行中的小部件

rqdpfwrv  于 2023-09-28  发布在  其他
关注(0)|答案(1)|浏览(99)

我有一个脚手架和一排在其身体。

class StudentsView extends StatelessWidget {
  const StudentsView({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: [
          if (Responsive.isDesktop(context)) const SideNavigation(),
          if (someCondition) const StudentsPanel(),
          else (someOtherCondition) const SomeOtherPanel(),
          if (Responsive.isDesktop(context))
            Expanded(
              child: Container(
                padding: const EdgeInsets.all(20),
                color: Colors.white,
                child: ListView(
                  children: const [
                    Text(
                      'Preview Panel',
                      style: TextStyle(fontWeight: FontWeight.bold),
                    ),
                  ],
                ),
              ),
            )
        ],
      ),
    );
  }
}

侧边导航小部件如下所示

class SideNavigation extends StatefulWidget {
  const SideNavigation({
    super.key,
  });

  @override
  State<SideNavigation> createState() => _SideNavigationState();
}

class _SideNavigationState extends State<SideNavigation> {
  int _selectedIndex = 0;

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return NavigationRail(
      selectedIndex: _selectedIndex,
      onDestinationSelected: _onItemTapped,
      extended: Responsive.isDesktop(context) ? true : false,
      destinations: const [
        NavigationRailDestination(
          icon: Icon(Icons.person),
          label: Text('Item1'),
        ),
        NavigationRailDestination(
          icon: Icon(Icons.person),
          label: Text('Item2'),
        ),
      ]
    )

如何将NavigationRail中选择的项目冒泡回Scaffold以显示SomeOtherPanel()而不是StudentsPanel()_onItemTapped函数仅更改本地_selectedIndex

uajslkp6

uajslkp61#

所以基本上你是在问状态管理和小部件通信,几年前我写了一篇关于这方面的文章:https://medium.com/flutter-community/flutter-communication-between-widgets-f5590230df1e
您也可以使用状态管理包(如provider、riverpod、bloc等)来实现这一点。
在这个例子中,我只使用回调函数(用于子控件与父控件之间的通信)。
1-将StudentsView转换为Stateful以刷新小部件状态。2-在SideNavigation中创建一个回调函数,以了解项目何时被选中。3-在父控件中添加回调参数以接收值并刷新状态。
完整示例(当然,您可以更改条件):

class StudentsView extends StatefulWidget {
  const StudentsView({super.key});

  @override
  State<StudentsView> createState() => _StudentsViewState();
}

class _StudentsViewState extends State<StudentsView> {

  bool someCondition = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: [
          if (Responsive.isDesktop(context)) SideNavigation(
            onItemSelected: (index){
              if(index == 0) {
                setState(() {
                  someCondition = true;
                });
              } else {
                setState(() {
                  someCondition = false;
                });
              }
            }
          ),
          if (someCondition) const StudentsPanel(),
          else const SomeOtherPanel(),
          if (Responsive.isDesktop(context))
            Expanded(
              child: Container(
                padding: const EdgeInsets.all(20),
                color: Colors.white,
                child: ListView(
                  children: const [
                    Text(
                      'Preview Panel',
                      style: TextStyle(fontWeight: FontWeight.bold),
                    ),
                  ],
                ),
              ),
            )
        ],
      ),
    );
  }
}


class SideNavigation extends StatefulWidget {
  const SideNavigation({
    required this.onItemSelected,
    super.key,
  });

  final ValueChanged<int> onItemSelected;

  @override
  State<SideNavigation> createState() => _SideNavigationState();
}

class _SideNavigationState extends State<SideNavigation> {
  int _selectedIndex = 0;

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
    widget.onItemSelected(index);
  }

  @override
  Widget build(BuildContext context) {
    return NavigationRail(
      selectedIndex: _selectedIndex,
      onDestinationSelected: _onItemTapped,
      extended: Responsive.isDesktop(context) ? true : false,
      destinations: const [
        NavigationRailDestination(
          icon: Icon(Icons.person),
          label: Text('Item1'),
        ),
        NavigationRailDestination(
          icon: Icon(Icons.person),
          label: Text('Item2'),
        ),
      ]
    );
  }
}

相关问题