Flutter web - 根据url设置状态[关闭]

Posted

技术标签:

【中文标题】Flutter web - 根据url设置状态[关闭]【英文标题】:Flutter web - Set state based on url [closed] 【发布时间】: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,请检查编辑,我添加了显示索引的代码部分。 【参考方案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,
                ),
              ],
            );
          ,
        )

【讨论】:

以上是关于Flutter web - 根据url设置状态[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何更改 Flutter web 中的 url?

带有 url 更新和超链接支持的 Flutter web 底部导航栏

Flutter web 自定义 url 路由导致 404

从 URL 下载 TXT 文件并保存到 Flutter Web 上的 PC

为啥在我的 Flutter Web 上使用路径 URL 策略会破坏我的导航?

Flutter:获取 Firebase 存储下载 URL 和上传状态 [重复]