I like flutter hot reload. I use flutter bloc and auto route. but it doesn't work for me
main.dart file
void main() {
WidgetsFlutterBinding.ensureInitialized();
configureInjection(Environment.prod);
runApp(const AppWidget());
}
app_widget.dart
class AppWidget extends StatelessWidget {
const AppWidget({super.key});
#override
Widget build(BuildContext context) {
final _appRouter = AppRouter();
return MultiBlocProvider(
providers: [
BlocProvider(
create: (context) =>
getIt<AuthBloc>()..add(const AuthEvent.authCheckRequested()))
],
child: MaterialApp.router(
title: 'MyApp',
routerDelegate: _appRouter.delegate(),
routeInformationParser: _appRouter.defaultRouteParser(),
debugShowCheckedModeBanner: false,
theme: ThemeData.light().copyWith(
floatingActionButtonTheme: FloatingActionButtonThemeData(
backgroundColor: Colors.blue[900],
),
primaryColor: Colors.green[800],
colorScheme: ColorScheme.fromSwatch().copyWith(
secondary: Colors.blueAccent,
),
inputDecorationTheme: InputDecorationTheme(
hintStyle: const TextStyle(fontSize: 10),
contentPadding:
const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(40)),
),
),
),
);
}
}
I tried to convert AppWidget to statefull but doesn't work
Thanks for your valuable time
Related
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(
// ...
);
},
);
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),
),
),
);
}
}
I added the libraries to pubspec.yaml. In the current project I am not using hooks, but used the package because I want to use this to build a skeleton starter project.
pubspec.yaml:
flutter_hooks: ^0.18.2+1
hooks_riverpod: ^1.0.3
Then I modified the code to the latest RiverPod syntax. This involved changing things to Consumer widgets and using the ref parameter. The app now runs but just is not switching from dark mode to light mode and vice versa!
main.dart:
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
class AppThemeState extends StateNotifier<bool> {
AppThemeState(): super(false);
void setLightTheme() => state = false;
void setDarkTheme() => state = true;
}
// Theme
final appThemeStateNotifier = StateNotifierProvider((ref) => AppThemeState());
void main() {
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends HookConsumerWidget {
#override
Widget build(BuildContext context, WidgetRef ref) {
final darkModeEnabled = ref.watch(appThemeStateNotifier);
return MaterialApp(
title: 'Flutter Demo',
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
themeMode: darkModeEnabled != null ? ThemeMode.dark : ThemeMode.light,
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 2.0,
title: Text("Flutter Theme Riverpod Demo"),
),
body: Column(
children: [
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Light Mode"),
DarkModeSwitch(),
Text("Dark Mode"),
],
),
),
],
),
);
}
}
class DarkModeSwitch extends ConsumerWidget {
#override
Widget build(BuildContext context, WidgetRef ref) {
final darkModeEnabled = ref.read(appThemeStateNotifier) == true;
return //Text('$darkModeEnabled');
Switch(
value: darkModeEnabled,
onChanged: (enabled) {
if (enabled) {
ref.read(appThemeStateNotifier.notifier).setDarkTheme();
} else {
ref.read(appThemeStateNotifier.notifier).setLightTheme();
}
},
);
}
}
class AppTheme {
// Private Constructor
AppTheme._();
static final lightTheme = ThemeData(
scaffoldBackgroundColor: Colors.white,
appBarTheme: AppBarTheme(
color: Colors.teal,
iconTheme: IconThemeData(
color: Colors.white,
),
),
textTheme: TextTheme(
bodyText2: TextStyle(
color: Colors.black,
),
),
);
static final darkTheme = ThemeData(
scaffoldBackgroundColor: Colors.black,
appBarTheme: AppBarTheme(
color: Colors.black,
iconTheme: IconThemeData(
color: Colors.white,
),
),
textTheme: TextTheme(
bodyText2: TextStyle(
color: Colors.white,
),
),
);
}
The problem is at this line:
themeMode: darkModeEnabled != null ? ThemeMode.dark : ThemeMode.light,
darkModeEnabled can't be null.
Use this instead:
themeMode: darkModeEnabled ? ThemeMode.dark : ThemeMode.light,
Flutter SearchDelegate: How to change the color of the blue bubbles in search delegate widget in flutter?
environment:
sdk: ">=2.12.0 <3.0.0"
In my Scaffold-Appbar i have an action with an IconButton and then i call DataSearch. Then i set the ThemeData appBarTheme in the DataSearch. Thats it.
appBar: AppBar(
title: Text(widget.title),
actions: [
IconButton(
icon: const Icon(Icons.search),
onPressed: () {
showSearch(context: context, delegate: DataSearch());
},
),
],
),
class DataSearch extends SearchDelegate<String> {
#override
ThemeData appBarTheme(BuildContext context) {
return ThemeData(
textSelectionTheme: TextSelectionThemeData(
//cursorColor: Colors.red,
selectionHandleColor: Colors.red,
//selectionColor: Colors.white,
), // cursor color
);
}
You can change the color within the textSelectionTheme by setting the selectionHandleColor.
textSelectionTheme: TextSelectionThemeData(
selectionHandleColor: Colors.red, // Change bubble to red
cursorColor: Colors.white,
),
EDIT: Full Example
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
textSelectionTheme: TextSelectionThemeData(
selectionHandleColor: Colors.red,
),
primaryColor: Colors.green,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: TextField(),
),
body: Center(
child: Text('MyApp'),
),
),
);
}
}
Result:
I am trying to customized the appearance of search using a custom SearchDelegate, but it appears that overriding appBarTheme only updates certain theme styles. I am able to change the color of the app bar and text style, but I appears to ignore other settings, like elevation and decoration.
How do I customize the search delegate input decoration and app bar elevation?
Am I missing something? Is this intended behavior?
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Title',
home: Scaffold(
appBar: AppBar(
actions: [
Builder(
builder: (context) => IconButton(
icon: Icon(Icons.search),
onPressed: () => showSearch(context: context, delegate: CustomSearchDelegate()),
),
),
],
),
),
);
}
}
class CustomSearchDelegate extends SearchDelegate {
#override
List<Widget> buildActions(BuildContext context) => [
if (query.isNotEmpty)
IconButton(
icon: Icon(Icons.close),
onPressed: () {
query = "";
showSuggestions(context);
},
)
];
#override
Widget buildLeading(BuildContext context) => IconButton(
tooltip: 'Back',
icon: AnimatedIcon(icon: AnimatedIcons.menu_arrow, progress: transitionAnimation),
onPressed: () => close(context, null),
);
#override
Widget buildSuggestions(BuildContext context) => Text("Suggestions go here");
#override
Widget buildResults(BuildContext context) => Text("Results go here");
#override
ThemeData appBarTheme(BuildContext context) {
final ThemeData theme = Theme.of(context);
return theme.copyWith(
primaryColor: Colors.white,
primaryIconTheme: theme.primaryIconTheme.copyWith(color: Colors.green),
primaryColorBrightness: Brightness.dark,
textTheme: theme.textTheme.copyWith(
title: TextStyle(fontWeight: FontWeight.normal),
),
// these ↓ do not work ☹️
appBarTheme: theme.appBarTheme.copyWith(color: Colors.black12, elevation: 0),
inputDecorationTheme: theme.inputDecorationTheme.copyWith(border: UnderlineInputBorder()),
);
}
}
I managed to get the elevation to zero by adding appBarTheme: AppBarTheme(elevation: 0.0, color: Colors.black12). I could not get the input decoration to work in the same way, I did add the line in the root of the app theme code but it didn't seem to work.
The code Root theme code is as follows:
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
backgroundColor: Colors.white,
appBarTheme: AppBarTheme(elevation: 0.0, color: Colors.black12),//elevation did work
inputDecorationTheme:
InputDecorationTheme(border: UnderlineInputBorder()),//this did not imply
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
and the Theme inside SearchDelegate is as follows:
#override
ThemeData appBarTheme(BuildContext context) {
assert(context != null);
final ThemeData theme = Theme.of(context);
assert(theme != null);
return theme.copyWith(
primaryColor: Colors.white,
primaryIconTheme: theme.primaryIconTheme.copyWith(color: Colors.green),
primaryColorBrightness: Brightness.dark,
textTheme: theme.textTheme.copyWith(
title: TextStyle(fontWeight: FontWeight.normal),
),
);
}
Hope this helps!
this is worked to me.
enter image description here
#override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: AnimatedIcon(icon: AnimatedIcons.menu_close, progress: transitionAnimation),
onPressed: () {
if (query.isEmpty) {
close(context, null);
} else {
query = "";
// showSuggestions(context);
}
},
),
];
}
#override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: AnimatedIcon(icon: AnimatedIcons.menu_arrow, progress: transitionAnimation),
onPressed: () => close(context, null),
);
}
#override
ThemeData appBarTheme(BuildContext context) {
final ThemeData theme = Theme.of(this.context);
return theme.copyWith(
accentColor: Colors.red,
textTheme: theme.textTheme.copyWith(
headline6: theme.textTheme.subtitle1.copyWith(color: Colors.black),
),
inputDecorationTheme: theme.inputDecorationTheme.copyWith(
hintStyle: theme.textTheme.subtitle1.copyWith(color: Colors.grey),
fillColor: Colors.grey[200],
filled: true,
isDense: true,
contentPadding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey, width: 0),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey, width: 0),
),
),
appBarTheme: theme.appBarTheme.copyWith(
titleSpacing: 0,
),
);
}
Modified adhithya Shetty's answer .
This is for those who wants to change hint color along with cursor color
Color primaryColor = Color(0xff673BB7); // My Custom Color
#override
ThemeData appBarTheme(BuildContext context) {
assert(context != null);
final ThemeData theme = Theme.of(context);
assert(theme != null);
return theme.copyWith(
appBarTheme: theme.appBarTheme.copyWith(backgroundColor: primaryColor), // appbar background color
primaryColor: primaryColor,
textSelectionTheme: TextSelectionThemeData(
cursorColor: Colors.white ), // cursor color
hintColor: Colors.white, //hint text color
primaryIconTheme: theme.primaryIconTheme.copyWith(color: Colors.white), //icons color
primaryColorBrightness: Brightness.dark,
textTheme: theme.textTheme.copyWith(
headline6: TextStyle(fontWeight: FontWeight.normal,color: Colors.white), // query Color
),
);
}
I have found the solution !!!
Remove building Widget
Widget buildLeading(BuildContext context) {
// TODO: implement buildLeading
return Container(
height: 0,
);
}
You need to override buildActions to put custom Input
List<Widget> buildActions(BuildContext context) {
// TODO: implement buildActions
return [
Expanded(flex: 1),
Expanded(flex: 7),
Expanded(flex: 2),
];
}
First Expanded Widget is "Back button"
Second Expanded Widget is "TextFormField", then you can override decoration: InputDecoration....
Third Expanded Widget is clearing textformfield input