如何在 Flutter Web 中动态更改 App Title?
How to dynamically change the App Title in Flutter Web?
Web 应用程序通常会在 选项卡的标题 中反映当前显示的内容。
提供 title
parameter to a MaterialApp
or WidgetsApp
意味着我无法更改它 而不重建整个树 ,即在我 [=34] 的顶层调用 setState
=] 我的 MaterialApp
.
MaterialApp(
title: 'Web app title',
...,
)
我希望能够在任何时间在应用中的任何地方更改应用标题。我该怎么做?
Flutter 中的动态应用标题
应用程序标题可以动态更改在所有平台上使用SystemChrome.setApplicationSwitcherDescription
:
@override
Widget build(BuildContext context) {
SystemChrome.setApplicationSwitcherDescription(ApplicationSwitcherDescription(
label: 'Dynamic web app title',
primaryColor: Theme.of(context).primaryColor.value,
));
return Container(...);
}
SystemChrome
随 import 'package:flutter/services.dart';
可用,并且您想在 build
方法中调用 setApplicationSwitcherDescription
.
这也是Title
does it (see source code),WidgetsApp
、MaterialApp
等
使用的widget
因此,您也可以使用 Title
小部件,而不是自己访问 SystemChrome
:
@override
Widget build(Context context) {
return Title(
label: 'Dynamic app title',
primaryColor: Theme.of(context).primaryColor,
child: ..,
);
}
label
label
参数非常简单:它精确映射到 MaterialApp
中的 title
和 String
.
primaryColor
primaryColor
将确定系统可能在应用程序切换器中使用的颜色,例如Android.
最近的标题栏颜色
这是 int
而不是 Color
的 ,这就是为什么您需要调用 Color.value
将原色转换为整数的原因。
干扰其他Title
您可能会问自己,如果在 MaterialApp
上设置了 title
属性 时调用 setApplicationSwitcherDescription
或插入 Title
小部件是否会导致任何问题。
答案是:no 因为树中最底层的小部件将设置标题。本质上,即使整个应用程序重建,假设您在 child 中调用它,您的 setApplicationSwitcherDescription
也会在 MaterialApp
之后被调用,因此您将 override MaterialApp
标题。
迟了将近 2 年,但我找到了我的解决方案。没那么简单,但很好用。
main.dart
在 MaterialApp
内,添加 navigatorObservers
:
MaterialApp(
initialRoute: "/welcome",
routes: <String, WidgetBuilder>{
'/welcome': (BuildContext context) => WelcomeScreen(),
'/login': (BuildContext context) => LoginScreen(),
'/register': (BuildContext context) => RegisterScreen(),
},
// other codes ...
navigatorObservers: [MyRouteObserver()],
// other codes ...
);
并在最底部添加:
class MyRouteObserver extends RouteObserver<PageRoute<dynamic>> {
void _setTitle(String what, PageRoute<dynamic> routeFrom, PageRoute<dynamic> routeTo) {
final oldScreenName = routeFrom.settings.name;
final newScreenName = routeTo.settings.name;
log("route changed: $what ($oldScreenName -> $newScreenName)"); // it's just route activity log, don't forget to import 'dart:developer';
final uri = Uri.parse(newScreenName ?? "");
final routeName = uri.pathSegments.isNotEmpty ? uri.pathSegments.first : "";
switch ("/$routeName") {
case "/welcome" : return setTitle("Welcome");
case "/login" : return setTitle("Login");
case "/register" : return setTitle("Sign Up");
// etc ...
}
setTitle("Not Found");
}
@override
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
super.didPush(route, previousRoute);
if (route is PageRoute && previousRoute is PageRoute) _setTitle("push", previousRoute, route);
}
@override
void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {
super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
if (newRoute is PageRoute && oldRoute is PageRoute) _setTitle("replace", oldRoute, newRoute);
}
@override
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
super.didPop(route, previousRoute);
if (route is PageRoute && previousRoute is PageRoute) _setTitle("pop", route, previousRoute);
}
}
helpers.dart
void setTitle([String? title]) async {
Future.microtask(() {
SystemChrome.setApplicationSwitcherDescription(ApplicationSwitcherDescription(
label: "Your APP | ${title ?? 'Your Tagline'}",
primaryColor: Colors.blue.value, // your app primary color
));
});
}
最后,如果您想在特定页面中单独覆盖标题,请执行:
@override
void initState() {
super.initState();
WidgetsBinding.instance?.addPostFrameCallback((_) {
setTitle("Custom Page Title");
});
}
Web 应用程序通常会在 选项卡的标题 中反映当前显示的内容。
提供 title
parameter to a MaterialApp
or WidgetsApp
意味着我无法更改它 而不重建整个树 ,即在我 [=34] 的顶层调用 setState
=] 我的 MaterialApp
.
MaterialApp(
title: 'Web app title',
...,
)
我希望能够在任何时间在应用中的任何地方更改应用标题。我该怎么做?
Flutter 中的动态应用标题
应用程序标题可以动态更改在所有平台上使用SystemChrome.setApplicationSwitcherDescription
:
@override
Widget build(BuildContext context) {
SystemChrome.setApplicationSwitcherDescription(ApplicationSwitcherDescription(
label: 'Dynamic web app title',
primaryColor: Theme.of(context).primaryColor.value,
));
return Container(...);
}
SystemChrome
随 import 'package:flutter/services.dart';
可用,并且您想在 build
方法中调用 setApplicationSwitcherDescription
.
这也是Title
does it (see source code),WidgetsApp
、MaterialApp
等
因此,您也可以使用 Title
小部件,而不是自己访问 SystemChrome
:
@override
Widget build(Context context) {
return Title(
label: 'Dynamic app title',
primaryColor: Theme.of(context).primaryColor,
child: ..,
);
}
label
label
参数非常简单:它精确映射到 MaterialApp
中的 title
和 String
.
primaryColor
primaryColor
将确定系统可能在应用程序切换器中使用的颜色,例如Android.
最近的标题栏颜色
这是 int
而不是 Color
的 ,这就是为什么您需要调用 Color.value
将原色转换为整数的原因。
干扰其他Title
您可能会问自己,如果在 MaterialApp
上设置了 title
属性 时调用 setApplicationSwitcherDescription
或插入 Title
小部件是否会导致任何问题。
答案是:no 因为树中最底层的小部件将设置标题。本质上,即使整个应用程序重建,假设您在 child 中调用它,您的 setApplicationSwitcherDescription
也会在 MaterialApp
之后被调用,因此您将 override MaterialApp
标题。
迟了将近 2 年,但我找到了我的解决方案。没那么简单,但很好用。
main.dart
在 MaterialApp
内,添加 navigatorObservers
:
MaterialApp(
initialRoute: "/welcome",
routes: <String, WidgetBuilder>{
'/welcome': (BuildContext context) => WelcomeScreen(),
'/login': (BuildContext context) => LoginScreen(),
'/register': (BuildContext context) => RegisterScreen(),
},
// other codes ...
navigatorObservers: [MyRouteObserver()],
// other codes ...
);
并在最底部添加:
class MyRouteObserver extends RouteObserver<PageRoute<dynamic>> {
void _setTitle(String what, PageRoute<dynamic> routeFrom, PageRoute<dynamic> routeTo) {
final oldScreenName = routeFrom.settings.name;
final newScreenName = routeTo.settings.name;
log("route changed: $what ($oldScreenName -> $newScreenName)"); // it's just route activity log, don't forget to import 'dart:developer';
final uri = Uri.parse(newScreenName ?? "");
final routeName = uri.pathSegments.isNotEmpty ? uri.pathSegments.first : "";
switch ("/$routeName") {
case "/welcome" : return setTitle("Welcome");
case "/login" : return setTitle("Login");
case "/register" : return setTitle("Sign Up");
// etc ...
}
setTitle("Not Found");
}
@override
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
super.didPush(route, previousRoute);
if (route is PageRoute && previousRoute is PageRoute) _setTitle("push", previousRoute, route);
}
@override
void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {
super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
if (newRoute is PageRoute && oldRoute is PageRoute) _setTitle("replace", oldRoute, newRoute);
}
@override
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
super.didPop(route, previousRoute);
if (route is PageRoute && previousRoute is PageRoute) _setTitle("pop", route, previousRoute);
}
}
helpers.dart
void setTitle([String? title]) async {
Future.microtask(() {
SystemChrome.setApplicationSwitcherDescription(ApplicationSwitcherDescription(
label: "Your APP | ${title ?? 'Your Tagline'}",
primaryColor: Colors.blue.value, // your app primary color
));
});
}
最后,如果您想在特定页面中单独覆盖标题,请执行:
@override
void initState() {
super.initState();
WidgetsBinding.instance?.addPostFrameCallback((_) {
setTitle("Custom Page Title");
});
}