Thanks for giving time to read this question and help me.
I have a SideDrawer in my home screen having two options. If I click on 'Tickets' I want Flutter to produce a new page with the tickets.
But, this doesn't seem to be the case. Whenever i tap on 'Tickets', nothing loads. I am pretty sure the function userData() does execute, but doesn't load the new page.
You need to push new screen on the navigation screen. So do this
Future<void> userData(BuildContext context) async {
final FirebaseAuth auth = FirebaseAuth.instance;
final FirebaseUser user = await auth.currentUser();
uid = user.uid;
goToTicketScreen(context,uid); //Add thiis
}
Then define the function as follow
Future<void> goToTicketScreen(BuildContext context,String uid) async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>TicketList(value: uid),
),
);
}
Related
Im struggling with this topic a few weeks. I registered on firebase console, pusher beams, everything setup as is written in documentation, I copied example project from flutter pusher_beams package so that when i send notification and app is opened, alert pop up and when is minimised, notification is shown in notification tray.
Problems:
When I tap on notification when app is minimised, i cannot check, which notification was tapped. I tried to add delay before that function but without help.
PusherBeams.instance.getInitialMessage is returning null, when i break there, but debugger dont stop on that breakpoint when i tap on notification when app is minimised.
I dont know how to handle notifications when app is killed. I found flutter_background_service, but when i set isForegroundMode to true, unhideable (if that word exists) notification is in notification tray and when i set isForegroundMode to false, when app is killed, that service is killed too. Another possibility is to use workmanager, but that can be called the fastest every 15 mins.
class _MyHomePageState extends State<MyHomePage> {
#override
initState() {
super.initState();
initPusherBeams();
}
initPusherBeams() async {
// Let's see our current interests
print(await PusherBeams.instance.getDeviceInterests());
// This is not intented to use in web
if (!kIsWeb) {
await PusherBeams.instance
.onInterestChanges((interests) => {
print('Interests: $interests')});
await PusherBeams.instance
.onMessageReceivedInTheForeground(_onMessageReceivedInTheForeground);
}
await _checkForInitialMessage();
}
Future<void> _checkForInitialMessage() async {
await Future.delayed(const Duration(seconds: 1));
final initialMessage = await PusherBeams.instance.getInitialMessage();
if (initialMessage != null) {
_showAlert('Initial Message Is:', initialMessage.toString());
}
}
void _onMessageReceivedInTheForeground(Map<Object?, Object?> data) {
_showAlert(data["title"].toString(), data["body"].toString());
}
void _showAlert(String title, String message) {
AlertDialog alert = AlertDialog(
title: Text(title), content: Text(message), actions: const []);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
I'm not using API or firebase yet, the data is stored locally.
here is my code
======>>
Widget _buildhouse(BuildContext contex, int index){
Size size = MediaQuery.of(context).size;
House house = houselist[index]; //houselist is the list of all houses
return GestureDetector(
onTap: (){
setState(() {]
house = filteredhouse[index]; //this code wont be executed
print(house.price);
});
Navigator.push(context, MaterialPageRoute(builder: (_) => DetailsScreen(house),));
},
so those two lines that I commented on are the important ones I guess, the print code gets executed but not the other one. also if I say "house = filteredhouse[index];" at the beginning, I will get the filtered value. but it won't get changed when clicked the button
solved it by using this function void _filtered(){ setState(() { houselist = filteredhouse; }); } and then calling it inside of setState
In this app when user click login page is navigate to homepage but when user press back button on home screen then page is navigate to login so this is not a right flow
I triend navigator.pushReplacement but when user press back button while on home screen app is close and go to background and when user open that app from background then instead showing home screen it show login screen so please give suggestions,
Here is my code
LoginScreen
Future<void> login(
String emailId, String password, String accessToken) async {
final dio = Dio(); // Provide a dio instance
String token = AppStrings.keyBearer + accessToken;
var customHeaders = {
AppStrings.authorization: token,
AppStrings.keyContentType: AppStrings.valueContentType
};
dio.options.headers.addAll(customHeaders);
final client = RestClient(dio);
await client
.loginUser(LoginUser(
deviceToken: AppStrings.valueDeviceToken,
lastLoginPlatform: AppStrings.valuePlatform))
.then((res) {
if(res.interests.isEmpty){
AppHelper.showToastMessage(
AppStrings.message_logged_in_successfully);
Navigator.of(context, rootNavigator: true).pop();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => InterestsPage(
userAccesstoken: accessToken,
)));
}
else{
AppHelper.showToastMessage(
AppStrings.message_logged_in_successfully);
Navigator.of(context, rootNavigator: true).pop();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomePage(
userAccesstoken: accessToken,
userInterests: res.interests
)));
}
}).catchError((Object obj) {
switch (obj.runtimeType) {
case DioError:
final res = (obj as DioError).response;
Navigator.of(context, rootNavigator: true).pop();
logger.e(res.statusMessage);
AppHelper.showToastMessage(AppStrings.message_something_went_wrong);
break;
}
});
}
I used
Navigator.of(context, rootNavigator: true).pop();
for close dialog box
I don't get any error but I want when user press back button on home screen app goes background and when user open that app from background show home screen not login screen
Show me where I made mistake in navigation and how to resolve it.
The method you are looking for is pushReplacement, and the way to go is:
Navigator.of(context).pop();
Navigator
.of(context)
.pushReplacement(
MaterialPageRoute(
builder: (BuildContext context) => InterestsPage(
userAccesstoken: accessToken,
)
)
)
This way, it will pop out of the alert message, and then replace all the previous pages with the one that you want.
However, the logic behing wether the login page needs to be displayed comes down to preference, and since I can't say how to do it without addicional code. I, for example, store the user on a local database after login. This way, even without a connection, there is a way to access the app.
You should use routes on your main file, using PushReplacement just works great there is no problem with it, you should decide where to navigate the user base on if the user logged in before or not, you can use something like share preferences to achieve this functionality. after login just save a pref that says user logged in and then on your splash screen navigate the user to correct screen
I'm making a LoginScreen, in LoginScreen i check data in database for know user logged or not for each times open app.
If user logged, the app will switched to HomeScreen.
I have a problem, i had logged in LoginScreen and then the app switched to HomeScreen. But my app's not standing in HomeScreen, it's continuing push new HomeScreen and looping this push action.
My code:
goToHomeIfAvailable() async {
// Go to HomeScreen if available
if (await this._databaseProvider.tokenTableIsEmpty() == false) {
print('Logged');
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HomeScreen()),
);
}
}
#override
Widget build(BuildContext context) {
// In first times user open app=> create DB and go to HomeScreen if available
_databaseProvider.openOrCreate().then((_) async {
await goToHomeIfAvailable();
});
/* Return a widget bellow */
}
DatabaseProvider.dart:
class DatabaseProvider {
String _path = 'O2_DB.db';
Database _database;
Map _tableName = {'token': 'token_tbl'};
Future openOrCreate() async {
this._database = await openDatabase(this._path, version: 1,
onCreate: (Database db, version) async {
await db.execute('CREATE TABLE IF NOT EXISTS ' +
this._tableName['token'] +
' (token_id integer primary key autoincrement, token text)');
});
}
}
Build is called many times during the app life cycle - & its better to always put our logic outside build method. Its normal Behavior.
In your case - As build was called each time the method - goToHomeIfAvailable() was called hence multiple push.
Moving goToHomeIfAvailable() out of build to initState() will solve the issue.
I used Navigator.push up to 6 screens to get to the payment page. After Payment, I want to push to the "Payment Successful" page then remove all the previous screens i.e using the back button will return to the very first screen.
NOTE: I have tried pushReplacementNamed and it doesn't work.
I figured it out. It was the Navigator.pushAndRemoveUntil function. Where i had to pass the PaymentSuccessful widget as the newRoute, and the "/Home" route as the predicate
_navPaymentSuccessful(){
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => PaymentSuccessful()
),
ModalRoute.withName("/Home")
);
}
Accepted Answer is correct. But you can try this too.
Navigator.pushAndRemoveUntil<dynamic>(
context,
MaterialPageRoute<dynamic>(
builder: (BuildContext context) => YourPageNameGoesHere(),
),
(route) => false,//if you want to disable back feature set to false
);
even simpler and I think a better way would be to do it this way,
this Schedules a callback for the end of the current persistent frame,to push to route /loginPage and removes all the previous routes,this way you can make sure that all the frames are rendered and then you navigate to next page.
SchedulerBinding.instance.addPostFrameCallback((_) {
Navigator.of(context).pushNamedAndRemoveUntil(
'/loginPage', (Route<dynamic> route) => false);
});
I would Suggest use WillPopScope in your Payment successful page and onWillPop method write following snippet of code:
return WillPopScope(
onWillPop: (){
Navigator.of(context)
.pushNamedAndRemoveUntil('/Home', (Route<dynamic> route) => false);
},
child: Scaffold()
};
Try this if you want pass arguments to new page:
Navigator.of(context).pushNamedAndRemoveUntil(
'/new-route-name',
arguments: {
any object
},
ModalRoute.withName("/the-route-name-that-you-want-back-to-it")
);