How can i change theme of my widget in this situation? - flutter

Im not sure that my code is correct for using themes and easylocalization together and im open for any help too, but my main goal is creating a custom navigation bar inside of MyApp. When i do it like example down below, i cant change my NavBarItem theme with my theme provider because of its outside of MaterialApp. How can i handle this situation ?
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
runApp(EasyLocalization(
supportedLocales: [
Locale('en'),
Locale('tr'),
],
path: 'assets/translations',
saveLocale: true,
fallbackLocale: Locale('en'),
child: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => CustomThemeData(),
builder: (context, _) {
return MaterialApp(
debugShowCheckedModeBanner: false,
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
theme: Provider.of<CustomThemeData>(context).getThemeData,
home: Scaffold(
body: _ActivePage,
bottomNavigationBar: Container(child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
NavBarItem(),
NavBarItem(),
NavBarItem(),
],
),),
),
//
);
},
);
}
Widget NavBarItem(){}
}

You can try this below codebase, I think you will get your solution.
main.dart
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:theme_changer/custom_theme_data.dart';
final callMenuTheme = ThemeData(
primarySwatch: Colors.orange,
colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.orange),
iconTheme: const IconThemeData(
color: Colors.orange,
),
);
final cameraMenuTheme = ThemeData(
primarySwatch: Colors.red,
colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.red),
iconTheme: const IconThemeData(
color: Colors.red,
),
);
final chatMenuTheme = ThemeData(
primarySwatch: Colors.green,
colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.green),
iconTheme: const IconThemeData(
color: Colors.green,
),
);
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
runApp(EasyLocalization(
supportedLocales: const [
Locale('en'),
Locale('tr'),
],
path: 'assets/translations',
saveLocale: true,
fallbackLocale: const Locale('en'),
child: ChangeNotifierProvider(
create: (context) => CustomThemeData(0, callMenuTheme),
builder: (context, _) {
return MaterialApp(
debugShowCheckedModeBanner: false,
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
theme: Provider.of<CustomThemeData>(context).getThemeData(),
home: const MyApp(),
//
);
},
)));
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
var themeNotifier = Provider.of<CustomThemeData>(context,listen: false);
List<Widget> _pages = <Widget>[
const Icon(
Icons.call,
size: 150,
),
const Icon(
Icons.camera,
size: 150,
),
const Icon(
Icons.chat,
size: 150,
),
];
void _onItemTapped(int index) async{
setState(() {
switch(index) {
case 0:
{
themeNotifier.setNavigationIndexData(0);
themeNotifier.setThemeData(callMenuTheme);
}
break;
case 1:
{
themeNotifier.setNavigationIndexData(1);
themeNotifier.setThemeData(cameraMenuTheme);
}
break;
case 2:
{
themeNotifier.setNavigationIndexData(2);
themeNotifier.setThemeData(chatMenuTheme);
}
break;
default:
{
themeNotifier.setNavigationIndexData(0);
themeNotifier.setThemeData(callMenuTheme);
}
break;
}
});
}
return MaterialApp(
debugShowCheckedModeBanner: false,
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
theme: themeNotifier.getThemeData(),
home: Scaffold(
appBar: AppBar(
title: const Text('BottomNavigationBar Demo'),
),
body: Center(
child: _pages.elementAt(themeNotifier.getNavigationIndexData()),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.call),
label: 'Calls',
),
BottomNavigationBarItem(
icon: Icon(Icons.camera),
label: 'Camera',
),
BottomNavigationBarItem(
icon: Icon(Icons.chat),
label: 'Chats',
),
],
currentIndex: themeNotifier.getNavigationIndexData(),
onTap: _onItemTapped,
),
),
);
}
}
custom_theme_data.dart
import 'package:flutter/material.dart';
class CustomThemeData with ChangeNotifier {
ThemeData? _themeData;
int? _navigationIndex;
CustomThemeData(this._navigationIndex, this._themeData);
getNavigationIndexData() => _navigationIndex;
setNavigationIndexData(int navigationIndex) async {
_navigationIndex = navigationIndex;
notifyListeners();
}
getThemeData() => _themeData;
setThemeData(ThemeData themeData) async {
_themeData = themeData;
notifyListeners();
}
}
If you need a better idea about the project, here is the GitHub link to this project. Also, you will check the screenshots(1,2,3) of this project.

Related

Flutter Theme Dark/Lights Theme toggle doesn't work

