I'm currently developing an app which uses the flutter_split_view plugin to automatically display split view. There's one main annoyance, though, pressing the Android's native back button from the child screen (i.e. the right widget) simply closes the app.
I have tried using WillPopScope to call SplitView.of(context) on the child screen, because the SplitView constructor does not accept external controllers (e.g. TabController for tabs) which I could call to redirect the back button calls to the SplitView instead.
import 'package:flutter/material.dart';
import 'package:flutter_split_view/flutter_split_view.dart';
class ChildPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
SplitViewState splitView = SplitView.of(context);
return WillPopScope(
onWillPop: () async {
splitView.pop();
return false;
},
child: Scaffold(...),
);
}
}
Is there a way to solve this?
You can use the WillPopScope widget to capture the back button press event, and then use the splitView.pop() method to navigate to the previous screen, instead of closing the app.
By wrapping the Scaffold widget with a WillPopScope widget, you can intercept the back button press event, and then use the splitView.pop() method to navigate to the previous screen. The onWillPop callback should return Future, returning false will prevent the back button from doing its default action, in this case close the app. And that way you can redirect the back button calls to the SplitView instead.
This should work as expected if implemented correctly. However, you should test it on the actual device to make sure the behavior is the one you expect.
Don't think that split_view can help you split the current page into several single running StateFullWidget's. All the pages you see are only controlled by the context of the current page. So, the pop you reference in the subclassed widget will only apply to the current page. If the current page is the last page, there will be no page after running pop, so the program exits
Related
In the MaterialApp constructor, I am injecting a widget in the builder method to handle push notifications. To process foreground notification, I would like to use this widget to show a notification bar (using another_flushbar) but I need a Navigator in the context for that, and MaterialApp's builder injects above the Navigator, so when I try to using it to push my notification bar, there is no Navigator accessible via the context.
Of course, I could wrap every screen of my app with my notification-handling widget, but it defeats the purpose. I want a widget that is always on screen when the app is running, and that can show my notification bar, wherever I am in my app.
Any idea how I can do that?
Here is how I solved it, while still using MaterialApp's builder to inject my NotificationHandler widget ABOVE the Navigator.
My NotificationHandler widget accepts a GlobalKey<NavigatorState> navigatorKey property
When I initialize my NotificationHandler widget inside of MaterialApp's builder, I pass it GoRouter.routerDelegate.navigatorKey
Inside of NotificationHandler, when I need a context with a Navigator above it, I use navigatorKey.currentContext insted of my local widget context.
This solution was inspired by this issue.
In Flutter, I need to pop the route stack until I get to a modal bottom sheet, but I can't figure out how to do that using Navigator.popUntil .
The scenario is this: I have a settings screen (lets call it SettingsScreen) which you can reach in a number of different ways from the main HomeScreen, resulting in a different stack of routes in the navigator. So for example the stack could be:
HomeScreen -> ScreenA -> SettingsScreen
or
HomeScreen -> ScreenA -> ScreenB -> SettingsScreen
Now I need a way to pop until I get to the HomeScreen. Normally I would achieve this using:
Navigator.popUntil(
context,
(Route<dynamic> route) => route.settings.name == "HomeScreen"
);
But here's the catch: sometimes there will be a modal bottom sheet open in the HomeScreen, and I need that to remain open. Since a modal bottom sheet is a route on the stack, if the sheet is open, the stack might be for example:
HomeScreen -> _ModalBottomSheetRoute<dynamic> -> ScreenA -> ScreenB -> SettingsScreen
So popping until I hit the HomeScreen causes the modal bottom sheet to pop, which closes it. So, I need to pop until I get to the HomeScreen OR until I get to _ModalBottomSheetRoute<dynamic>.
Unfortunately the bottom sheet route has no name or arguments in it's settings, and the runtime type of _ModalBottomSheetRoute<dynamic> is private so I can't even use that as a test. So how do I change the logic in Navigator.popUntil to stop when it gets to the modal bottom sheet? Or is there another way of doing this?
how about passing route settings to showModalBottomSheet(... routeSettings: RouteSettings(name: 'MyModalBottomSheet'))? You could then test for the name given in popupUntil....
I have 2 screens - screen A and screen B. I navigate from screen A to screen B.
I want to take some particular action when I am coming BACK to screen A by popping out screen B from the navigation stack.
I know I can use didUpdateWidge but I can't figure out an efficient way of doing it.
Is using Inherited Widget the correct way here?
Navigator.push[Named] returns a Future that completes when screen B pops. So add the code you want to execute after the pop to then.
Navigator.pushNamed(context, '/someRoute').then((_) {/* do stuff here */});
Try to use WillPopScope. This widget allows to catch back button press.
If I am using WillPopScope to overwrite the BackButton behavior with a new route, it works fine. But on iOS, the automatic 'SwipeBack' gesture is not working any more. How can I set the SwipeBack gesture on iOS to push the current screen to the page with the class 'StartScreen'?
WillPopScope(onWillPop: (){
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => StartScreen(),
),
);
}
This may be a very late answer, but at the moment there is no clear opportunity to listen to this gesture
You can achieve the call to onWillPop when you press the back button, and at the same time do not block the gesture if you make a descendant class of the ModalRoute class (or its descendants, such as MaterialPageRoute) and override the hasScopedWillPopCallback method (however, the gesture will not call onWillPop)
WillPopScope is not meant to affect navigation (I.e.: push a route on the navigator). It is meant for vetoing (preventing) navigation away from the current route when you don't want the user to navigate away. (For example, when it might result in data loss.)
Try CupertinoWillPopScope, as it allows you to conditionally veto the back navigation. So you can only block it when there's an actual need.
happy new year! :)
I have three tabs, each holding a stateful widget. The data presented in tab #2 could be changed by the user within tab #3. Thus, when moving back from tab #3 to tab #2, I need to call an update() method within tab #2. Is there a stateful widget method that gets fired everytime the widget gets visible? If not, what opporutinites do I have in order to achieve this?
Best, Nico
The reason it's not updating is due to the widget already been rendered and now cached until the user exits the app. You can try numerous methods to make this work. For example, VoidCallBack method, adding an async function or leaving a blank setState in the initState itself. At the end of the day, it depends on how your app works. If you have a custom tabbar I'd recommend using the VoidCallBack method or maybe adding an async function which will be called before you return a render. Regardless these methods should work.