How to change appBar's back icon theme globally? - flutter

Flutter automatically provides a back button for routes that can pop, but how can I change the back button Icon theme through the whole app?
Like how can I change the normal material back icon to chevron?

Create pages without Scafold and use this method to navigate between routes.
navigateToRoute(BuildContext context, Widget page,String title) {
Navigator.push(context, MaterialPageRoute(builder: (context) => Scaffold(
appBar: AppBar(
leading:Icon(Icons.chevron_left),
title: Text(title),
),
body: page,
)));
}

You have to create a custom BackButton in that case. I'll suggest that you can create a customAppBar method and use it everywhere.
Checkout the below code.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ScreenOne(),
);
}
}
class ScreenOne extends StatefulWidget {
#override
_ScreenOneState createState() => _ScreenOneState();
}
class _ScreenOneState extends State<ScreenOne> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: customAppBar(title: Text("Screen One")),
body: Center(
child: RaisedButton(onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (_) => ScreenTwo()));
}),
),
);
}
}
class ScreenTwo extends StatefulWidget {
#override
_ScreenTwoState createState() => _ScreenTwoState();
}
class _ScreenTwoState extends State<ScreenTwo> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: customAppBar(
customBackButton: true,
title: Text("Screen Two"),
),
);
}
}
AppBar customAppBar({
Widget title,
bool customBackButton = false,
}) {
return AppBar(
leading: customBackButton ? CustomBackButton() : null,
title: title,
);
}
class CustomBackButton extends StatelessWidget {
const CustomBackButton({Key key, this.color, this.onPressed}) : super(key: key);
final Color color;
final Function onPressed;
#override
Widget build(BuildContext context) {
assert(debugCheckHasMaterialLocalizations(context));
return IconButton(
icon: Icon(Icons.arrow_back_ios),
color: color,
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
onPressed: () {
if (onPressed != null) {
onPressed();
} else {
Navigator.maybePop(context);
}
},
);
}
}
Hope it helps :)

return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
appBarTheme: AppBarTheme(
iconTheme: IconThemeData(
color: Colors.black,
),
),
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);[![Initially didn't put any color so it was white[![This is the image when I added appbartheme and changed color to black][1]][1]][1]

Related

Flutter ColorScheme class Background color not showing in scaffold

My code is:
import 'package:flutter/material.dart';
void main() => runApp(BMICalculator());
class BMICalculator extends StatelessWidget {
#override
Widget build(BuildContext context) {
final ThemeData theme = ThemeData();
return MaterialApp(
theme: theme.copyWith(
colorScheme: theme.colorScheme.copyWith(
secondary: Colors.purple,
primary: Color(0xFF0d0f1e),
background: primaryC,
),
),
home: InputPage(),
);
}
}
class InputPage extends StatefulWidget {
#override
_InputPageState createState() => _InputPageState();
}
class _InputPageState extends State<InputPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BMI CALCULATOR'),
),
body: Center(
child: Text('Body Text'),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
),
);
}
}
And I have no idea why the background color of my app won't turn into the black/purple color I have set for it. I am following a tutorial that was using the depricated theme: ThemeData but I can't find the reason why my background color isn't changing for the scaffold.
To set a background color for your Scaffold, you can set the scaffoldBackgroundColor in your ThemeData.
Using your example:
import 'package:flutter/material.dart';
void main() => runApp(BMICalculator());
class BMICalculator extends StatelessWidget {
#override
Widget build(BuildContext context) {
final ThemeData theme = ThemeData();
return MaterialApp(
theme: theme.copyWith(
// Pick the color here
scaffoldBackgroundColor: Colors.black,
colorScheme: theme.colorScheme.copyWith(
secondary: Colors.purple,
primary: Color(0xFF0d0f1e),
),
),
home: InputPage(),
);
}
}
class InputPage extends StatefulWidget {
#override
_InputPageState createState() => _InputPageState();
}
class _InputPageState extends State<InputPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BMI CALCULATOR'),
),
body: Center(
child: Text('Body Text'),
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
),
);
}
}

Flutter Basics: My app bar color is not changing

