I have a flutter app that connects via bluetooth with a device by pressing on the device name from the list of paired devices. This is the coding :
final BluetoothDevice server;
DataCollectionPage({required this.server});
...............................................................................
child: ListView(
children: devices
.map((_device)=> BluetoothDeviceListEntry(
device: _device,
enabled: true,
onTap: (){
if (kDebugMode) {
print("item");
}
_startDataCollection(context, _device);
},
................................................................................
void _startDataCollection(BuildContext context, BluetoothDevice server){
Navigator.of(context).push(MaterialPageRoute(builder: (context){
return DataCollectionPage(server: server);
}));
}
Then once I navigate to the "DataCollectionPage" page, I perform some actions and data collection methods and at the end I will be in other page named "DataCollectionTimer". In this page a timer will be displayed on the screen for few seconds then at the end of this timer a Dialog will show to give some message and then finally Once I press the button close on this dialog, I want to go back to DataCollectionPage. So If I try to use
MaterialPageRoute( builder: (context) => DataCollectionPage(), ),
It will give an error because parameter 'server' is required which I obtained from the list of paired devices that was in a different class.
Is there a way to go back to DataCollectionPage from the current one without going all the way back to the page where the list of paired devices is there.
Thank you in advance
You need to make the server field optional and then use popUntil
final BluetoothDevice? server;
DataCollectionPage({this.server});
Related
I am fairly new to state management in Flutter, and I have an application where the user will be interacting with dialogs, and a dialog may have a button to open another dialog which can result in the following:
https://i.stack.imgur.com/VBSzr.png
As shown, multiple issues arise when more than one is opened at once -- most notably the previous dialog is still visible in the background. So when a user opens a new dialog, is there any method where I can hide the dialog behind it, and when the frontmost dialog closes, show the previous one which is hidden? Thanks in advance.
Use Navigator.pop(context); method to close the dialog on your button's onPressed before opening the second dialog.
And then while closing your second dialog you can reopen your previous dialog.
Example:
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text("Hello World"),
content: Text("This is content"),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context); //Close your current dialog
//TODO:open your second dialog
},
child: Text("Open"))
],
);
});
I would first try to re-think the logic for opening multiple dialogs at the same time.
Maybe there is a quick workaround for that, but if you keep adding more and more dialogs, then it would become a mess.
Since showDialog<T> function returns Future<T?>, you could potentially use await and wait until the first dialog is closed and then open the second one and so on:
bool canContinue = await showDialog<bool>(
context: context,
builder: (context) => YourWidget(),
);
Alternatively, you could pop by using Navigator but as said, this will be visible to the user that something weird is going on (pushing and popping dialogs programatically).
I'm making an app with Dart/ flutter now and having an issue with routing pages.
The app is basically the matching app, and I want to add the functionality that a user can edit their profile. Currently, we have 4 stateful widgets: Match(), Message(), MyProfile() and EditProfile(). In the bottom navigation bar, I put three widgets, Match(), Message(), and MyProfile(); when the user wants to change the profile information, the person goes to MyProfile() and click "edit profile" button, which takes the user to EditProfile. After the user changes the information, I want to rout the page to MyProfile() for allow the user to check the profile info.
The code below is some part of the Navigation bar.
class _NavigationHomeState extends State<NavigationHome> {
int _currentIndex = 0;
final List<Widget> _children = [
Match(),
Messages(),
MyProfile(),
];
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
});
}
and I put the code below in one of the button of the EditProfile().
Navigator.of(context).pushNamed('/myProfile');
Then gave me an error saying
Error: Could not find the correct Provider above this
MyProfile Widget
This likely happens because you used a BuildContext that does not
include the provider of your choice. There are a few common scenarios:
The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route,
then other routes will not be able to access that provider.
You used a BuildContext that is an ancestor of the provider you are trying to read.
Make sure that MyProfile is under your
MultiProvider/Provider. This usually happen when you are
creating a provider and trying to read it immediatly.
I guess I'm getting this error because we set the _currentIndex in the bottom navigation bar as 0, which is Match(), so Navigator.of(context).pushNamed('/myProfile'); trying to take the user to the Match() page (?)
How can we take the user to the MyProfile page after the person save and click the button on EditProfile()?
Try using MaterialPageRoute instead of named routes.
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);
}
If you going to EditProfile from MyProfile widget then I suggest to just pop the screen. As this will not reload complete screen, you can always pass data while doing pop.
RaisedButton(
onPressed: () {
// The Yep button returns "Yep!" as the result.
Navigator.pop(context, 'Yep!');
},
child: Text('Yep!'),
);
Another option is to use pushNamedAndRemoveUntil method.
navigator.pushNamedAndRemoveUntil('/MyProfile', ModalRoute.withName('/MyProfile'));
I guess I'm getting this error because we set the _currentIndex in the
bottom navigation bar as 0, which is Match(), so
Navigator.of(context).pushNamed('/myProfile'); trying to take the user
to the Match() page (?)
Not sure about your error but you can pass data as argument while doing pushNamed.
RaisedButton(
child: Text("Navigate to MyProfile"),
onPressed: () {
Navigator.pushNamed(
context,
'/myProfile',
arguments: [
'Extract Arguments Screen',
'This message is extracted in the build method.',
],
);
},
),
I'm trying to avoid the default behaviour of Flutter, instead of closing app when the back button (of the smartophone of course) is pressed I will send the app in background, so when I try to reopen the app it returns on the last screen.
I also tried a solution that I have found here, but didn't work.
This is the code:
return WillPopScope(
onWillPop: () async =>
await SystemChannels.platform.invokeMethod('SystemNavigator.pop'),
child: Scaffold(
It also closes the app and don't send it in background.
The screen that contains the code showed above is the last route.
You can use MethodChannel for this, invoke a method from Flutter that will trigger a method in Java.
// in flutter use something like this
methodChannel.invokeMethod("homeButton");
And in Java, you can create a method like:
public void homeButton() {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
More info on how to write platform specific code.
Flutter plugin for sending mobile applications to the background. Supports iOS and Android.
move_to_background: ^1.0.2
WillPopScope(
child: MaterialApp(...),
onWillPop: () async {
MoveToBackground.moveTaskToBack();
return false;
},
);
i have app with two screens,one fingerprint screen and another home screen.once
fingerprint is authenticated i will get routed to home screen(using navigator.push()),but if I click back button in phone now it is getting routed to fingerprint screen again.Now how to close the app instead of routing back to finger print screen?
Use Navigator.pushReplacement. It will replace the current topmost widget on the stack with the new one instead of simply pushing it on top.
Example usage -
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (BuildContext context) => MyHomePage()));
More documentation about this method can be found here.
put your homepage scaffold inside WillPopScope as a child
WillPopScope(
child: Scaffold(...),
onWillPop: () async {
return false;
},
),
Is there any method similar to this.finish() in android to finish current flutter activity.
Do you mean close current screen and come back to previous screen?
If that, Navigator.pop(context) should do the work. However, if you are at the entry screen (the first screen of the app and this screen has no parent screen/previous screen), Navigator.pop(context) will return you to a black screen. In this case, we have to use SystemNavigator.pop().
But don't use SystemNavigator.pop() for iOS, Apple says that the application should not exit itself :)
Below code will work on Android for both cases
if (Navigator.canPop(context)) {
Navigator.pop(context);
} else {
SystemNavigator.pop();
}
use Navigator.pushReplacement(BuildContext context, Route<T> newRoute) to open a new route which replace the current route of the navigator
use thie code
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) {
return AddDemoUnitActivity();
}));