I have a card with PopupMenuButton that I can tap to perform the 'copy' action. I can also perform the same action from the card details page. The problem I have is to get back to the home page I have to cater for both paths. So if the action is performed from the details page, I need to pop twice to go back to the home page.
Action from the home page:
Home > add card page
navigator.pop() takes me back to home page
Action from the details page:
home > card details page > add card page
Having to pop twice here.
I know I have to do the pop atleast once and then I used the popUntil to check the current state of the route. For some reason, it is always popping twice.
After debugging, its showing current route as /
void _changeRoute(String newRouteName) {
bool isNewRoute = false;
// Pop once
Navigator.pop(context); // after this I should be on home page for the first path
Navigator.popUntil(context, (route) {
print('Current route is ${route.settings.name}');
if (route.settings.name == newRouteName) { // but this is showing current route as /
isNewRoute = true;
}
return true;
});
print('is home page: $isNewRoute');
if (!isNewRoute) {
Navigator.pop(context);
}
}
I have this working.
My problem was that in my Main App, I had specified the home property on MaterialApp. According to the documentation, if the home property is specified, it takes the route /. So my home page is / and I had it defined as /home in my routes and this was being overridden by /.
Related
I want to remove a specific route and stay on the same page without navigating to different page.
I have three pages PageA, PageB, PageC. I have the below code in PageC and removing PageB from Route stack. After removing it's navigating back to PageA (default route page). I want to stay on the RouteC without navigating.
final newRouteName = "/PageB";
navigatorKey.currentState!.popUntil((route) {
if (widget.routeSettings!.name == newRouteName) {
navigatorKey.currentState!.removeRoute(route);
}
return true;
});
Please help me, i stuck with this for days
I dont know if this works for you, but probably what you can do is:
When navigating from 'Page B' to 'Page C' make a
void _moveToPageC() {
Navigator.pushReplacementNamed(context, '/routeC');
}
That way, your stack would be page a > page c
Then if you want to go back to page a then you can simply pop page C
Hope, this helps
I'm trying to figure out the best way to implement the proper navigation flow of a flutter app I'm building that involves a 3rd party authentication page (Azure AD B2C). Currently I have a page that serves simply as a "navigate to 3rd party auth login" page which is set as the initialRoute for my app. The first time through, it runs exactly the way I want it to, but I'm not able to figure out how to get that 'navigate to auth' page to re-run when navigated back to (after logout) so that the user ends up back at the 3rd party auth login page.
Basically what I'd like to do is, on logout - have the app navigate back to that page specified as the initialRoute page, and upon that page being navigated back to, have it re-launch the 3rd party auth login page just like it did the first time it executed.
I tried just awaiting the call to Navigator.push() and then calling setState((){}) afterwards, and that does re-display the page, but it just leaves that initial page sitting there, and doesn't end up triggering the execution the way it did the first time. initState() does not fire again, so neither does any of my code that's in there.
I've tried various methods off the Navigator object trying to reload the page or navigate to itself again, or just calling goToLogin() again after the await Navigator.push() call, nothing works.
Here's what I'm currently doing :
User launches the app, the initialRoute is LoginRedirect
class LoginRedirect extends StatefulWidget {
#override
_LoginRedirectState createState() => _LoginRedirectState();
}
class _LoginRedirectState extends State<LoginRedirect> {
#override
void initState() {
Utility.getConfig().then((value) {
config = value;
oauth = AadOAuth(config);
goToLogin(context);
});
super.initState();
}
void goToLogin(BuildContext context) async {
setState(() {
loading = true;
});
try {
await oauth.login(); // this launches the 3rd party auth screen which returns here after user signs in
String accessToken = await oauth.getAccessToken();
navigateToDashboard();
setState(() {
loading = false;
});
} on Exception catch (error) {
setState(() {
loading = false;
});
}
}
void navigateToDashboard() {
await navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => Dashboard()));
// right here is where I'd like to call goToLogin() again after I Navigator.popUntil() back to this
// page, but if I try that I get an error page about how 'The specified child already
// has a parent. You must call removeView() on the child's parent first., java.lang
// .IllegalStateException and something about the bottom overflowed by 1063 pixels
}
}
After getting some config values and calling oauth.login() then I call a navigateToDashboard() method that pushes the Dashboard page on to the navigation stack.
Elsewhere in the code I have a logout button that ends up calling this code:
oauth.logout();
Navigator.popUntil(context, ModalRoute.withName('/LoginRedirect'));
which returns execution to where I called await Navigator.push() previously. But I can't figure out what I need to do there to have that LoginRedirect page execute again. I can't call goToLogin() again or it errors/crashes. I can't call initState() again, calling setState() doesn't do anything. I'm kinda stumped here, I thought this would be easy.
When logging out try: Navigator.pushReplacementNamed(context, "/LoginRedirect"); instead of Navigator.popUntil(context, ModalRoute.withName('/LoginRedirect'));
I'm practicing the new API, navigation 2.0, for my web project with flutter. I'm quite new to flutter either.
I successfully implemented the routing with navigation 2.0, but still can't figure out how the onPopPage works. If I tapped the button to navigate to the sub-page, the back button is automatically generated in the header. So when I clicked the back button in the header, it takes me home.
What if I implement another nested sub-page of the sub page, then I clicked the back button it takes me all the way to the top page, home.
I think it's because of the onPopPage function which I added like this. How can I edit this function to work properly. I want the back button to pop the only recent page of navigation history.
onPopPage: (route, result) {
if (!route.didPop(result)) {
return false;
}
_currentPath = 'home';
show404 = false;
notifyListeners();
return true;
},
I have implemented a bottom navigation bar with the logic listed below, and I want to check if the user is logged in. If user is logged in on third tab I want to show the profile page instead of SignIn page. This is my code where I am displaying the bottom navigation bar, I am stuck on what to do after checkIsLoggedIn() async function.
After that Im building list of widgets to show the pages in 3 tabs.
code of which is below,
so in place of SignIn(), I need to show, if the user is logged in it shows signin other wise, it shows Profile page.
Please do help me out here.
This may help.
Future<void> checkIfLoggedIn() async {
SharedPreferences localStorage = await SharedPreferences.getInstance();
var id = localStorage.getString('id');
if (id != null) {
setState(() {
_children[2] = ProfilePage();
});
}
}
Inside checkIfLoggedIn(), along with _isLoggedIn write the following code: _children[2] = Profile().
You can set the last BottomNavigationItem as below
BottomNavigationItem(
icon:_isLoggedIn ? Icons.person : Icons.key,
title:Text(_isLoggedIn ? 'Account' : 'Log in' )
)
and you can handle the click event and set the proper page in the build() by the same ternary operators using the _isLoggedIn variable
build(){
return Scaffold(
body:_isLoggedIn?ProfilePage():LoginPage()
);
}
I have bottom navigation bar which consist of 5 icon which will redirect to 5 screen correspondingly.
The fifth icon is Account screen so when no session it must redirect to Login screen and then load the Account screen. But after login when user tap the Account icon just redirect to Account screen.
How to achieve this? How can I use if condition to determine which layout to load? Error says missing identifier expexted ')'
You can easily achieve this with by passing an async function for the onPressed of Account icon. Your async function would look something like.
Example:
//On Home Page, for account icon pressed
Future<void> checkCredsAndNavigate(){
bool loggedIn = _checkIfLoggedIn(); // this might be a function that gets status of user login, you can fetch from prefs, state, etc.
if(!loggedIn){
var data = await Navigator.of(context).pushNamed('YOUR_LOGIN_ROUTE_NAME');
if(data == null){ // Check for data, will be null when user cancels login
return;
}
}
Navigator.of(context).pushNamed('YOUR_ACCOUNT_ROUTE_NAME');
}
//On Login page,
// On successful login call
Navigator.of(context).pop(data); // this data can be anything like user id, or just a boolean indicating successful login,etc.
//To cancel login, call
Navigator.of(context).pop();
Hope this helps!