beamer
beamer copied to clipboard
Problem with BottomNavigationBar with multiple Beamers
Describe the bug
When implementing BottomNavigation and PageView with multiple Beamers appears a bug. Everything is OK when I'm clicking BottomNavigationBar Items - the pages are changing. Then I'm beaming toNamed to get to one of the pages (friends page). It goes OK too. And tapping BottomNavBarItem goes OK. But if I'm trying to beamToNamed (friends page as previously) again - it redirects to 'Not found' and all the navigation through NavBarItems breaks.
Here is my beamer code parts: main:
class _MyApp extends StatelessWidget {
final BeamerDelegate<BeamState> routerDelegate = BeamerDelegate<BeamState>(
initialPath: '/users',
locationBuilder: SimpleLocationBuilder(
routes: <Pattern, dynamic Function(BuildContext, BeamState)>{
'*': (final BuildContext context, final BeamState state) =>
NavigationScreen(),
},
),
);
MaterialApp:
GetMaterialApp.router(
scaffoldMessengerKey: snackBarKey,
debugShowCheckedModeBanner: false,
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
theme: Theme.of(themeContext),
routerDelegate: routerDelegate,
routeInformationParser: BeamerParser(),
backButtonDispatcher: BeamerBackButtonDispatcher(
delegate: routerDelegate,
),
),
Locations:
class UsersLocation extends BeamLocation<BeamState> {
UsersLocation(final BeamState state) : super(state);
@override
List<String> get pathBlueprints => <String>['/users/'];
@override
List<BeamPage> buildPages(
final BuildContext context,
final BeamState state,
) =>
<BeamPage>[
BeamPage(
key: const ValueKey<String>('users'),
title: 'Users',
type: BeamPageType.noTransition,
child: const DatingScreen(),
),
];
}
class RestaurantsLocation extends BeamLocation<BeamState> {
RestaurantsLocation(final BeamState state) : super(state);
@override
List<String> get pathBlueprints => <String>['/restaurants/'];
@override
List<BeamPage> buildPages(
final BuildContext context,
final BeamState state,
) =>
<BeamPage>[
BeamPage(
key: const ValueKey<String>('restaurants'),
title: 'Restaurants',
type: BeamPageType.noTransition,
child: const DefaultScreen(),
),
];
}
class FriendsLocation extends BeamLocation<BeamState> {
FriendsLocation(final BeamState state) : super(state);
@override
List<String> get pathBlueprints => <String>['/friends/'];
@override
List<BeamPage> buildPages(
final BuildContext context,
final BeamState state,
) =>
<BeamPage>[
BeamPage(
key: const ValueKey<String>('friends'),
title: 'Friends',
type: BeamPageType.noTransition,
child: const FriendsScreen(),
),
];
}
class ChatsLocation extends BeamLocation<BeamState> {
ChatsLocation(final BeamState state) : super(state);
@override
List<String> get pathBlueprints => <String>['/chats/'];
@override
List<BeamPage> buildPages(
final BuildContext context,
final BeamState state,
) =>
<BeamPage>[
BeamPage(
key: const ValueKey<String>('chats'),
title: 'Chats',
type: BeamPageType.noTransition,
child: const ChatsScreen(),
),
];
}
NavigationScreen:
class NavigationScreen extends StatelessWidget {
NavigationScreen({final Key? key}) : super(key: key);
final List<BeamerDelegate<BeamState>> routerDelegates =
<BeamerDelegate<BeamState>>[
BeamerDelegate<BeamState>(
initialPath: '/users',
locationBuilder: (final BeamState state) {
if (state.uri.pathSegments.contains('users')) {
return UsersLocation(state);
}
return NotFound();
},
),
BeamerDelegate<BeamState>(
initialPath: '/restaurants',
locationBuilder: (final BeamState state) {
if (state.uri.pathSegments.contains('restaurants')) {
return RestaurantsLocation(state);
}
return NotFound();
},
),
BeamerDelegate<BeamState>(
initialPath: '/friends',
locationBuilder: (final BeamState state) {
if (state.uri.pathSegments.contains('friends')) {
return FriendsLocation(state);
}
return NotFound();
},
),
BeamerDelegate<BeamState>(
initialPath: '/chats',
locationBuilder: (final BeamState state) {
if (state.uri.pathSegments.contains('chats')) {
return ChatsLocation(state);
}
return NotFound();
},
),
];
@override
Widget build(final BuildContext context) {
final String uriString = Beamer.of(context).state.uri.toString();
final RxInt _page = 0.obs;
if (uriString.contains('users')) {
_page.value = 0;
} else if (uriString.contains('restaurants')) {
_page.value = 1;
} else if (uriString.contains('friends')) {
_page.value = 2;
} else if (uriString.contains('chats')) {
_page.value = 3;
}
final PageController _pageController = PageController(
initialPage: _page.value,
);
routerDelegates[_page.value].active = true;
routerDelegates[_page.value].update();
_pageController.addListener(() {
if (_pageController.page == 0) {
routerDelegates[0].active = true;
routerDelegates[1].active = false;
routerDelegates[2].active = false;
routerDelegates[3].active = false;
routerDelegates[0].update();
} else if (_pageController.page == 1) {
routerDelegates[1].active = true;
routerDelegates[0].active = false;
routerDelegates[2].active = false;
routerDelegates[3].active = false;
routerDelegates[1].update();
} else if (_pageController.page == 2) {
routerDelegates[2].active = true;
routerDelegates[1].active = false;
routerDelegates[0].active = false;
routerDelegates[3].active = false;
routerDelegates[2].update();
} else if (_pageController.page == 3) {
routerDelegates[3].active = true;
routerDelegates[1].active = false;
routerDelegates[2].active = false;
routerDelegates[0].active = false;
routerDelegates[3].update();
}
});
return Scaffold(
resizeToAvoidBottomInset: false,
floatingActionButton: FloatingActionButton(
onPressed: () {
Beamer.of(context).beamToNamed('/friends', replaceCurrent: true);
},
),
body: PageView(
controller: _pageController,
pageSnapping: false,
physics: const NeverScrollableScrollPhysics(),
onPageChanged: (final int newPage) {
_page.value = newPage;
},
children: <Widget>[
Beamer(
key: const Key('users-page'),
routerDelegate: routerDelegates[0],
),
Beamer(
key: const Key('restaurants-page'),
routerDelegate: routerDelegates[1],
),
Beamer(
key: const Key('friends-page'),
routerDelegate: routerDelegates[2],
),
Beamer(
key: const Key('chats-page'),
routerDelegate: routerDelegates[3],
),
],
),
bottomNavigationBar: Obx(
() => BottomNavigationBar(
currentIndex: _page.value,
onTap: (final int index) {
if (index != _page.value) {
_page.value = index;
_pageController.jumpToPage(_page.value);
}
},
items: <BottomNavigationBarItem>[...],
),
),
);
}
}
Beamer version: v0.14.1
To Reproduce Steps to reproduce the behavior:
- Navigate through NavBarItems
- Click FloatingActionButton to get to friends page
- Navigate to any other NavBarItem
- Click again FloatingActionButton to get to friends page
- See "Not Found" page
Smartphone (please complete the following information):
- Device: iPhone13 pro simulator
- OS: iOS15.0 (the same on Android)
Is it a bug or am I doing anything wrong?
Hi @abigotado :wave: Thanks for creating an issue and sorry for a late response.
Have you tried on v1.0.0
?
If you can make a runnable app with the code snippets you provided, that would be much appreciated. I can then migrate it and try against v1.0.0
to check if the problem is still there.
Hello @slovnicki !
Thank you for your response! I'm sorry for answering so long.
No, I haven't tried newer versions, but I think the problem is somewhere in my code and doesn't depend on the version. Well, I've made a special repository to check the problem, so you can see fully reproducible code here: https://github.com/abigotado/problem_beamer_example
Hope you will find some time to see it. Thank you very much!