I'm new in flutter and I just want to know if this scenario/feature is possible in flutter/flutter web. I want to update the url/route base on the state of the screen. For example, in 9gag.com, there are buttons for Hot, Trending, and Fresh. Then, if I clicked the Hot button its url will be updated to 9gag.com/hot and also its contents, the same goes for Trending and Fresh buttons. Is this possible in flutter/flutter web? If so, how do I implement this feature?(much better if the implementation uses bloc)
Totally possible and is very easy to achieve just use url_launcher Package on onpressed/ontap
Example: Add this code somewhere like in the beginning of your stateful management or at the end of your code
_launchURL() async {
const url = 'https://flutter.io';
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
Call it somewhere like this
RaisedButton(
onPressed: _launchURL,
child: new Text('Show Flutter homepage'),
),
),
Now if you have some 9gag/hot button or container whatever you are going with just put that url and when user taps it, it will open that url. If you want to open it inside the app webview that's also possible but slightly different.
If I understood correctly It's pretty straightforward use the default way of navigation and routing.
I'm not sure with your approach like you have mentioned
I want to update the url/route base on the state of the screen
and
Then, if I clicked the Hot button its url will be updated to 9gag.com/hot and also its contents
If I'm not wrong there is a inbuilt feature of navigating to other screens and once you land on the desired screen, you can see the refreshed content. If you want to try material design the code will be like this
//within your stateful or stateless widget
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => YourPage()),
Instead of using a package you can try this inbuilt way of doing the same job. But it's upto you which one you want to use. Checkout the official flutter documentation https://flutter.dev/docs/cookbook/navigation
I hope this approach also helps to answer your question. If so happy to help in your flutter journey, if not share that how did you solved it.
Related
Hello hope you guys are ok.
the problem I'm facing is we have a main_page which leads to a page doing some changes on data which are show on the main page.
after some process if the user touches back button and goes to main_page app loads it from stack and the data are not shown because it does not get rebuilt.
I don't want to control back button because there are other pages which lead to data changing page and I also tried using valuelistenablebuilder but I don't know why it goes wild and gets into a screen refresh loop without even changing the valueListenable I used redux to manage the value.
actual reason I want main page to rebuild is to call a method. why do I not call that method in second page is complicated and because i don't want to.
in conclusion I want main page to rebuild whenever it shows up even when it's read from the stack or even is there a way to tamper with stack of the pages without visual changes to the user.
you need to use Shared preferences plugin
https://pub.dev/packages/shared_preferences
If I understood the question correctly
The flow should be:
Screen A
#override
void initState() {
loadSomeDataFromDB();
super.initState();
}
Screen B
#override
void initState() { *//INIT AS EXAMPLE*
changeSomeDataFromDB();
super.initState();
}
You can try this in Screen A
onPressed: () async {
bool? shouldLoadDataAgain = await
Navigator.of(context).push(PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) =>
const ScreenB(),
));
if(shouldLoadDataAgain!=null&&shouldLoadDataAgain ==true){
loadSomeDataFromDB();
}
},
and this in Screen B when user press back button
onPressed: () async {
Navigator.of(context).pop(true)
},
solution for my problem was that used redux store had an object and updating object property or a list does not count as variable change to redux so the widget wouldn't rebuild.
According to this blog, if using Navigator 2.0 and/or (in my case) GoRouter you can no longer override the phone's back button using the "WillPopScope" and onWillPop function call. Navigator 2.0 now uses PopRoute to go back.
This causes an issue when using webview on a flutter page. If the user navigates to another web page within that webview and then clicks the back button on their phone they naturally expect the webview navigate back to the previous web page. But instead it takes the user off that page and back to their previous flutter page.
Is there any way around this? Can I have my back button first check whether there is a controller.canGoBack() like I used to be able to do with the old Navigator system?
I have found a solution. Convoluted, but functional:
I had to create a custom "backButtonDispatcher" and add it to the main.dart MaterialApp.router function
child: Builder(builder: (BuildContext context) {
final router = Provider.of<MainRouter>(context, listen: false).router;
backbuttondispatcher = backButtonDispatcher(router.routerDelegate, settings);
return MaterialApp.router(
routeInformationParser: router.routeInformationParser,
routeInformationProvider: router.routeInformationProvider,
routerDelegate: router.routerDelegate,
backButtonDispatcher: backbuttondispatcher,
.
.
.
I created the new dispatcher in the router folder and called it "backbuttondispatcher.dart.
import 'package:flutter/material.dart';
class backButtonDispatcher extends RootBackButtonDispatcher {
final RouterDelegate _routerDelegate;
final _settings;
backButtonDispatcher(this._routerDelegate,this._settings)
: super();
Future<bool> didPopRoute() async {
//Can user leave the page?
if (!_settings.canLeavePage) {
//no, as the webview widget has flagged canLeavePage as false
_settings.goBackToPreviousWebsite();
return true;
}else{
//yes, perform standard popRoute call
return _routerDelegate.popRoute();
}
}
}
Using a shared class reference (I used "_settings") I store a flag that says whether or not the user has traversed through more than one web page - if TRUE, the back button dispatcher won't go back to a previous route/page and instead call another function (pointer) that handles going back to a previous web page in the webview widget route. But if FALSE, the dispatcher performs it's standard didPopRoute function.
Additionally, on all other routes/pages with a webview, the pointer function and boolean need to reset to null and false. This is not ideal but fortunately there aren't that many pages in the app.
It annoys me that they changed the back button functionality for main route/page navigation but didn't take in to consideration the fact that the back button can also be used for going back to a previous webpage. I understand that we shouldn't really be showing web pages with apps anyway but we lowly developers don't always have the power to deny app requirements from higher up.
I'm using flutter navigator 2.0 in my app and I'm trying to return some data from another screen when it pops. Here's the code for the same:
This is what I'm using to push/add a new page. After the user has made changes to the edit profile page, I'm trying to update the data on the existing page (profile page).
appState.currentAction = PageAction(
state: PageState.addPage,
widget: EditProfile(currentUserId: currentUserId),
page: Edit_Profile_PageConfig,
);
After the changes are made on the edit profile page, this is what I'm doing to pop:
appState.currentAction = PageAction(state: PageState.pop);
But I'm not sure how can I pass the data from the edit profile page back to the profile page. In the old navigator style, it was pretty easy to have a then function, like this:
var callBack = await Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => EditProfile( )));
But I'm not sure how to achieve this using Navigator 2.0. I referred to these two references for developing the navigation in the app.
Flutter Navigator 2.0
Google Docs
when calling navigator.pop add your data as a second argument.
Navigator.pop(context, data);
I have a typical CRUD operation task: (List Sites, Add Site, ...)
I created a SitesProvider. In the same provider, I added 2 methods for add and edit. I was thinking to use the same provider in the 2 screens (ListSites and AddEditSite)
In the ListSites screen, it works fine. Here is the problem:
I open the AddSite screen by clicking the AddButton in the ListSites screen
Hit submit (did not enter data, simulating error case)
The error gets displayed in the ListSites screen, not in the AddSite screen.
It makes sense. They both use the same provider, both screens are on the stack. It seems that the first one only consumes the state update and displays the error.
I use MultipleProviders approach that wraps the MaterialApp with all providers in the app.
Can we fix that without creating separate providers for each of the 2 screens?
EDIT:
I used provider.removeListener in the ListSites screen right before I open the AddEdit and it shows the error in the correct screen now. I still have to do some other tweaks to get it back to listen after I add. Not efficient I think but it is a step.
I ended up doing that:
Added Another Field in the provider (stateType: list/addedit)
Change the type per the screen I'm currently in
provider.stateType = UIStateType.add_edit;
await Navigator.push(context,
MaterialPageRoute(builder: (context) => AddEditSiteScreen()));
provider.stateType = UIStateType.list;
in build(), I check for the type
sitesProvider = Provider.of(context);
if (sitesProvider.stateType != UIStateType.add_edit) return Container();
I need to make an app in which the user needs to press an InkWell or a button and then it should take them to a website, so does anyone know how to do this?
There is a really nice plugin for this, called url_launcher. Usage is as follows:
InkWell(
onTap: () => launch(websiteUrl),
...
)
You can also use canLaunch to test if launching will work. More on that in README.md.