My project is a todo app and I have these parts:
Meetings
Checks
Alarms
and all of these parts have a details screen, add screen, list screen, edit screen and search screen.
I'm tired of creating a separate screen for each section, so I need a way to implement all these screens using inheritance and less code.
Any idea will be great.
Set Navigator route to screen with an argument for the part type you want to render (e.g. Meetings).
Receive that arg in the new screen, then render specific widgets based on that.
For example, set the Navigator to pass the part:
Navigator.of(context).pushNamed(
DetailsScreen.routeName,
arguments: 'details',
);
Then in the new screen, use the argument to render the rest of the page:
final sourcePage = ModalRoute.of(context)!.settings.arguments as String;
// passed from last page
You can use this var to render different elements in the page:
return Scaffold(
appBar: AppBar(
title: Text('$sourcePage'),
backgroundColor: sourcePage.toLowerCase() == 'details'
? Colors.green
: Colors.black26,
),
);
Related
I need help.
I am creating a multi page form which is divided into 2 screens.
First Screen
Second Screen
Both screen share same bloc which is FormBloc, and same state which is FormState. When we click submit button in first screen, it update the state variables using state.copyWith() method and then it take us to 2nd screen. I am using Navigator.pushNamed(context, '/screen2'); to move to second screen.
Bloc is provided to second screen from the AppRoute class:
static final _formBloc = FormBloc();
Following code is called during Navigation:
// Route to second screen
static BlocProvider<FormBloc> secondScreenRoute() {
return BlocProvider.value(value: _formBloc, child: const SecondScreen());
}
But In the second screen all the fields which was updated using state.copyWith() method gets restored to their initial state.
For Example:
In first Screen there is input formtextfield for user name. When user enters his name, I update state using state.copywithMethod()
Suppose user enter name "John" then
emit(state.copyWith(
name: John,
status: Formz.validate([state.name, name]),
));
And When I am accessing this in second screen using state.name then I am getting empty string "".
I fail to understand why this is happening. I am not creating new bloc instance and I am passing already created bloc instance to second screen but then also all the properties which was updated using state.copyWith() method gets restored to their initial value on second screen.
Could you please help?
You can try better instead of using BlocProvider.value, create the Bloc globally in your MaterialApp as follows :
return
BlocProvider<FormBloc>( // like this
create: (context) => FormBloc(),
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
initialRoute: PageNames.login,
onGenerateRoute: RouteGenerator.generateRoute,
),
),
);
This will allow to have it already created when you start your application, and thus all the Blocs that you occupy later will have the value in the state.
Now just try to do a normal navigation, remove the other BlocProvider you have created as well as the .value.
i am new to flutter and i would like to have a shared appBar and bottomNavigationBar
the way i am currently using is implementing them in spearte files and importing them in each screen but i need to make one screen contains the appbar and the bottomNavigationBar and the content of the body renders diffrent views according to the routes and i can't make it at main page because the main page renders welcome screen
in reactJS i was importing the header and footer and make my routes between them how can i make somthing similar in flutter
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: navBar(),
body: SingleChildScrollView(reverse: true, child: ScanPassport()),
bottomNavigationBar: bottomNavigation(),
currentIndex: _selectedIndex,
onTap: _onItemTapped,
showSelectedLabels: false,
showUnselectedLabels: false,
type: BottomNavigationBarType.fixed,
),
);
}
}
A couple of options:
Use MaterialApp() router. There's a tutorial here showing how to refactor your Scaffold() so you don't have duplicate code for appBar, bottomNavigationBar, etc. This is the official Flutter method for view routing.
If you need to swap out your Scaffold() body but can't change your other Scaffold() elements, you can create a widget for the body that takes a "page" value and change what it returns from build() based on the "page" value passed. The widget holding your Scaffold can be stateful and your bottom navigation bar can setState() the page number.
In your context, You can just have a single scaffold homepage screen after logged in success or after welcome screen (depends up app). Once you navigate to homepage, You will have appBar and bottom navigation bar at top and bottom respectively. The remaining portion at center will be your body content of the selected tab. Once you switched the tap on bottom navigation, you should change the content rather than using routes for switching the body content. The current page status will be preserved on homepage.
I am developing an app in flutter with few screen I want to add AppBar in home screen and want that appbar to be fixed in all screen, but in the dummy code which i have written the complete screen is getting replaced by that.
Below is the screen
HomeScreen - here i have created appbar
When I click on AddPolicy Button, i get that screen where right now i just have a text but the complete screen gets replaced as below, but I want the header appBar should be fixed. How can I achieve this.
Below is the code
homepage - https://github.com/lodha13/samkit/blob/main/lib/screens/home.dart
AddPolicy page - https://github.com/lodha13/samkit/blob/main/lib/screens/add_policy.dart
You have two opptions:
have a global widget for appbar and use it on each different page,
or
You can have one Scaffold in your main.dart and instead of generating a new one for each page, only change the body parameter using setState. for example:
// have as many widget as you want for each page
const body1 = Text("body1"); //just a simple example, you can change it to whatever you want.
const body2 = Text("body2");
return Scaffold(
appBar: AppBar(
title: const Text('Sample Code'),
),
body: handleBody(selectedIndex)
);
then you can have a function to handle bodies:
handleBody(int index){ // you can pass different input for body selection I have used an int for simplicity
if(index == 1){return body1;}
if(index ==2) {return body2;}
// and so on
}
now with changing the selectedIndex you can show different bodies. Personally, I prefer to have a list of widgets and select one of them based on selectedIndex.
What I'm trying to do is build a flutter web app that, when displayed in the browser, the tab shows an icon and a title (as currently it only shows the world icon and the localhost... title).
Actual Result :
Desired Result :
Edit:
I can now add the title, as this is set in the main function
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Icon(Icons.menu, color: Colors.white,),
title: Text(_your title here_),
)
...
);
}
So, the only thing I need to edit is the favicon
In order to change the title to what you desire, you need to add the parameter title (Which is a String) to your MaterialApp widget.
return MaterialApp(
title: "MyTitle",
home: MyHomeWidget());
Assuming you already have a favicon.ico file, placing it inside the your_project_dir\web folder alongside index.html as shown below is enough for the browser to pick it up.
Following is the result of placing a favicon.ico' in theweb` folder. Make sure to do a clean build.
In other case you can manually mention it using the link tag inside your index.html as explained here in this Wikipedia page.
Edit title
it is the simplest. just use the Title widget on each page or directly inside the materialApp constructor and set title string key to the title text you need.
like this:
...
Title(
color: myColors, //not important in web but still required
title: 'web page title',
child: myChildWidget,
),
...
Edit icon
If your app is only for the web, use the dart:html library to perform change using DOM access.
something like this
import 'dart:html';
...
...
updateIcon(String assetIcon){
LinkElement link = (document.querySelector("link[rel*='icon']") ??
document.createElement('link')) as LinkElement;
link.type = 'image/x-icon';
link.rel = 'shortcut icon';
link.href = assetIcon;
}
if your application is multi-platform, you need to create separate main file for the web like main_web.dart. and declare the previous function inside this file.
Now, anywhere you need to set up the icon you just need to call the method after checking the platform using the keyword kIsWeb.
Ex: change icon inside page
...
initState(){
super.initSate();
if(kIsWeb){
WebMixin.updateIcon("assets/home_icon.png"); //WebMixin is just a helper. replace it by your one.
}
}
...
You could set the onGenerateTitle property of your MaterialApp widget, and provide a callback function to build your title. The onGenerateTitle callback is called each time the WidgetsApp rebuilds. This is useful if you want the title of your page to change dynamically or if you want to produce a localized title.
MaterialApp(
...
onGenerateTitle: (BuildContext context) {
return AppLocalizations.of(context).myTitle;
}
...
);
If you're wondering how to change the app name on your device's homepage, you can update the "name" and "short_name" values in web/manifest.json:
"name": "Ideasky",
"short_name": "Ideasky",
Since i want this to be my layout i was trying to implement it with a showModalBottomSheet but the problem is that this widget only works on the button click as it is showing me error when i am trying to call the method as it is in the initState method. So then I started to work with bottomSheet value present in the scaffold but then the background is being displayed only upto the starting of the bottom sheet creating the distance between the model sheet and the background whereas I want it to overlap like in the image..How should I prepare this layout.
There is no such parameter as "bottomSheet" in Scaffold, there is one called bottomAppBar, which is used for making Bottom Bars like the one on the Youtube Android App. So this should help you make the basic structure.
Use a Stack widget to put widgets on top of each other, in first layer, add the image using the NetworkImage widget, then in the second layer, make a Column, like this:
#override
Widget build() => Scaffold(
body: _body(),
);
_body() => Stack(
children: <Widget>[
NetworkImage(your_url_here),
Column(
children: <Widget>[
_basicDetails(),
_guidePanel(),
]
),
]);
Then create 2 new methods after the _body method like this:
_body() => Stack(...);
_basicDetailsPage() => Container();
_guidePanel() => Container();
Create your layout in these 2 methods. Comment if you need more help :)
For additional help, please join the Facebook Group "Let's Flutter With Dart"