import 'package:flutter/material.dart';
void main() {
runApp(RecipeApp());
}
class RecipeApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final ThemeData theme = ThemeData();
return MaterialApp(
title: 'Recipe Calculator',
theme: theme.copyWith(
colorScheme: theme.colorScheme.copyWith(
primary: Colors.grey,
secondary: Colors.black,
),
),
home: const MyHomePage(title: 'Recipe Calculator'),
);
}
}
This is the current code and above is the current output as per the code, the color remains blue and white instead of grey and black
running on my emulator using your code it works, try restarting your app completely.
import 'package:flutter/material.dart';
void main() {
runApp(RecipeApp());
}
class RecipeApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final ThemeData theme = ThemeData();
return MaterialApp(
title: 'Recipe Calculator',
theme: theme.copyWith(
colorScheme: theme.colorScheme.copyWith(
primary: Colors.grey,
secondary: Colors.black,
),
),
home: const MyHomePage(title: 'Recipe Calculator'),
);
}
}
class MyHomePage extends StatelessWidget {
final title;
const MyHomePage({this.title});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
);
}
}
Try below code hope its helpful to you ,I think you can used Scaffold Widget refer AppBar class here and refer Scaffold class here
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.grey,//change color on your need
title: Text(
'BottomNavigationBar Sample',
),
),
body:Container(),//or your widget
);
Your result screen->

flutter: provider dosen't work in statefulwidget

I create a new flutter demo and modify it to use the provider package. But it doesn't work. And here is my code.
class MyState {
MyState();
int cnt = 0;
void increase() {
print("increase. $cnt");
cnt++;
}
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Provider<MyState>(
create: (_) => MyState(),
child: MyHomePage(title: 'Flutter Demo Home Page'),
),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Consumer<MyState>(
builder: (context, state, _) {
return Text(
"${state.cnt}",
style: Theme.of(context).textTheme.headline4,
);
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: Provider.of<MyState>(context, listen: false).increase,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
When press the button, the UI is not rebuilt. And as the printed messages show, the cnt field of Mystate had been changed. Why? May provider can not be used in statefulwidget?
Provider: You can use Provider to provide a value anywhere in the widget tree. It will not rebuild the widget tree whenever the value changes. It simply passes the model to its descendant's widget in the widget tree.
ChangeNotifierProvider: ChangeNotifierProvider listens for changes in the model object. It rebuilds the dependents widgets whenever ChangeNotifier.notifyListeners is called.
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyState with ChangeNotifier {
MyState();
int cnt = 0;
void increase() {
print("increase. $cnt");
cnt++;
notifyListeners();
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<MyState>(
create: (context) => MyState(),
child: Scaffold(
appBar: AppBar(
title: Text("Page Title"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'You have pushed the button this many times:',
),
Consumer<MyState>(
builder: (context, counter, child) => Text(
'${counter.cnt}',
style: Theme.of(context).textTheme.display1,
),
),
],
),
),
floatingActionButton: Builder(builder: (context) {
return FloatingActionButton(
onPressed: Provider.of<MyState>(context, listen: false).increase,
tooltip: 'Increment',
child: Icon(Icons.add),
);
}),
),
);
}
}
You can copy paste run full code below
Step 1: MyState extends ChangeNotifier and use notifyListeners()
Step 2: Use ChangeNotifierProvider
code snippet
class MyState extends ChangeNotifier {
MyState();
int cnt = 0;
void increase() {
print("increase. $cnt");
cnt++;
notifyListeners();
}
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
...
home: ChangeNotifierProvider(
create: (_) => MyState(),
child: MyHomePage(title: 'Flutter Demo Home Page'),
working demo
full code
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyState extends ChangeNotifier {
MyState();
int cnt = 0;
void increase() {
print("increase. $cnt");
cnt++;
notifyListeners();
}
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: ChangeNotifierProvider(
create: (_) => MyState(),
child: MyHomePage(title: 'Flutter Demo Home Page'),
),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Consumer<MyState>(
builder: (context, state, _) {
return Text(
"${state.cnt}",
style: Theme.of(context).textTheme.headline4,
);
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: Provider.of<MyState>(context, listen: false).increase,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

How to keep the widget's state in Scaffold.drawer in Flutter?

I want to keep the widget's state in Scaffold.drawer. The Scaffold.drawer is a custom widget, which has a RaiseButton in it.
When click the button, the text in the button changed.
But when the drawer is closed, and reopen the drawer, the changed text is reseted.
I have use " with AutomaticKeepAliveClientMixin<> " in my custom Drawer, but it does't work.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Flutter Demo"),
),
drawer: Drawer(child: CustomDrawer(),),
body: Center(
child: Text("Flutter Demo"),
),
);
}
}
class CustomDrawer extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _CustomDrawerState();
}
}
class _CustomDrawerState extends State<CustomDrawer> with AutomaticKeepAliveClientMixin<CustomDrawer> {
String btnText = "Click!";
#override
bool get wantKeepAlive => true;
#override
Widget build(BuildContext context) {
super.build(context);
return Center(
child: RaisedButton(onPressed: () {
setState(() {
btnText = "Clicked!!";
});
}, child: Text(btnText),),
);
}
}
I expect the widget's state can keep, even if the Drawer is closed.
Create a separate widget for the drawer and just use in anywhere you need to.
Manage the Drawer State with a Provider
class DrawerStateInfo with ChangeNotifier {
int _currentDrawer = 0;
int get getCurrentDrawer => _currentDrawer;
void setCurrentDrawer(int drawer) {
_currentDrawer = drawer;
notifyListeners();
}
void increment() {
notifyListeners();
}
}
Adding State Management to the Widget tree
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MultiProvider(
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.teal,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
),
providers: <SingleChildCloneableWidget>[
ChangeNotifierProvider<DrawerStateInfo>(
builder: (_) => DrawerStateInfo()),
],
);
}
}
Creating The Drawer Widget for reuse in application
class MyDrawer extends StatelessWidget {
MyDrawer(this.currentPage);
final String currentPage;
#override
Widget build(BuildContext context) {
var currentDrawer = Provider.of<DrawerStateInfo>(context).getCurrentDrawer;
return Drawer(
child: ListView(
children: <Widget>[
ListTile(
title: Text(
"Home",
style: currentDrawer == 0
? TextStyle(fontWeight: FontWeight.bold)
: TextStyle(fontWeight: FontWeight.normal),
),
trailing: Icon(Icons.arrow_forward),
onTap: () {
Navigator.of(context).pop();
if (this.currentPage == "Home") return;
Provider.of<DrawerStateInfo>(context).setCurrentDrawer(0);
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (BuildContext context) =>
MyHomePage(title: "Home")));
},
),
ListTile(
title: Text(
"About",
style: currentDrawer == 1
? TextStyle(fontWeight: FontWeight.bold)
: TextStyle(fontWeight: FontWeight.normal),
),
trailing: Icon(Icons.arrow_forward),
onTap: () {
Navigator.of(context).pop();
if (this.currentPage == "About") return;
Provider.of<DrawerStateInfo>(context).setCurrentDrawer(1);
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (BuildContext context) => MyAboutPage()));
},
),
],
),
);
}
}
Use of Drawer in one of your pages
class MyAboutPage extends StatefulWidget {
#override
_MyAboutPageState createState() => _MyAboutPageState();
}
class _MyAboutPageState extends State<MyAboutPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('About Page'),
),
drawer: MyDrawer("About"),
);
}
}
In your case, you have 2 choices:
You should keep your state in your Top level widget. in your case _MyHomePageState;
Use state managers like Redux, Bloc, ScopedModel. I think ScopedModel is great for you in this case.
otherwise, you can't control the state of Drawer. cause it re-creates every moment you call the Drawer by the action button in Appbar;

