I'm trying to change app theme using bloc implementation. But, when the state changed, builder doesnt recall.
part of 'theme_bloc.dart';
abstract class ThemeEvent extends Equatable {
// Passing class fields in a list to the Equatable super class
ThemeEvent([List props = const <dynamic>[]]);
@override
List<Object> get props => [];
}
class ThemeChanged extends ThemeEvent {
final AppTheme theme;
ThemeChanged({
@required this.theme,
}) : super([theme]);
}
```part of 'theme_bloc.dart';
class ThemeState extends Equatable {
final ThemeData themeData;
ThemeState({
@required this.themeData,
});
@override
List
### theme_bloc.dart
```import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:musica_tl/helper/theme_helper.dart';
part 'theme_event.dart';
part 'theme_state.dart';
class ThemeBloc extends Bloc<ThemeEvent, ThemeState> {
@override
ThemeState get initialState =>
ThemeState(themeData: ThemeHelper.appThemeData[AppTheme.BlueDark]);
@override
Stream<ThemeState> mapEventToState(ThemeEvent event) async* {
if (event is ThemeChanged) {
yield ThemeState(themeData: ThemeHelper.appThemeData[event.theme]);
}
}
}
```enum AppTheme {
GreenLight,
GreenDark,
BlueLight,
BlueDark,
}
class ThemeHelper {
static final appThemeData = {
AppTheme.GreenLight: ThemeData(
brightness: Brightness.light,
primaryColor: Colors.green,
),
AppTheme.GreenDark: ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.green[700],
),
AppTheme.BlueLight: ThemeData(
brightness: Brightness.light,
primaryColor: Colors.blue,
),
AppTheme.BlueDark: ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.blue[700],
),
};
}
### main.dart:
```import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:musica_tl/screens/onboarding/onboarding_screen.dart';
import 'app/bloc/theme/bloc/theme_bloc.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => ThemeBloc(),
child: BlocBuilder<ThemeBloc, ThemeState>(
builder: _buildWithTheme,
),
);
}
Widget _buildWithTheme(BuildContext context, ThemeState state) {
return MaterialApp(
title: 'Musica.tl',
home: OnBoardingScreen(),
theme: state.themeData,
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:musica_tl/app/bloc/theme/bloc/theme_bloc.dart';
import 'package:musica_tl/helper/theme_helper.dart';
class OnBoardingScreen extends StatelessWidget {
const OnBoardingScreen({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('OnBoarding'),
),
body: ListView.builder(
padding: EdgeInsets.all(8),
itemCount: AppTheme.values.length,
itemBuilder: (context, index) {
// Enums expose their values as a list - perfect for ListView
// Store the theme for the current ListView item
final itemAppTheme = AppTheme.values[index];
return Card(
// Style the cards with the to-be-selected theme colors
color: ThemeHelper.appThemeData[itemAppTheme].primaryColor,
child: ListTile(
title: Text(
itemAppTheme.toString(),
// To show light text with the dark variants...
style: ThemeHelper.appThemeData[itemAppTheme].textTheme.body1,
),
onTap: () {
// This will make the Bloc output a new ThemeState,
// which will rebuild the UI because of the BlocBuilder in main.dart
BlocProvider.of<ThemeBloc>(context).add(ThemeChanged(theme: itemAppTheme));
},
),
);
},
),
);
}
}
I've checked if the state has changed but i have no idea why the blocBuilder doesnt recall and update the view.
Hi @ariefwijaya 馃憢
Thanks for opening an issue!
It looks like you鈥檙e not using Equatable properly which is likely causing this issue. Please make sure to override props in your state class and pass the ThemeData into the props override. I highly recommend checking out the faqs for more details.
Hope that helps 馃憤
If you鈥檙e still having trouble can you please share a link to a sample app which illustrates the issue? Thanks!
Ah I see, now the problem solved and worked well!.
it happened because I dont know about the new syntax (prefer to use props instead of super).
In theme_state I forgot to pass the variable to the props, it should be like this:
@override
List<Object> get props => [themeData];
instead of
@override
List<Object> get props => [];
Before, I was trying to implement super in the constructor to pass the variable and its give me error like this:
Too many positional arguments: 0 expected, but 1 found.
Try removing the extra arguments.dart(extra_positional_arguments)
Thank you 馃憤
Most helpful comment
Ah I see, now the problem solved and worked well!.
it happened because I dont know about the new syntax (prefer to use props instead of super).
In theme_state I forgot to pass the variable to the props, it should be like this:
instead of
Before, I was trying to implement super in the constructor to pass the variable and its give me error like this:
Thank you 馃憤