【问题标题】:Flutter web - Set state based on url [closed]Flutter web - 根据url设置状态[关闭]
【发布时间】:2022-01-19 10:08:24
【问题描述】:

我正在开发一个颤振网站,顶部有一个持久的导航栏,通过在活动页面的标题周围添加一个边框来显示用户所在的当前页面,如下所示。

我在网站上使用 url 导航,因此用户可能能够使用特定 url 访问不同的页面:

  • webpage.com/#/about :打开“关于我”页面
  • webpage.com/#/skills : 打开“技能”页面等

由于用户可以直接访问网站页面,所以我需要在加载页面时根据 url 设置导航栏的状态。但我无法在构建过程中调用 setState 并收到以下错误:

Another exception was thrown: setState() or markNeedsBuild() called during build.

我正在使用 Navigator 和 Routes 来进行 url 导航,如下所示:

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: Strings.appName,
      theme: ThemeData(
        primarySwatch: Colors.cyan,
      ),
      builder: (context, child) => Dashboard(child: child!),
      navigatorKey: locator<NavigationService>().navigatorKey,
      onGenerateRoute: generateRoute,
      initialRoute: Routes.aboutRoute,
    );
  }
}

我使用Provider来控制导航栏的状态如下:

class NavigationBarProvider extends ChangeNotifier {
  List<bool> isSelected = [false, false, false, false];
  List<bool> isHovering = [false, false, false, false];

  void setSelected(int _index) {
    isSelected = List.filled(4, false);

    isSelected[_index] = true;

    notifyListeners();
  }

  void setHovering(int _index, bool _val) {
    isHovering[_index] = _val;

    notifyListeners();
  }

  bool isSelHov(int _index) {
    return isSelected[_index] || isHovering[_index];
  }
}

这是我的导航栏按钮小部件:

return InkWell(
      onTap: () {
        locator<NavigationService>().navigateTo(routeName);

        provider.setSelected(index);
      },
      onHover: (value) {
        provider.setHovering(index, value);
      },
      child: SizedBox(
        width: 100.0,
        height: 50.0,
        child: Stack(
          children: [
            Center(
              child: AnimatedContainer(
                duration: const Duration(milliseconds: 500),
                curve: Curves.easeInCirc,
                width: provider.isSelHov(index) ? 100.0 : 0.0,
                height: provider.isSelHov(index) ? 50.0 : 0.0,
                decoration: BoxDecoration(
                  border: Border.all(
                    color: Colors.white,
                    width: provider.isSelHov(index) ? 0.0 : 10.0,
                  ),
                  borderRadius: BorderRadius.circular(provider.isSelHov(index) ? 10.0 : 50.0),
                ),
              ),
            ),
            Center(
              child: Text(
                name,
                style: const TextStyle(
                  fontSize: 16.0,
                  color: Colors.white,
                ),
              ),
            ),
          ],
        ),
      ),
    );

请帮助我了解如何设置状态,并在使用特定网址启动网站时显示活动的导航按钮。

感谢您的帮助。非常感谢。

编辑

这是我的导航栏代码,带有索引:

ChangeNotifierProvider<NavigationBarProvider>(
            create: (context) => NavigationBarProvider(),
            child: Consumer<NavigationBarProvider>(
              builder: (context, provider, child) {
                return Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: [
                    NavBarButton(
                      index: 0,
                      name: 'About Me',
                      routeName: Routes.aboutRoute,
                      provider: provider,
                    ),
                    NavBarButton(
                      index: 1,
                      name: 'Projects',
                      routeName: Routes.projectsRoute,
                      provider: provider,
                    ),
                    NavBarButton(
                      index: 2,
                      name: 'Skills',
                      routeName: Routes.skillsRoute,
                      provider: provider,
                    ),
                    NavBarButton(
                      index: 3,
                      name: 'Contact Me',
                      routeName: Routes.contactsRoute,
                      provider: provider,
                    ),
                  ],
                );
              },
            ),
          )

编辑 2

我自己设法找到了解决方案,我在下面提供了它作为答案之一。谢谢。

【问题讨论】:

  • 从哪里获取 index 的值?
  • @Diwyansh,请检查编辑,我添加了显示索引的代码部分。

标签: flutter flutter-web flutter-provider flutter-navigation flutter-state


【解决方案1】:

我设法找到了解决方案。我在整个应用程序中实现了 Provider,并在生成路由时更改了选定的值。以下是我的工作代码:

我的运行应用程序:

runApp(
    ChangeNotifierProvider<NavBarProvider>(
      create: (context) => NavBarProvider(),
      child: const MyApp(),
    ),
  );

我正在使用如下自定义 RouteRouteBuilder:

_FadeRoute(
      {required this.index, required this.child, required this.routeName})
      : super(
          settings: RouteSettings(name: routeName),
          pageBuilder: (
            BuildContext context,
            Animation<double> animation,
            Animation<double> secondaryAnimation,
          ) {
            Future.delayed(Duration.zero, () async {
              Provider.of<NavBarProvider>(context, listen: false).setSelected(index);
            });
            return child;
          },
          transitionsBuilder: (
            BuildContext context,
            Animation<double> animation,
            Animation<double> secondaryAnimation,
            Widget child,
          ) {
            return FadeTransition(
              opacity: animation,
              child: child,
            );
          },
        );

其余代码都是一样的,只是我在NavBar Widget中去掉了ChangeNotifierProvider作为父级,只剩下Consumer如下:

Consumer<NavigationBarProvider>(
          builder: (context, provider, child) {
            return Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              crossAxisAlignment: CrossAxisAlignment.end,
              children: [
                NavBarButton(
                  index: 0,
                  name: 'About Me',
                  routeName: Routes.aboutRoute,
                  provider: provider,
                ),
                NavBarButton(
                  index: 1,
                  name: 'Projects',
                  routeName: Routes.projectsRoute,
                  provider: provider,
                ),
                NavBarButton(
                  index: 2,
                  name: 'Skills',
                  routeName: Routes.skillsRoute,
                  provider: provider,
                ),
                NavBarButton(
                  index: 3,
                  name: 'Contact Me',
                  routeName: Routes.contactsRoute,
                  provider: provider,
                ),
              ],
            );
          },
        )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-19
    • 2022-01-21
    • 1970-01-01
    • 2017-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多