How to fix Flutter MaterialApp(not_enough_required_arguments)?

when returning MaterialApp flutter shows error as follow "error: 1 required argument(s) expected, but 0 found. (not_enough_required_arguments at [demo] lib/main.dart:9)"Here is the screenshot
const _categoryName = "Cake";
const _categoryIcon = Icons.cake;
const _categoryColor = Colors.green;
import 'package:solution_02_category_widget/category.dart';
void main() {
runApp(UnitConverterApp());
}
class UnitConverterApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Unit Converter',
home: Scaffold(
backgroundColor: Colors.green[100],
body: Center(
child: Category(
name: _categoryName,
color: _categoryColor,
iconLocation: _categoryIcon,
),
),
),
);
}
}
You should wrap the title argument under AppBar Widget. You can in turn wrap the appBar argument inside the Scaffold. The scaffold is like an empty page that gives your app the white background. Below is a sample code implementation:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
// debugShowMaterialGrid: true,
theme: ThemeData(
brightness: Brightness .light,
accentColor: Colors.deepPurple,
primarySwatch: Colors.deepOrange),
home: Scaffold(
appBar: AppBar(
title: Text('Some text'),
),
),
);
}
}
Your code is working fine without error if i remove the Category() widget. The below code is working fine:
import 'package:flutter/material.dart';
const _categoryName = "Cake";
const _categoryIcon = Icons.cake;
const _categoryColor = Colors.green;
void main() {
runApp(UnitConverterApp());
}
class UnitConverterApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Unit Converter',
home: Scaffold(
backgroundColor: Colors.green[100],
body: Center(
child: Container(),
),
),
);
}
}
Maybe the problem is in the Category() widget so if you post it i can check it for you.