I have a dropDownButton where i select the theme for the entire app. I have tried two ways of actually trying to fix this. First one was using the commented line "Provider.of(context).toggleTheme();" in the "setState". Had to make the "listen" option "false" as advised in another thread but it was not working. And the second one was to just call the "toggleTheme()" inside the "Themes.dart" in order to notify listeners that way. What would be a correct implementation for a Dropdownbutton like this.
MainScreen.dart
import 'package:flutter/material.dart';
import 'package:thisismylastattempt/Misc/Themes.dart';
import 'package:provider/provider.dart';
class MainScreen extends StatefulWidget {
static const id = "main_screen";
#override
_MainScreenState createState() => _MainScreenState();
}
class ThemeOptions{
final Color themeColor;
final ThemeType enumTheme;
ThemeOptions({this.themeColor, this.enumTheme});
void callParentTheme(){
ThemeModel().changeEnumValue(enumTheme);
}
}
class _MainScreenState extends State<MainScreen> {
List<ThemeOptions> themes = [
ThemeOptions(themeColor: Colors.teal, enumTheme: ThemeType.Teal),
ThemeOptions(themeColor: Colors.green, enumTheme: ThemeType.Green),
ThemeOptions(themeColor: Colors.lightGreen, enumTheme: ThemeType.LightGreen),
];
ThemeOptions dropdownValue;
#override
void initState() {
dropdownValue = themes[0];
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('MainScreen'),
),
body: Column(
children: <Widget>[
Container(
child: DropdownButton<ThemeOptions>(
value: dropdownValue,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(
color: Colors.deepPurple
),
underline: Container(
height: 0.0,
color: Colors.deepPurpleAccent,
),
onChanged: (ThemeOptions newValue) {
setState(() {
dropdownValue = newValue;
dropdownValue.callParentTheme();
print(newValue.themeColor);
//Provider.of<ThemeModel>(context).toggleTheme();
});
},
items: themes.map((ThemeOptions colorThemeInstance) {
return DropdownMenuItem<ThemeOptions>(
value: colorThemeInstance,
child: CircleAvatar(
backgroundColor: colorThemeInstance.themeColor,
),
);
})
.toList(),
),
),
SizedBox(height: 20.0,),
],
),
);
}
}
Themes.dart
import 'package:flutter/material.dart';
enum ThemeType {Teal, Green, LightGreen}
ThemeData tealTheme = ThemeData.light().copyWith(
primaryColor: Colors.teal.shade700,
appBarTheme: AppBarTheme(
color: Colors.teal.shade700,
),
);
ThemeData greenTheme = ThemeData.light().copyWith(
primaryColor: Colors.green.shade700,
appBarTheme: AppBarTheme(
color: Colors.green.shade700,
),
);
ThemeData lightGreenTheme = ThemeData.light().copyWith(
primaryColor: Colors.lightGreen.shade700,
appBarTheme: AppBarTheme(
color: Colors.lightGreen.shade700,
),
);
class ThemeModel extends ChangeNotifier {
ThemeData currentTheme = tealTheme;
ThemeType _themeType = ThemeType.Teal;
toggleTheme() {
if (_themeType == ThemeType.Teal) {
currentTheme = tealTheme;
_themeType = ThemeType.Teal;
print('teal');
notifyListeners();
}
if (_themeType == ThemeType.Green) {
currentTheme = greenTheme;
_themeType = ThemeType.Green;
print('green');
notifyListeners();
}
if (_themeType == ThemeType.LightGreen) {
currentTheme = lightGreenTheme;
_themeType = ThemeType.LightGreen;
print('lightGreen');
notifyListeners();
}
}
ThemeType getEnumValue(){
return _themeType;
}
void changeEnumValue(ThemeType newThemeType){
_themeType = newThemeType;
toggleTheme();
}
}
main.dart
void main() => runApp(ChangeNotifierProvider<ThemeModel>(
create: (BuildContext context) => ThemeModel(), child: MyApp()));
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamProvider<User>.value(
value: AuthService().user,
child: MaterialApp(
theme: Provider.of<ThemeModel>(context).currentTheme,
title: 'Flutter Demo',
initialRoute: MainScreen.id,
routes: {
Wrapper.id: (context) => Wrapper(),
LoginPage.id: (context) => LoginPage(),
Registration.id: (context) => Registration(),
MainScreen.id: (context) => MainScreen(),
SwitchAuthenticationState.id: (context) =>
SwitchAuthenticationState(),
},
),
);
}
}
I managed to make it work by calling the changeEnumValue from the Provider in the callParentTheme of your ThemeOptionsclass :
class ThemeOptions {
final Color themeColor;
final ThemeType enumTheme;
ThemeOptions({this.themeColor, this.enumTheme});
// void callParentTheme() {
// ThemeModel().changeEnumValue(enumTheme);
void callParentTheme(context) {
Provider.of<ThemeModel>(context, listen: false).changeEnumValue(enumTheme);
}
call the method with the context in your DropDown onChanged method :
onChanged: (ThemeOptions newValue) {
setState(() {
dropdownValue = newValue;
dropdownValue.callParentTheme(context);
print(newValue.themeColor);
});
},
Hope It's help
Related
I am in the learning stage of flutter and facing errors. I am watching a course on Udemy. I am trying to build a Personal Expense Tracker. It's a fundamental project but, as I already told I am currently learning and am facing an error. Any help would be appreciated.
This is the code of my main.dart file:
import 'package:flutter/material.dart';
import './widgets/transaction_list.dart';
import './widgets/new_transactions.dart';
import './widgets/chart.dart';
import './models/transaction.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final ThemeData theme = ThemeData(
primarySwatch: Colors.primaries[1],
errorColor: Colors.red,
fontFamily: 'Quicksand',
);
return MaterialApp(
title: 'Expense Planner',
theme: theme.copyWith(
colorScheme: theme.colorScheme.copyWith(secondary: Colors.amber),
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<Transaction> _userTransactions = [];
List<Transaction> get _recentTransactions {
return _userTransactions.where((tx) {
return tx.date.isAfter(
DateTime.now().subtract(
Duration(days: 7),
),
);
}).toList();
}
void _addNewTransaction(
String txTitle, double txAmount, DateTime chosenDate) {
final newTx = Transaction(
title: txTitle,
amount: txAmount,
date: chosenDate,
id: DateTime.now().toString(),
);
setState(() {
_userTransactions.add(newTx);
});
}
void _startAddNewTransaction(BuildContext ctx) {
showModalBottomSheet(
context: ctx,
builder: (_) {
return GestureDetector(
onTap: () {},
child: NewTransaction(_addNewTransaction),
behavior: HitTestBehavior.opaque,
);
},
);
}
void _deleteTransaction(String id) {
setState(() {
_userTransactions.removeWhere((tx) => tx.id == id);
{
;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Expense Planner',
style: TextStyle(
fontFamily: 'OpenSans',
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
onPressed: () => _startAddNewTransaction(context),
),
],
),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Chart(_recentTransactions),
TransactionList(_userTransactions, _deleteTransaction),
],
),
),
floatingActionButtonLocation:
FloatingActionButtonLocation.centerFloat,
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => _startAddNewTransaction(context),
),
);
}
});
}
}
There's some error in the _MyHomePageState class. it shows the following error
Missing concrete implementation of 'State.build'.
Try implementing the missing method, or make the class abstract.
However when I try to make the _MyHomePageState class abstract it shows the following:
Abstract classes can't be instantiated.
Try creating an instance of a concrete subtype.
Thanks & Regards,
Harshit Chitkara
I think 'home: MyHomePage(),' is waiting for a Widget. You have to build a Widget arround the List. After that you probably need a Scaffold inside the Widget.
#override
Widget build(BuildContext context) {
return Scaffold(
child: List<Transaction> get _recentTransactions {
return _userTransactions.where((tx) {
return tx.date.isAfter(
DateTime.now().subtract(
Duration(days: 7),
),
);
}).toList();
}
);
}
This should fix the current problem, but you can't have a return inside a return.
I am trying to build a speech to text app in flutter(using dart) . I get this error when I run however there are no issues with the code as far as I can tell. I've pasted the entire code below.
The error I am getting is when the onListen Handler is called. It points to an error in the speech to text package which isn't even my code. pls see image and error below.
TypeError: result[$item] is not a function
at speech_to_text_web.SpeechToTextPlugin.new.[_onResult] (http://localhost:53227/packages/speech_to_text/speech_to_text_web.dart.lib.js:143:36)
at http://localhost:53227/packages/speech_to_text/speech_to_text_web.dart.lib.js:97:98
at Object._checkAndCall (http://localhost:53227/dart_sdk.js:5242:16)
at Object.dcall (http://localhost:53227/dart_sdk.js:5247:17)
at SpeechRecognition.<anonymous> (http://localhost:53227/dart_sdk.js:100617:100)
import 'package:flutter/material.dart';
import 'package:speech_to_text/speech_to_text.dart' as stt;
import 'package:avatar_glow/avatar_glow.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter voice',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.red,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: SpeechScreen(),
);
}
}
class SpeechScreen extends StatefulWidget {
#override
_SpeechScreenState createState() => _SpeechScreenState();
}
class _SpeechScreenState extends State<SpeechScreen> {
stt.SpeechToText _speech = stt.SpeechToText();
bool _isListening = false;
String _text = 'Press the button and start speaking';
double _confidence = 1.0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Confidence: ${(_confidence * 100.0).toStringAsFixed(1)}%'),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: AvatarGlow(
animate: _isListening,
glowColor: Theme.of(context).primaryColor,
endRadius: 75.0,
duration: const Duration(milliseconds: 2000),
repeatPauseDuration: const Duration(milliseconds: 100),
repeat: true,
child: FloatingActionButton(
onPressed: _listen,
child: Icon(_isListening ? Icons.mic : Icons.mic_none),
),
),
body: SingleChildScrollView(
reverse: true,
child: Container(
padding: const EdgeInsets.fromLTRB(30.0, 30.0, 30.0, 150.0),
child: Text(
_text,
style: const TextStyle(
fontSize: 32.0,
color: Colors.black,
fontWeight: FontWeight.w400,
),
),
),
),
);
}
void _listen() async {
if (!_isListening) {
bool available = await _speech.initialize(
onStatus: (val) => print('onStatus: $val'),
onError: (val) => print('onError: $val'),
);
if (available) {
setState(() => _isListening = true);
_speech.listen(
onResult: (val) => setState(() {
_text = val.recognizedWords;
if (val.hasConfidenceRating && val.confidence > 0) {
_confidence = val.confidence;
}
}));
}
} else {
setState(() => _isListening = false);
_speech.stop();
}
}
}
Error
So I'm trying here to get the current theme, if it's light or dark.
So I can change widget color accordingly..
However, it doesn't work, I used if statment to know when it's dark mode..
but it's always False ..
This is the code.. btw it switch between dark & light theme..
but when i try to get current theme.. even if the theme changed to dark..
the if statments always show false...
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
bool darkModeOn = MediaQuery.of(context).platformBrightness == Brightness.dark;
Color containerColor;
if (darkModeOn == true) {
containerColor = Colors.blueGrey;
print("----------------");
print("dark mode ON");
print("----------------");
} else {
containerColor = Colors.deepPurple;
print("LIGHT mode ON");
}
return Scaffold(
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
//----switch theme---
currentTheme.switchTheme();
},
label: Text(
"Switch theme",
style: TextStyle(
),
),
icon: Icon(Icons.color_lens_outlined),
),
appBar: AppBar(
title: Text("DarkXLight"),
),
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(child: Container(
color: containerColor,
),
),
Expanded(child: Container(
color: Colors.amber,
),
),
],
),
),
);
}
}
You can't switch themes like that. You will need to handle the logic in the MaterialApp otherwise
MediaQuery.of(context).platformBrightness == Brightness.dark;
will always return true/false based on what was provided to the MaterialApp.themeMode.
Here's a sample code to get started. I used ValueListenableBuilder but you can also use provider.
Full code:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
final ValueNotifier<ThemeMode> _notifier = ValueNotifier(ThemeMode.light);
#override
Widget build(BuildContext context) {
return ValueListenableBuilder<ThemeMode>(
valueListenable: _notifier,
builder: (_, mode, __) {
return MaterialApp(
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
themeMode: mode, // Decides which theme to show, light or dark.
home: Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () => _notifier.value = mode == ThemeMode.light ? ThemeMode.dark : ThemeMode.light,
child: Text('Toggle Theme'),
),
),
),
);
},
);
}
}
So, I was able to solve my problem..
I will put the code so if someone faced the same issue..
I simply, changed the way I used to switch themes. It was wrong..
However, here I'm posting the Correct way & this way solved the problem..
MAIN PAGE
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:practice_darkmode/theme_provider.dart';
import 'package:provider/provider.dart';
import 'MyHomePage.dart';
Future<void> main() async {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => ThemeProvider(),
builder: (context, _) {
final themeProvider = Provider.of<ThemeProvider>(context);
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: MyThemes.lightTheme,
darkTheme: MyThemes.darkTheme,
themeMode: themeProvider.themeMode,
home: MyHomePage(),
);
},
);
}
}
Theme Provider class
import 'package:flutter/material.dart';
//---This to switch theme from Switch button----
class ThemeProvider extends ChangeNotifier {
//-----Store the theme of our app--
ThemeMode themeMode = ThemeMode.dark;
//----If theme mode is equal to dark then we return True----
//-----isDarkMode--is the field we will use in our switch---
bool get isDarkMode => themeMode == ThemeMode.dark;
//---implement ToggleTheme function----
void toggleTheme(bool isOn) {
themeMode = isOn ? ThemeMode.dark : ThemeMode.light;
//---notify material app to update UI----
notifyListeners();
}
}
//---------------Themes settings here-----------
class MyThemes {
//-------------DARK THEME SETTINGS----
static final darkTheme = ThemeData(
scaffoldBackgroundColor: Colors.black45,
// colorScheme: ColorScheme.dark(),
);
//-------------light THEME SETTINGS----
static final lightTheme = ThemeData(
scaffoldBackgroundColor: Colors.white,
//colorScheme: ColorScheme.light(),
);
}
Change Theme button widget class ( this is to create a switch button)
import 'package:flutter/material.dart';
import 'package:practice_darkmode/theme_provider.dart';
import 'package:provider/provider.dart';
class ChangeThemeButtonWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
//----First we want to get the theme provider----
final themeProvider = Provider.of<ThemeProvider>(context);
return Switch.adaptive(
//---isDarkMode to return if its dark or not--true or false--
value: themeProvider.isDarkMode,
onChanged: (value) {
final provider = Provider.of<ThemeProvider>(context, listen: false);
provider.toggleTheme(value);
},
activeColor: themeProvider.isDarkMode ? Colors.purple : Colors.green,
);
}
}
Home Page
import 'package:flutter/material.dart';
import 'package:practice_darkmode/theme_provider.dart';
import 'package:provider/provider.dart';
import 'ChangeThemeButtonWidget.dart';
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
dynamic text;
dynamic textColor;
dynamic appBarColor;
dynamic btnColor;
dynamic appBarTextColor;
if (Provider.of<ThemeProvider>(context).themeMode == ThemeMode.dark) {
text = "IT'S DARK ";
textColor = Colors.cyanAccent;
appBarColor = Colors.black;
btnColor = Colors.deepPurple;
appBarTextColor = Colors.cyanAccent;
} else if (Provider.of<ThemeProvider>(context).themeMode == ThemeMode.light) {
text = "IT'S LIGHT ";
textColor = Colors.red;
appBarColor = Colors.red;
btnColor = Colors.red;
appBarTextColor = Colors.white;
}
return Scaffold(
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
},
label: Text(
"Switch theme",
style: TextStyle(
),
),
icon: Icon(Icons.color_lens_outlined),
backgroundColor: btnColor,
),
appBar: AppBar(
title: Text("DarkXLight", style: TextStyle(color: appBarTextColor),),
backgroundColor: appBarColor,
actions: [
ChangeThemeButtonWidget(),
],
),
body: Container(
child: Center(
child: Text(
"$text!",
style: (
TextStyle(
fontSize: 27,
color: textColor,
)
),
),
),
),
);
}
}
Below code will to change theme via Icon Button in appBar. Steps:
Create a stateful widget.
Add the following variables:
bool _iconBool = false;
IconData _iconLight = Icons.wb_sunny;
IconData _iconDark = Icons.nights_stay;
Create actions -> IconButton in the appBar as below:
appBar: AppBar(
title: Text("Simple Colregs"),
backgroundColor: Color(0xFF5B4B49).withOpacity(0.8),
actions: [
IconButton(icon: Icon(_iconBool ? _iconDark : _iconLight),
},)
],
), //AppBar
Add Below methods with Light and Dark themes and any custom preference is required:
// light Theme
ThemeData lightThemeData(BuildContext context) {
return ThemeData.light().copyWith(
primaryColor: Color(0xFF5B4B49),
colorScheme: ColorScheme.fromSwatch().copyWith(secondary: Color(0xFF24A751)));
}
// dark Theme
ThemeData darkThemeData(BuildContext context) {
return ThemeData.dark().copyWith(
primaryColor: Color(0xFFFF1D00),
colorScheme: ColorScheme.fromSwatch().copyWith(secondary: Color(0xFF24A751)));
}
Read more about ThemeData Class here.
Under IconButton, create a functionality for the button as below which will toggle the theme:
onPressed: () {
setState(() {
_iconBool = !_iconBool;
});
Finally add under Material App:
theme: _iconBool ? lightThemeData(context) : darkThemeData(context),
That's all, good to go. Hope it helps.
you can use it in initState
bool darkModeOn = brightness == Brightness.dark;
or
var brightness = MediaQuery.of(context).platformBrightness;
bool darkModeOn = brightness == Brightness.dark;
Is there a way to return Google maps marker to it's original position after dragging it to a new location? For example, onDragEnd => if (condition) => do something => else => go back to original position...
import 'package:google_maps_place_picker/google_maps_place_picker.dart';
Add This Package and then try this :
import 'package:flutter/material.dart';
import 'package:google_maps_place_picker/google_maps_place_picker.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
// Your api key storage.
import 'keys.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// Light Theme
final ThemeData lightTheme = ThemeData.light().copyWith(
// Background color of the FloatingCard
cardColor: Colors.white,
buttonTheme: ButtonThemeData(
// Select here's button color
buttonColor: Colors.black,
textTheme: ButtonTextTheme.primary,
),
);
// Dark Theme
final ThemeData darkTheme = ThemeData.dark().copyWith(
// Background color of the FloatingCard
cardColor: Colors.grey,
buttonTheme: ButtonThemeData(
// Select here's button color
buttonColor: Colors.yellow,
textTheme: ButtonTextTheme.primary,
),
);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Google Map Place Picker Demo',
theme: lightTheme,
darkTheme: darkTheme,
themeMode: ThemeMode.light,
home: HomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key key}) : super(key: key);
static final kInitialPosition = LatLng(-33.8567844, 151.213108);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
PickResult selectedPlace;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Google Map Place Picer Demo"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text("Load Google Map"),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return PlacePicker(
apiKey: APIKeys.apiKey,
initialPosition: HomePage.kInitialPosition,
useCurrentLocation: true,
selectInitialPosition: true,
//usePlaceDetailSearch: true,
onPlacePicked: (result) {
selectedPlace = result;
Navigator.of(context).pop();
setState(() {});
},
//forceSearchOnZoomChanged: true,
//automaticallyImplyAppBarLeading: false,
//autocompleteLanguage: "ko",
//region: 'au',
//selectInitialPosition: true,
// selectedPlaceWidgetBuilder: (_, selectedPlace, state, isSearchBarFocused) {
// print("state: $state, isSearchBarFocused: $isSearchBarFocused");
// return isSearchBarFocused
// ? Container()
// : FloatingCard(
// bottomPosition: 0.0, // MediaQuery.of(context) will cause rebuild. See MediaQuery document for the information.
// leftPosition: 0.0,
// rightPosition: 0.0,
// width: 500,
// borderRadius: BorderRadius.circular(12.0),
// child: state == SearchingState.Searching
// ? Center(child: CircularProgressIndicator())
// : RaisedButton(
// child: Text("Pick Here"),
// onPressed: () {
// // IMPORTANT: You MUST manage selectedPlace data yourself as using this build will not invoke onPlacePicker as
// // this will override default 'Select here' Button.
// print("do something with [selectedPlace] data");
// Navigator.of(context).pop();
// },
// ),
// );
// },
// pinBuilder: (context, state) {
// if (state == PinState.Idle) {
// return Icon(Icons.favorite_border);
// } else {
// return Icon(Icons.favorite);
// }
// },
);
},
),
);
},
),
selectedPlace == null ? Container() : Text(selectedPlace.formattedAddress ?? ""),
],
),
));
}
}
I'm really new to flutter and now I'm studying bloc pattern in flutter.
so I'm trying to implement a function which user click button (blue or green), it should change the theme color blue or green.
but the problem is I set initiaData as purple color and it just shows orange theme even user click the green or blue button.
event.dart
abstract class ChangeColorEvent {}
class ChangeToGreen extends ChangeColorEvent {}
class ChangeToBlue extends ChangeColorEvent {}
bloc.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:theme_change/bloc/colorTheme/event.dart';
class ColorThemeBloc {
var _theme =
ThemeData(brightness: Brightness.light, primaryColor: Colors.orange);
final _colorStateController = StreamController();
StreamSink get _inTheme => _colorStateController.sink;
Stream get theme => _colorStateController.stream;
final _colorEventController = StreamController<ChangeColorEvent>();
Sink<ChangeColorEvent> get changeColorEventSink => _colorEventController.sink;
ColorThemeBloc() {
//wherever there's a new event we want to map it to a new state
_colorEventController.stream.listen(_mapEventToState);
}
void _mapEventToState(ChangeColorEvent event) {
print(event);
if (event is ChangeToGreen)
_theme =
ThemeData(brightness: Brightness.light, primaryColor: Colors.red);
else
_theme =
ThemeData(brightness: Brightness.light, primaryColor: Colors.pink);
_inTheme.add(_theme);
print(_theme);
}
void dispose() {
_colorEventController.close();
_colorStateController.close();
}
}
themeChange.dart
import 'package:flutter/material.dart';
import 'package:theme_change/bloc/colorTheme/bloc.dart';
import 'package:theme_change/bloc/colorTheme/event.dart';
class ThemeChange extends StatelessWidget {
// final bool isDarkThemeEnabled;
// final ThemeBloc bloc;
final _bloc = ColorThemeBloc();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
RaisedButton(
onPressed: () {
Navigator.pop(context);
},
color: Colors.grey,
child: Text('GO BACK'),
),
// ListTile(
// title: Text("Dark Theme"),
// trailing: Switch(
// value: isDarkThemeEnabled, onChanged: bloc.changeTheTheme),
// ),
RaisedButton(
onPressed: () => _bloc.changeColorEventSink.add(ChangeToBlue()),
color: Colors.blue,
child: Text('blue'),
),
RaisedButton(
onPressed: () => _bloc.changeColorEventSink.add(ChangeToGreen()),
color: Colors.green,
child: Text('Green'),
)
],
),
),
);
}
}
main.dart
class MyApp extends StatelessWidget {
final _bloc = ColorThemeBloc();
#override
Widget build(BuildContext context) {
return StreamBuilder(
initialData: ThemeData(
brightness: Brightness.light, primaryColor: Colors.purple),
stream: _bloc.theme,
builder: (context, snapshot) {
return MaterialApp(
theme: snapshot.data,
title: 'Flutter Demo',
home: DemoScreen(),
);
});
}
}
You haven't extended Equatable on Abstract Event, which is used to identify if event Object is same or not. change your event class to following :
abstract class ChangeColorEvent extends Equatable{}
class ChangeToGreen extends ChangeColorEvent {
// Add props, if you want to return data, else
}
class ChangeToBlue extends ChangeColorEvent {
// Add props, if you want to return data, else
}