【问题标题】:Flutter material drawer navigate to pagesFlutter 材质抽屉导航到页面
【发布时间】:2020-03-20 16:05:37
【问题描述】:

我是 Flutter 新手,仍在学习中。

我按照Techie Blossom的教程创建了一个带有材质驱动侧边栏的plutter项目

不过,Techie 并未在他的教程中解释如何将导航添加到不同的页面。 我一直在绞尽脑汁想弄清楚该怎么做,但还没有运气。

你们能帮帮我吗?我已将我的项目添加到 GitHub,你们可以在其中 find the code

谢谢

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 0.0,
        backgroundColor: drawerBackgroundColor,
        title: Text('MD Drawer'),
      ),
      body: BlocProvider<CmdNavBloc>(
        create: (context) => CmdNavBloc(),
        child: Stack(
          children: <Widget>[
            BlocBuilder<CmdNavBloc, NavigationStates>(
              builder: (context, state) {
                if (state is Dashboard) {
                  return DashBoardPage();
                } else if (state is Search) {
                  return SearchPage();
                } else if (state is Notifications) {
                  return SearchPage();
                } else if (state is Errors) {
                  return SearchPage();
                } else if (state is Settings) {
                  return SearchPage();
                }
              },
            ),
            CmdDrawer(),
          ],
        ),
      ),
    );
  }
}

【问题讨论】:

  • 我应该如何帮助?分叉你的仓库并添加导航?或者只是在这里举个例子给出一个平面答案?
  • 什么对你来说更容易,我已经在这几个小时了,我还没有接近解决方案。如果你可以分叉回购,那么我感谢你的帮助。

标签: android ios flutter dart


【解决方案1】:

有很多方法可以做您正在寻找的事情,但我看到您正在尝试使用 Bloc 来实现这一目标。这是一个不错的选择,因此您可以在 MyHomePage 类中使用它,如下所示:

BlocProvider<CmdNavBloc>(
    create: (context) => CmdNavBloc(),
    child: Stack(
      children: <Widget>[
        BlocBuilder<CmdNavBloc, NavigationStates>(
          builder: (context, state) {
            if (state is Dashboard) {
              return DashBoardPage();
            } else {
              if (state is Search) {
                return SearchPage();
              } else {
                ....
              }
            }
          },
        ),
        CmdDrawer(),
      ],
    ),
  ),

请记住,Bloc 与事件和状态一起使用,因此您可以在 CmdNavBloc 类中为每个页面添加一个状态,如下所示,并且还生成此状态而不是小部件:

abstract class NavigationStates {}

class Dashboard extends NavigationStates {}

class Search extends NavigationStates {}

...

class CmdNavBloc extends Bloc<NavigationEvents, NavigationStates> {
  @override
  NavigationStates get initialState => Dashboard();

  @override
  Stream<NavigationStates> mapEventToState(NavigationEvents event) async* {
    switch (event) {
      case NavigationEvents.DashboardClickedEvent:
        yield Dashboard();
        break;
      case NavigationEvents.SearchClickedEvent:
        yield Search();
        break;

      ...
    }
  }
}

接下来,您可以在菜单抽屉中填充每个项目的列表,您可以为每个项目添加一个事件以使导航中的事情变得容易,也有很多选项可以实现这一点,但是目前最简单:

class CmdNavModel {
  String title;
  IconData icon;
  NavigationEvents navigationEvent;

  CmdNavModel({this.title, this.icon, this.navigationEvent});
}

List<CmdNavModel> navigationItems = [
  CmdNavModel(
      title: 'Dashboard',
      icon: Icons.insert_chart,
      navigationEvent: NavigationEvents.DashboardClickedEvent),
  CmdNavModel(
      title: 'Search',
      icon: Icons.search,
      navigationEvent: NavigationEvents.SearchClickedEvent),
  CmdNavModel(
      title: 'Notifications',
      icon: Icons.error,
      navigationEvent: NavigationEvents.NotificationsClickedEvent),
  CmdNavModel(
      title: 'Errors',
      icon: Icons.notifications,
      navigationEvent: NavigationEvents.ErrorsClickedEvent),
  CmdNavModel(
      title: 'Settings',
      icon: Icons.settings,
      navigationEvent: NavigationEvents.SettingsClickedEvent),
];

最后,您可以按如下方式在 CmdDrawer 中使用 Bloc,并从项目中的 onTap 将事件添加到 Bloc:`

@override
Widget build(BuildContext context) {
    final CmdNavBloc bloc = BlocProvider.of<CmdNavBloc>(context);

    return AnimatedBuilder(
        animation: _animationController,
        builder: (context, widget) => getWidget(bloc,context, widget),
    );
}

...


Widget getWidget(CmdNavBloc bloc,context, widget) {
    ...
    itemBuilder: (context, counter) {
        return CollapsingListTile(
            onTap: () {
              setState(() {
                bloc.add(navigationItems[counter].navigationEvent);
                currentSelectedIndex = counter;
              });
            },
            isSelected: currentSelectedIndex == counter,
            title: navigationItems[counter].title,
            icon: navigationItems[counter].icon,
            animationController: _animationController,
          );
        },

}

【讨论】:

  • 您好,我在 -return AnimatedBuilder( animation: _animationController, builder: (context, widget) =&gt; getWidget(bloc, context, widget), ); 上遇到错误 --- 位置参数过多:预期 2 个,但找到了 3 个。
  • 哦对了,忘记放那部分代码了,你得在getWidget方法中接收参数:Widget getWidget(CmdNavBloc bloc,context, widget) {},我去更新答案也是。
  • 我现在在 main 中遇到一个新错误 - builder: (context, state) {... ---> 此函数的返回类型为“StatelessWidget”,但不以 return 语句结尾。尝试添加 return 语句,或将返回类型更改为“void”。
  • 我将发布我当前的Main.dart 文件
  • 请看我的主课
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-03
  • 2020-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多