there is a dark/light theme toggle function in this snap of code. There is no error when I compile, debuging this code. But It doesn't work.
For example, I never define scaffoldbackgroundColor(0xfffafafa) and What I define color in dark, light theme is Color(0xFFE7626C) and Color(0xFF232B55). But ios simulator only show me backgroundcolor(0xfffafafa).
When I click toggle button, the screen never changes. What's wrong with my code...
import 'package:flutter/material.dart';
import 'package:pomodoro_app/widget/sidebar_widget.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
static final ValueNotifier<ThemeMode> themeNotifier =
ValueNotifier(ThemeMode.dark);
#override
Widget build(BuildContext context) {
return ValueListenableBuilder<ThemeMode>(
valueListenable: themeNotifier,
builder: (_, ThemeMode currentMode, __) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
brightness: Brightness.light,
scaffoldBackgroundColor: const Color(0xFFE7626C),
textTheme: const TextTheme(
displayLarge: TextStyle(
color: Color(0xFF232B55),
),
displaySmall: TextStyle(
color: Color(0xFF232B55),
),
),
cardColor: const Color(0xFFF4EDDB),
),
darkTheme: ThemeData(
brightness: Brightness.dark,
scaffoldBackgroundColor: const Color(
0xFF232B55,
),
cardColor: const Color(0xFFF4EDDB),
textTheme: const TextTheme(
displayLarge: TextStyle(
color: Color(0xFFE7626C),
),
displaySmall: TextStyle(
color: Colors.white,
),
),
),
themeMode: currentMode,
home: Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
elevation: 0,
leading: Builder(
builder: (context) => IconButton(
onPressed: () => Scaffold.of(context).openDrawer(),
icon: const Icon(
Icons.menu_rounded,
color: Color(0xFFF4EDDB),
),
),
),
actions: [
IconButton(
icon: Icon(themeNotifier.value == ThemeMode.light
? Icons.dark_mode
: Icons.light_mode),
onPressed: () {
setState(
() {
themeNotifier.value =
themeNotifier.value == ThemeMode.light
? ThemeMode.dark
: ThemeMode.light;
},
);
},
),
],
),
drawer: const SideBar(),
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
"Hello",
)
],
),
),
);
},
);
}
}
That's because the context you are using with
Theme.of(context);
comes from the build method of _HomeScreenState.
So this context is above the MaterialApp which has the Theme.
You have to use a context that is bellow the MaterialApp.
One way to do it is to add a Builder in between your MaterialApp and Scaffold:
return MaterialApp(
title: 'Flutter Demo',
theme: // ...
darkTheme: // ...
themeMode: currentMode,
home: Builder( // <- Insert a builder here.
builder: (context) { // <- Now you'll be using this `context` which is below the `MaterialApp` (and your themes) in the widget tree, so you'll be able to use them.
return Scaffold(
// ...
);
},
);

How to change theme to dark on click on IconButton?

In my application, in the appBar, there is a button that should change the theme to dark. I need to create functionality Provider. How can this be implemented? I just need to change the Scaffold color to black and the text color to white.
My main.dart:
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
textTheme: const TextTheme(
headline1: TextStyle(fontSize: 50.0, fontWeight: FontWeight.bold),
headline5: TextStyle(fontSize: 36.0, fontStyle: FontStyle.italic),
subtitle2: TextStyle(fontSize: 10.0, color: Colors.black),
bodyText1: TextStyle(fontSize: 14.0, color: Colors.black),
),
),
home: const HomeScreen(),
);
}
My switch button:
appBar: AppBar(
title: const Text('Flutter theme config'),
centerTitle: true,
actions: [
IconButton(
onPressed: () {
},
icon: const Icon(Icons.dark_mode),
)
],
),
Theme provider:
class ThemeProvider extends ChangeNotifier {
}
You can try something like this :
First we provide our Provider globally for the whole application, and then in the attribute theme: we listen for the change.
** main **
void main() async {
runApp(
MultiProvider( // create the provider
providers: [
ChangeNotifierProvider(
create: (_) => ThemeProvider(),
)
],
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Material App',
initialRoute: HomeScreen.routerName,
routes: {
},
theme: Provider.of<ThemeProvider>(context).currentTheme, // listen to the current theme
);
}
}
In the provider we will only have two functions, one to switch to LightMode and the other to DarkMode, then we add it to the currentTheme variable which is the one that listens in the main
** ThemeProvider **
class ThemeProvider extends ChangeNotifier {
ThemeData? currentTheme;
setLightMode() {
currentTheme = ThemeData(
brightness: Brightness.light, // LightMode
scaffoldBackgroundColor: Colors.red,
[...] // more attributes
);
notifyListeners();
}
setDarkmode() {
currentTheme = ThemeData(
brightness: Brightness.dark, // DarkMode
scaffoldBackgroundColor: Colors.green,
[...] // more attributes
);
notifyListeners();
}
}
Finally we create a StatefulWidget to change the isDarkMode variable to call the provider
** Button Home **
class _HomeScreenState extends State<SettingsScreen> {
bool isDarkmode = false; // new variable
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Settings"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: IconButton(
onPressed: () {
final themeProvider =
Provider.of<ThemeProvider>(context, listen: false); // get the provider, listen false is necessary cause is in a function
setState(() {
isDarkmode = !isDarkmode;
}); // change the variable
isDarkmode // call the functions
? themeProvider.setDarkmode()
: themeProvider.setLightMode();
},
icon: const Icon(Icons.dark_mode),
),
),
);
}
}

Flutter: assertion: line 4269 pos 14 : 'owner!._debugCurrentBuildTarget == this': is not true

