I am creating an app which has bottomnavigation bar.In that bottomnavigation bar it has 5 items names namely profile,aboutus,home,notifications and cart. Each item names has its own page. Now question is i add a button in homepage and if i click on the button it goes to the new page but it doesn't show the bottomnavigation bar.How do i show the bottomnavigation bar in the new page and also the selected current index. Below is the dart code
Mainpage.dart
class MainPage extends StatefulWidget {
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
int _currentIndex = 0;
final tabs = [
Profile(),
AboutUs(),
Home(),
Notifications(),
CartPage(),
];
#override
void initState() {
super.initState();
_currentIndex = 2;
}
#override
Widget build(BuildContext context) {
return Consumer<Cart>(
builder: (context, cart, child) {
return PlatformScaffold(
body: tabs[_currentIndex],
bottomNavBar: PlatformNavBar(
android: (_) => MaterialNavBarData(
type: BottomNavigationBarType.fixed,
),
ios: (_) => CupertinoTabBarData(),
currentIndex: _currentIndex,
itemChanged: (index) => setState(
() {
_currentIndex = index;
},
),
items: [
BottomNavigationBarItem(
icon: PlatformWidget(
ios: (_) => Icon(CupertinoIcons.person),
android: (_) => Icon(Icons.person),
),
title: Text('Profile'),
),
BottomNavigationBarItem(
icon: PlatformWidget(
ios: (_) => Icon(CupertinoIcons.info),
android: (_) => Icon(Icons.info),
),
title: Text('About Us'),
),
BottomNavigationBarItem(
icon: PlatformWidget(
ios: (_) => Icon(CupertinoIcons.home),
android: (_) => Icon(Icons.home),
),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: PlatformWidget(
ios: (_) => new Image.asset(
"assets/notification.png",
height: 21.0,
color: Colors.grey[600],
),
android: (_) => Icon(Icons.notifications),
),
title: Text(
'Notifications',
style: TextStyle(fontSize: 12.0),
),
),
BottomNavigationBarItem(
icon: PlatformWidget(
ios: (_) => Icon(CupertinoIcons.shopping_cart),
android: (_) => Stack(
children: <Widget>[
Icon(Icons.shopping_cart),
cart.count == 0 ? new Container(height: 0, width: 0,)
: new Positioned(
right: 0,
child: new Container(
padding: EdgeInsets.all(1),
decoration: new BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(6),
),
constraints: BoxConstraints(
minWidth: 12,
minHeight: 12,
),
child: new Text(
'${cart.count}',
style: new TextStyle(
color: Colors.white,
fontSize: 8,
),
textAlign: TextAlign.center,
),
),
)
],
),
),
title: Text('Cart'),
),
],
),
);
},
);
}
}
Homepage.dart
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
onPressed: (){
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => NewPage()));
},
child: Text('New Page'),
),
),
);
}
}
Newpage.dart
class NewPage extends StatefulWidget {
#override
_NewPageState createState() => _NewPageState();
}
class _NewPageState extends State<NewPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
),
);
}
}
I use this method to add a widget which is common to all pages:
MaterialApp(
title: 'Flutter Demo',
initialRoute:"/home",
routes: [
...
],
builder: (context, child) {
return Stack(
children: [
child!,
Overlay(
initialEntries: [
OverlayEntry(
builder: (context) {
return YourCustomWidget(); *//This widget now appears on all pages*
},
),
],
),
],
);
},
);
You can have a Scaffold as a parent of all these pages, and have a BottomNavigationBar on the Scaffold, and a PageView as the body of the Scaffold:
Scaffold(
body: PageView(
controller: MyController(),
children: [
MyPage1(),
MyPage2(),
//...
],
onPageChanged: myOnPageChanged,
),
bottomNavigationBar: MyNavBar(),
)
Related
i wanted to use the AnimatedSplashScreen but in my case it didnt work.
This is the AnimatedSplashScreen displayed in my app:
Here my SplashScreen-Class:
class SplashScreen extends StatelessWidget {
const SplashScreen({super.key});
#override
Widget build(BuildContext context) {
final user = AuthService().currentUser;
String nextScreen =
user != null ? RoutesEnum.homePage : RoutesEnum.loginPage;
return AnimatedSplashScreen(
duration: 1500,
splash: Icons.home,
nextScreen: LoginPage(),
nextRoute: nextScreen,
splashTransition: SplashTransition.rotationTransition,
);}}
And my main.dart where the MaterialApp is created:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
theme: mainTheme,
home: const SplashScreen(),
routes: {
//RoutesEnum.splashScreen: (context) => const SplashScreen(),
RoutesEnum.loginPage: (context) => LoginPage(),
RoutesEnum.signUpPage: (context) => SignUpPage(),
RoutesEnum.homePage: (context) => HomePage(),
},
));
}
What am I doing wrong?
Thanks for ypur help.
Edit:
This is my LoginPage:
class LoginPage extends StatefulWidget {
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final authService = AuthService();
final emailcon = TextEditingController();
final passwordcon = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Stack(
children: [
Padding(
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
"assets/images/Logo_ohne_Hintergrund.png",
color: Colors.white.withOpacity(0.75),
colorBlendMode: BlendMode.modulate,
),
addVerticalSpace(60),
addFormEmailPassword(emailcon, passwordcon),
addVerticalSpace(20),
RoundButton(
title: "Login",
tapfun: () => {
if (emailcon.text.toString().isEmpty ||
passwordcon.text.toString().isEmpty)
{
toastmessage("Eingaben prüfen"),
}
else
{
authService
.signInWithEmailAndPassword(
email: emailcon.text.toString(),
password: passwordcon.text.toString(),
)
.then(
(value) => {
if (value)
{
Navigator.pushReplacementNamed(
context,
RoutesEnum.homePage,
),
}
},
),
}
},
),
addVerticalSpace(20),
const Text("- OR -"),
addVerticalSpace(20),
GoogleAuthButton(
style: AuthButtonStyle(
buttonType: AuthButtonType.icon,
buttonColor: Theme.of(context).backgroundColor,
borderRadius: 25,
),
onPressed: () => {
authService.signInWithGoogle().then(
(value) => {
Navigator.pushReplacementNamed(
context,
RoutesEnum.homePage,
),
},
),
},
),
addVerticalSpace(20),
RoundButton(
title: "Toast",
tapfun: () {
toastmessage(
authService.currentUser == null
? "NULL"
: authService.currentUser!.email.toString(),
);
},
),
],
),
),
Padding(
padding: const EdgeInsets.all(30),
child: Align(
alignment: Alignment.bottomCenter,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
"Don't have an account?",
style: TextStyle(
color: Colors.white,
),
),
TextButton(
onPressed: () {
Navigator.pushNamed(
context,
RoutesEnum.signUpPage,
);
},
child: const Text("Sign Up"),
),
],
),
),
)
],
),
);
}
}
Use below-mentioned package:
https://pub.dev/packages/flutter_native_splash
This package automatically generates iOS, Android, and Web-native code for customising this native splash screen background colour and splash image. Supports dark mode, full screen, and platform-specific options.
I found the mistake.
In the MaterialApp the theme-Property makes the trouble. When i remove that it works. Why is that so?
I'm pretty new to flutter and I'm trying to make a login system using providers. It seems to be working when I test the login. But when I rebuild the app the provider returns a null value. Any help would be appreciated.
The screen to check for employee data. If it exist it should redirect to the home page. And if it doesn't, it should redirect to the login authenticate page
Landing Page
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Landing extends StatefulWidget {
#override
_LandingState createState() => _LandingState();
}
class _LandingState extends State<Landing> {
//AuthService auth = new AuthService();
#override
Widget build(BuildContext context) {
Future<Employee> getuserdata() => Employee_preferences().getEmployee();
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (_) => AuthService(),
),
ChangeNotifierProvider(
create: (_) => Employee_Provider(),
)
],
child: MaterialApp(
title: 'ClockServe',
theme: ThemeData(primarySwatch: Colors.blue),
home: FutureBuilder(
future: getuserdata(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return CircularProgressIndicator();
default:
if (snapshot.hasError) {
return Text('Error:${snapshot.error}');
} else if (snapshot.data.empId == null) {
return AuthenticatePage();
} else {
return HomePage(emp: snapshot.data);
}
}
}),
routes: {
'/navigatorPage': (context) => NavigatorPage(),
'/homePage': (context) => HomePage(),
'/authenticate': (context) => AuthenticatePage(),
'/attendancePage': (context) => AttendanceScanner()
},
),
);
}
}
The homepage. The page will hold employee information. Landing page is correctly redirecting to this page but for some reason the provider is returning null
HomePage
class HomePage extends StatefulWidget {
final Employee emp;
const HomePage({Key key, this.emp}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
//to do: add back end
//use futurebuilder to return user object
//using futureprovider to get snapshot data of user object from database
#override
Widget build(BuildContext context) {
Employee emp = Provider.of<Employee_Provider>(context).emp;
print(emp.empEmail);
return Scaffold(
appBar: AppBar(
actions: <Widget>[
ElevatedButton.icon(
onPressed: () async {
Employee_preferences().removeEmployee();
Navigator.pushReplacementNamed(context, '/authenticate');
},
label: Text(
'Log Out',
style: TextStyle(color: Colors.white),
),
icon: Icon(
Icons.logout,
color: Colors.white,
),
)
],
title: Text('ClockServe'),
centerTitle: true,
),
//button to pop qr scanner camera
//after scanning a qr code it should parse the json array
//into a method, the method will take that as parameter.
//method should send http request check in the auth dart
floatingActionButton: FloatingActionButton.extended(
label: Text('Check In'),
icon: Icon(Icons.camera_alt),
onPressed: () => navigateToScanPage(context),
),
// floatingActionButton: FloatingActionButton(
// onPressed: () {},
// child: Icon(Icons.alarm_on),
// ),
body: SingleChildScrollView(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(emp.empFirstName ?? 'emp first name'),
],
),
),
),
);
}
}
Future navigateToScanPage(context) async {
Navigator.push(
context, MaterialPageRoute(builder: (context) => AttendanceScanner()));
}
Code for login page just in case if it's relevant.
Login Page
class LoginPage extends StatefulWidget {
final Function toggleView;
LoginPage({this.toggleView});
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final _formKey = GlobalKey<FormState>();
String email = '';
String password = '';
String error = '';
bool loading = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
ElevatedButton.icon(
onPressed: () {
widget.toggleView();
},
label: Text('Register'),
icon: Icon(Icons.person_add),
)
],
title: Text('Login'),
),
body: Container(
padding: EdgeInsets.all(30),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
WelcomeHeader(),
SizedBox(
height: 10,
),
TextFormField(
validator: (value) => value.isEmpty ? 'Enter email' : null,
onChanged: (val) {
setState(() => email = val);
},
decoration: decorationBox.copyWith(hintText: 'Email'),
),
SizedBox(
height: 20,
),
TextFormField(
validator: (value) => value.isEmpty ? 'Enter password' : null,
onChanged: (val) {
setState(() => password = val);
},
obscureText: true,
decoration: decorationBox.copyWith(hintText: 'Password'),
),
SizedBox(
height: 20,
),
ElevatedButton(
onPressed: () async {
final form = _formKey.currentState;
if (form.validate()) {
form.save();
AuthService auth = new AuthService();
final Future<Map<String, dynamic>> successMsg =
auth.empLogin(email, password);
successMsg.then((response) {
if (response['status']) {
Employee emp = response['employee'];
print(emp);
Provider.of<Employee_Provider>(context, listen: false)
.setEmp(emp);
Navigator.pushReplacementNamed(context, '/homePage');
}
});
}
},
child: Text('Log In'),
),
SizedBox(
height: 20.0,
),
Text(
error,
style: TextStyle(color: Colors.red, fontSize: 20.0),
)
],
),
),
),
),
);
}
}
class WelcomeHeader extends StatelessWidget {
const WelcomeHeader({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
Text(
'Welcome To ClockServe',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 28.0,
),
),
Divider(
height: 20,
thickness: 2,
),
Text(
'Enter your credentials to login',
style: TextStyle(fontStyle: FontStyle.italic),
),
],
),
);
}
}
I am trying to create a shopping cart using provider and display the number of items currently in the cart on my homepage. When I create my cart icon with a text widget overlaid, the value being shown does not reflect the number of items in the cart.
Here is my code:
class OurShoppingBasketIcon extends StatelessWidget {
const OurShoppingBasketIcon({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.center,
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ShoppingBasketScreen()),
);
},
child: Stack(
children: <Widget>[
new Icon(
Icons.shopping_cart_outlined,
color: Colors.white,
),
new Positioned(
right: 0,
child: new Container(
padding: EdgeInsets.all(1),
decoration: new BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(6),
),
constraints: BoxConstraints(
minWidth: 12,
minHeight: 12,
),
child: Text(
context.read<ShoppingBasket>().items.length.toString(),
style: new TextStyle(
color: Colors.white,
fontSize: 8,
),
textAlign: TextAlign.center,
),
),
)
],
),
),
);
}
}
This is where the icon is implemented:
class OurHomePage extends StatefulWidget {
#override
_OurHomePageState createState() => _OurHomePageState();
}
class _OurHomePageState extends State<OurHomePage> {
#override
Widget build(BuildContext context) {
return Consumer<OurUser>(
builder: (_, user, __) {
return ChangeNotifierProvider<SignInViewModel>(
create: (_) => SignInViewModel(context.read),
builder: (_, child) {
return Scaffold(
appBar: AppBar(
title: Text("My app"),
actions: [
OurShoppingBasketIcon(),
IconButton(
icon: Icon(
Icons.logout,
color: Colors.white,
),
onPressed: () {
context.read<FirebaseAuthService>().signOut();
},
),
],
),
);
},
);
},
);
}
}
There are 2 items in the cart as of writing this:
But the icon on the homepage does not change:
Here is my main.dart:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
MultiProvider(
providers: [
Provider(
create: (_) => FirebaseAuthService(),
),
StreamProvider<OurUser>(
create: (context) =>
context.read<FirebaseAuthService>().onAuthStateChanged),
ChangeNotifierProvider.value(
value: ShoppingBasket(),
),
],
child: MaterialApp(theme: OurTheme().buildTheme(), home: OurHomePage()),
),
);
}
perhaps if you watch for the value it will be updated dynamically:
context.watch<ShoppingBasket>().items.length.toString(), //<-- watch instead of read
The OurHomePage needs to be wrapped in the Provider<ShoppingBasket>.
return Provider<ShoppingBasket>(
create: (context) => ShoppingBasket(),
child: Consumer<OurUser>(
builder: (_, user, __) {
return ChangeNotifierProvider<SignInViewModel>(
create: (_) => SignInViewModel(context.read),
builder: (_, child) {
return Scaffold(
appBar: AppBar(
title: Text("My app"),
actions: [
OurShoppingBasketIcon(),
IconButton(
icon: Icon(
Icons.logout,
color: Colors.white,
),
onPressed: () {
context.read<FirebaseAuthService>().signOut();
},
),
],
),
),
);
},
);
I forgot to NotifyListeners() in my Change Notifier class:
class ShoppingBasket extends ChangeNotifier {
Map<String, SingleBasketItem> _items = {};
Map<String, SingleBasketItem> get items {
return {..._items};
}
void addItem(String id) {
_items.putIfAbsent(
id,
() => SingleBasketItem(id),
);
notifyListeners(); //HERE
}
Hi guys i am new to flutter. I have a grid of clickable buttons. Right now its only two, but it can grow to many. how can I refactor this to make it more dynamic and handle many future buttons? like a grid list of buttons that you can each click to navigate to different pages.
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(30.0),
child: GridView.extent(
maxCrossAxisExtent: 150,
crossAxisSpacing: 15.0,
mainAxisSpacing: 15.0,
children: <Widget>[
FlatButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => ProductScreen(),
),
);
},
padding: EdgeInsets.only(top: 33),
child: Column(
children: [
Icon(
Icons.shopping_cart_outlined,
color: Colors.white,
),
Text(
"Products",
style: TextStyle(
color: Colors.white,
),
),
],
),
),
FlatButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => MailScreen(),
),
);
},
padding: EdgeInsets.only(top: 33),
child: Column(
children: [
Icon(
Icons.mail,
color: Colors.white,
),
Text(
"Mail",
style: TextStyle(
color: Colors.white,
),
),
],
),
),
],
),
),
);
}
}
Here is a solution:
1. Define a AppAction Model
class AppAction {
final Color color;
final String label;
final Color labelColor;
final IconData iconData;
final Color iconColor;
final void Function(BuildContext) callback;
AppAction({
this.color = Colors.blueGrey,
this.label,
this.labelColor = Colors.white,
this.iconData,
this.iconColor = Colors.white,
this.callback,
});
}
You could also have the route or its name instead of a callback function. Though, a callback will allow you to define other types of actions if needed. (example: launching an external URL, triggering a modal dialog, etc.)
2. Defining your Application Actions
final List<AppAction> actions = [
AppAction(
label: 'Products',
iconData: Icons.shopping_cart_outlined,
callback: (context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => ProductScreen()));
},
),
AppAction(
label: 'Mails',
iconData: Icons.mail,
callback: (context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => MailScreen()));
},
),
AppAction(
color: Colors.white,
label: 'Urgent',
labelColor: Colors.redAccent,
iconData: Icons.dangerous,
iconColor: Colors.redAccent,
callback: (context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => UrgentScreen()));
},
),
AppAction(
color: Colors.green.shade200,
label: 'News',
labelColor: Colors.black,
iconData: Icons.new_releases,
iconColor: Colors.green,
callback: (context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => NewsScreen()));
},
),
];
3. Define a generic ActionButton
class ActionButton extends StatelessWidget {
final AppAction action;
const ActionButton({
Key key,
this.action,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return OutlinedButton.icon(
onPressed: () => action.callback?.call(context),
style: OutlinedButton.styleFrom(
backgroundColor: action.color,
padding: const EdgeInsets.all(16.0),
),
label: Text(action.label, style: TextStyle(color: action.labelColor)),
icon: Icon(action.iconData, color: action.iconColor),
);
}
}
4. Simplify your HomePage
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return AppLayout(
pageTitle: 'Home Page',
child: Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(30.0),
child: GridView.extent(
maxCrossAxisExtent: 120,
crossAxisSpacing: 15.0,
mainAxisSpacing: 15.0,
children: actions.map((action) => ActionButton(action: action)).toList(),
),
),
);
}
}
Voilà! If you want, here is a full standalone code sample to play with:
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
title: 'Flutter Demo',
home: HomePage(),
),
);
}
class AppAction {
final Color color;
final String label;
final Color labelColor;
final IconData iconData;
final Color iconColor;
final void Function(BuildContext) callback;
AppAction({
this.color = Colors.blueGrey,
this.label,
this.labelColor = Colors.white,
this.iconData,
this.iconColor = Colors.white,
this.callback,
});
}
final List<AppAction> actions = [
AppAction(
label: 'Products',
iconData: Icons.shopping_cart_outlined,
callback: (context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => ProductScreen()));
},
),
AppAction(
label: 'Mails',
iconData: Icons.mail,
callback: (context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => MailScreen()));
},
),
AppAction(
color: Colors.white,
label: 'Urgent',
labelColor: Colors.redAccent,
iconData: Icons.dangerous,
iconColor: Colors.redAccent,
callback: (context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => UrgentScreen()));
},
),
AppAction(
color: Colors.green.shade200,
label: 'News',
labelColor: Colors.black,
iconData: Icons.new_releases,
iconColor: Colors.green,
callback: (context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => NewsScreen()));
},
),
];
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return AppLayout(
pageTitle: 'Home Page',
child: Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(30.0),
child: GridView.extent(
maxCrossAxisExtent: 120,
crossAxisSpacing: 15.0,
mainAxisSpacing: 15.0,
children:
actions.map((action) => ActionButton(action: action)).toList(),
),
),
);
}
}
class AppLayout extends StatelessWidget {
final String pageTitle;
final Widget child;
const AppLayout({Key key, this.pageTitle, this.child}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(pageTitle)),
body: child,
);
}
}
class ActionButton extends StatelessWidget {
final AppAction action;
const ActionButton({
Key key,
this.action,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return OutlinedButton.icon(
onPressed: () => action.callback?.call(context),
style: OutlinedButton.styleFrom(
backgroundColor: action.color,
padding: const EdgeInsets.all(16.0),
),
label: Text(action.label, style: TextStyle(color: action.labelColor)),
icon: Icon(action.iconData, color: action.iconColor),
);
}
}
class ProductScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return AppLayout(
pageTitle: ('Products Page'),
child: Center(
child: Text('LIST OF PRODUCTS'),
),
);
}
}
class MailScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return AppLayout(
pageTitle: 'Mail Page',
child: Center(
child: Text('LIST OF MAIL'),
),
);
}
}
class UrgentScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return AppLayout(
pageTitle: 'Urgent Page',
child: Center(
child: Text('URGENT', style: TextStyle(color: Colors.redAccent)),
),
);
}
}
class NewsScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return AppLayout(
pageTitle: 'News Page',
child: Center(
child: Text('NEWS', style: TextStyle(color: Colors.green)),
),
);
}
}
Create a separate widget for the button and pass the color, icon, Text and route in the params.
Instead of using push in navigator use pushNamed and used the passed route name here.
I'm trying to build a collapse view after clicking an IconButton on my AppBar widget, I used ExpansionTile but nothing happens after I clicked the IconButton.
appBar: AppBar(
actions: <Widget>[
IconButton(
onPressed: () {
ExpansionTile(
title: Text(
"Settings",
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold
),
),
);
},
icon: Icon(Icons.settings),
),
],
),
Did I write the code right, or should I consider refactoring it. Thanks in advance!
Yes, you need to refactor your code because you cannot insert a widget into the widget tree this way directly from a function. I'm not sure of what you are trying to do, so I made two assumptions (1) You are trying to show a Expansion Tile in the app bar or (2) You want to show a Popup menu. Please see my code below to understand how you can achieve both.
import 'package:flutter/material.dart';
final Color darkBlue = const Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
title: 'Welcome to Flutter',
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Widget myWidget = Container(
child: const Text("Flutter"),
);
String myText = 'Hello, World!';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: myWidget, actions: [
IconButton(
onPressed: () async {
print(context);
showMenu(
context: context,
position: const RelativeRect.fromLTRB(110.0, 80.0, 0.0, 0.0),
items: ["One", "Two", "Three", "Four"]
.map(
(value) => PopupMenuItem<String>(
child: Text(value),
value: value,
),
)
.toList(),
elevation: 8.0,
);
},
icon: Icon(Icons.settings),
),
PopupMenuButton<int>(
onSelected: (selected) {
setState(
() {
myText = "You selected the menu number $selected";
},
);
},
itemBuilder: (BuildContext context) => <PopupMenuEntry<int>>[
const PopupMenuItem<int>(
value: 1,
child: Text('First Item'),
),
const PopupMenuItem<int>(
value: 2,
child: Text('Second Item'),
),
const PopupMenuItem<int>(
value: 3,
child: Text('Thrid Item'),
),
const PopupMenuItem<int>(
value: 4,
child: Text('Fourth Item'),
),
],
)
]),
body: Center(
child: Text(myText, style: Theme.of(context).textTheme.headline4),
),
);
}
}