英文:
Flutter FCM Navigation onResume/onLaunch
问题
在我的应用程序中,我有一个名为“home”的类,用户在授权后导航到该类。在“home”中,有一个带有BottomNavigationBar的PageView。当用户从Firebase收到推送通知(新消息)时,他应该在点击后导航到特定的聊天ChatHome
和特定的聊天界面。我该如何做到这一点?
ChatHome
看起来像这样:
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
body: PageView(
children: <Widget>[
Feed(userID: widget.userID),
SearchView(),
ChatHome(),
Profile(
uid: currentUser?.uid,
auth: widget.auth,
logoutCallback: widget.logoutCallback,
),
],
controller: pageController,
onPageChanged: onPageChanged,
physics: NeverScrollableScrollPhysics(),
),
bottomNavigationBar: CupertinoTabBar(
currentIndex: pageIndex,
inactiveColor: Colors.white,
backgroundColor: Color.fromRGBO(0, 111, 123, 1),
activeColor: Color.fromRGBO(251, 174, 23, 1),
onTap: onTap,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home, size: 20),
title: Text("Home"),
),
BottomNavigationBarItem(
icon: Icon(Icons.search, size: 20),
title: Text("Search"),
),
BottomNavigationBarItem(
icon: Icon(Icons.chat, size: 20),
title: Text("Chats"),
),
BottomNavigationBarItem(
icon: Icon(Icons.profile, size: 20),
title: Text("Profile"),
),
]),
);
}
在ChatHome中,我有一个ListTiles,显示了所有聊天伙伴。用户点击后会导航到特定的聊天。
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Chat(
chatPartnerId: chatPartner[index].uid,
chatPartnerName: chatPartner[index].username,
chatPartnerPhotoUrl: chatPartner[index].photoUrl)));
在主页中,我有我的onResume
方法。
我尝试了不同的方法,但找不到好的解决方案。
以下代码,我能够导航到ChatHome,但BottomNavigationBar消失了。
onResume: (Map<String, dynamic> message) async {
final screen = message['screen'];
print(screen);
if(screen == "ChatHome"){
Navigator.pushNamed(context, '/chatHome');
}
},
以下代码不起作用,因为应用程序跳来跳去,最终回到主页。
onResume: (Map<String, dynamic> message) async {
final screen = message['screen'];
print(screen);
if(screen == "ChatHome"){
Navigator.pushNamed(context, '/home').then((_) => pageController.jumpToPage(2));
}
},
路由设置如下:
routes: {
'/rootPage': (BuildContext context) => new RootPage(auth: new Auth()),
'/chatHome': (BuildContext context) => ChatHome(),
'/home': (BuildContext context) => Home(),
},
希望对您有所帮助。
英文:
In my app, I got a class "home" where the user is navigated to after he is authorized. Within "home" there is a PageView with BottomNavigationBar. When the user is getting a push notification from firebase (new message) he should be navigated to ChatHome
and to the specific chat after tapping. How can I do this?
Home does look like this
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
body: PageView(
children: <Widget>[
Feed(userID: widget.userID),
SearchView(),
ChatHome(),
Profile(
uid: currentUser?.uid,
auth: widget.auth,
logoutCallback: widget.logoutCallback,
),
],
controller: pageController,
onPageChanged: onPageChanged,
physics: NeverScrollableScrollPhysics(),
),
bottomNavigationBar: CupertinoTabBar(
currentIndex: pageIndex,
inactiveColor: Colors.white,
backgroundColor: Color.fromRGBO(0, 111, 123, 1),
activeColor: Color.fromRGBO(251, 174, 23, 1),
onTap: onTap,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home, size: 20),
title: Text("Home"),
),
BottomNavigationBarItem(
icon: Icon(Icons.search, size: 20),
title: Text("Search"),
),
BottomNavigationBarItem(
icon: Icon(Icons.chat, size: 20),
title: Text("Chats"),
),
BottomNavigationBarItem(
icon: Icon(Icons.profile, size: 20),
title: Text("Profile"),
),
]),
);
}
In ChatHome I got ListTiles with all the chat partners. On click the user is navigated to the specific chat.
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Chat(
chatPartnerId: chatPartner[index].uid,
chatPartnerName: chatPartner[index].username,
chatPartnerPhotoUrl: chatPartner[index].photoUrl)));
In home page, I got my onResume
I tried different things but could find a good solution
With the following code, I was able to navigate to ChatHome but the BottomNavigationBar disappeared.
onResume: (Map<String, dynamic> message) async {
final screen = message['screen'];
print(screen);
if(screen == "ChatHome"){
Navigator.pushNamed(context, '/chatHome');
}
},
The following code didn't work well as the app jumped around and always ends in home.
onResume: (Map<String, dynamic> message) async {
final screen = message['screen'];
print(screen);
if(screen == "ChatHome"){
Navigator.pushNamed(context, '/home').then((_) => pageController.jumpToPage(2));
}
},
routes: {
'/rootPage': (BuildContext context) => new RootPage(auth: new Auth()),
'/chatHome': (BuildContext context) => ChatHome(),
'/home': (BuildContext context) => Home(),
},
Any help is appreciated.
答案1
得分: 1
你需要为你的MaterialApp小部件提供一个navigatorKey:
final GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>();
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
....
navigatorKey: navigatorKey,
......
);
}
}
然后,你可以在onResume
处理程序中使用这个navigatorKey进行导航:
onResume: (message) async {
navigatorKey.currentState.pushNamed("/sample-route/" + message["data"]["..."])
}
对于onLaunch
处理程序(它直接在启动时调用,意味着第一个应用程序视图尚未构建,因此不能立即使用navigatorKey),我只找到了一种“不太干净”的解决方案:
onLaunch: (message) async {
Timer.periodic(
Duration(milliseconds: 500),
(timer) {
if (navigatorKey.currentState == null) return;
navigatorKey.currentState.pushNamed("/sample-route/" + message["data"]["..."]);
timer.cancel();
},
);
}
当然,对于onLaunch
的解决方案并不完美,但它可以工作。
英文:
You need to provide a navigatorKey to your MaterialApp Widget:
final GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>();
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
....
navigatorKey: navigatorKey,
.....
);
}
}
Then, you can use this navigatorKey to navigate in your onResume
handler:
onResume: (message) async {
navigatorKey.currentState.pushNamed("/sample-route/" + message["data"]["..."])
}
For the onLaunch handler (which is called directly onLaunch, means the first app view isn't built yet which means you cannot use the navigatorKey instantly, I only found a hacky solution:
onLaunch: (message) async {
Timer.periodic(
Duration(milliseconds: 500),
(timer) {
if (navigatorKey.currentState == null) return;
navigatorKey.currentState.pushNamed("/sample-route/" + message["data"]["..."]);
timer.cancel();
},
);
}
Of course, the solution for onLaunch isn't clean, but it works.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论