I'm making an "inventory" app, to keep track of objects food etc in my house. I wanted to use a navigator, to make multiple pages, without "modifying" the widgets in the scaffold.
This is my code: (i have as you can see multiple file, ask me if you need something else)
Just to be clear, the utils.dart is an export file that I use to import every thing else
import 'package:flutter/material.dart';
import 'package:storage_system/utils.dart';
import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Storage System',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.yellow,
),
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _index = 0;
void _onTap(int i) {
setState(() {
_index = i;
});
}
Future<void> getBarcodeData() async {
String resultData = await FlutterBarcodeScanner.scanBarcode(
"0xFFFFFF", "Close", false, ScanMode.BARCODE);
print(resultData);
}
Widget selectPage(int i) {
switch (i) {
case 0:
return MainPage();
case 1:
return SettingsPage();
default:
return Container();
}
}
#override
Widget build(BuildContext context) => Navigator(
onGenerateRoute: (settings) => MaterialPageRoute(
builder: (context) => Container(
child: Scaffold(
floatingActionButtonLocation:
FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
onPressed: getBarcodeData,
child: Icon(Icons.add),
),
appBar: AppBar(
actions: <Widget>[],
title: Text(
"Storage System",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 28),
),
),
bottomNavigationBar: BottomNavigationBar(
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home), label: "Home"),
BottomNavigationBarItem(
icon: Icon(Icons.settings), label: "Setings")
],
currentIndex: _index,
onTap: _onTap,
elevation: 15,
),
body: Container(
child: selectPage(_index),
),
),
)),
);
}

NoSuchMethodError: The getter was called on null

`
class MainPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider( //Comes from provider class
create: (context) => LocaleProvider(),
builder: (context, child) {
final provider = Provider.of<LocaleProvider>(context);
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Forts In Maharashtra',
locale: provider.locale,
supportedLocales: L10n.all,
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
home: MyApp(),
);
});
}
}
class MyApp extends StatefulWidget {
//static const String _title = 'Forts in Maharashtra';
MyApp({Key key, this.title}) : super(key: key);
final String title;
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
new FirebaseNotifications().setUpFirebase();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(accentColor: Colors.deepOrange),
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: Text(
AppLocalizations.of(context).apptitle, //Translates the text
style: TextStyle(fontSize: 23.0),
),
backgroundColor: Colors.deepOrange,
actions: [
Icon(Icons.language, size: 28),
LanguagePick(),
const SizedBox(width: 12),
],
),
body: MyBottomNavigationBar()),
);
}
}
class MyBottomNavigationBar extends StatefulWidget {
class _MyBottomNavigationBarState extends State<MyBottomNavigationBar> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: _children[_currentindex],
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
selectedItemColor: Colors.deepOrange,
onTap: onTappedBar,
currentIndex: _currentindex,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.explore),
label: AppLocalizations.of(context).exploreforts), //Giving error here
BottomNavigationBarItem(
icon: Icon(MdiIcons.waves), label: 'Sea Forts'),
BottomNavigationBarItem(
icon: Icon(Icons.terrain), label: 'Attractions'),
BottomNavigationBarItem(
icon: Icon(Icons.location_city), label: 'City Forts'),
],
));
}
}`
I am trying to use the Localization feature in my application. I am able to change the AppBar title to another language but I am unable to change the language on the BottomNavigationBar. I am having trouble changing the language in BottomNavigationBar. The App language is changed on the AppBar but I am facing issues while using the same in the BottomNavigationBar. I have added comments where required.
This is because you are defining two MaterialApp. You only need to define one in the main and render it in the entire app, remove the MaterialApp from the _MyAppState class

Flutter: animate appbar color with bottomnavigationbar

I wonna animate my appbar color the same way as the bottomnavigationbar does with the shifting type. So the appbar and bottomnavigationbar change color together.
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _tabIndex = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Dash')),
body: Container(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _tabIndex,
onTap: (value) => setState(() => _tabIndex = value),
type: BottomNavigationBarType.shifting,
unselectedItemColor: Theme.of(context).unselectedWidgetColor,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.dashboard), title: Text('Dash'), backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.insert_chart), title: Text('Data'), backgroundColor: Colors.red),
BottomNavigationBarItem(
icon: Icon(Icons.monetization_on), title: Text('Income'), backgroundColor: Colors.orange),
]),
);
}
}
How can I do this? (I'm fairly new to flutter) Thanks!
It's very simple. Simply change color based on the selected index.
Here you go
import 'package:flutter/material.dart';
final Color darkBlue = 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),
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _tabIndex = 0;
var colors = [Colors.blue, Colors.red, Colors.orange];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Dash'),
backgroundColor: colors[_tabIndex],
),
body: Container(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _tabIndex,
onTap: (value) => setState(() => _tabIndex = value),
type: BottomNavigationBarType.shifting,
unselectedItemColor: Theme.of(context).unselectedWidgetColor,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.dashboard),
title: Text('Dash'),
backgroundColor: colors[0]),
BottomNavigationBarItem(
icon: Icon(Icons.insert_chart),
title: Text('Data'),
backgroundColor: colors[1]),
BottomNavigationBarItem(
icon: Icon(Icons.monetization_on),
title: Text('Income'),
backgroundColor: colors[2]),
]),
);
}
}
See the live demo here.