Flutterexperts

Empowering Vision with FlutterExperts' Expertise
Switch Theme Using Bloc With Cubit In Flutter

In this article, we will explore the Switch Theme Using Bloc With Cubit In Flutter. We will see how to implement a demo program. How to switch theme using bloc with cubit the flutter_bloc package in your flutter applications.

For Flutter Bloc:

flutter_bloc | Flutter package
Flutter Widgets that make it easy to implement the BLoC (Business Logic Component) design pattern. Built to be used…pub.dev

For Equatable:

equatable | Dart package
A Dart package that helps to implement value based equality without needing to explicitly override == and hashCode.pub.dev

For Shared Preferences:

shared_preferences | Flutter package
Flutter plugin for reading and writing simple key-value pairs. Wraps NSUserDefaults on iOS and SharedPreferences on…pub.dev

If you’re looking for the best Flutter app development company for your mobile application then feel free to contact us at — support@flutterdevs.com.


Table Of Contents::

Introduction

Implementation

Code Implement

Conclusion



Introduction:

Bloc guarantees that the application generally opens with the client’s picked theme. Rather than utilizing standard Bloc classes, we can accomplish the ideal functionality by utilizing cubits which makes the implementation a lot more straightforward.

The below demo video shows how to switch theme using bloc with cubit in a flutter and shows how a switch theme will work using the flutter_bloc package and equatable package in your flutter applications. We will show a user switch the toggle button then the theme will be changed from the light mode to dark mode/vice versa and also the theme was persistent. It will be shown on your device.

Demo Module :


Implementation:

Step 1: Add the dependencies

Add dependencies to pubspec — yaml file.

dependencies:
flutter:
sdk: flutter
equatable: ^2.0.5
flutter_bloc: ^8.1.6
shared_preferences: ^2.2.3

Step 2: Import

import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:shared_preferences/shared_preferences.dart';

Step 3: Run flutter packages get in the root directory of your app.

How to implement code in dart file :

You need to implement it in your code respectively:

Create a new dart file called _share_pref.dart inside the lib folder.

Rather than getting to the SharedPreferences straightforwardly inside our ThemeRepository, I prescribe utilizing a SharedPreferencesController to make it simpler to deal with all your SharedPreferences keys.

import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:shared_preferences/shared_preferences.dart';

class _SharedPreferencesKeys {
static const String isDarkTheme = 'isDarkTheme';
}

class SharedPreferencesController {
static late SharedPreferences _preferences;

static Future init() async =>
_preferences = await SharedPreferences.getInstance();

static bool get isDarkTheme =>
_preferences.getBool(_SharedPreferencesKeys.isDarkTheme) ??
SchedulerBinding.instance.platformDispatcher.platformBrightness ==
Brightness.dark;

static Future<void> setIsDarkTheme({required bool isDarkTheme}) async =>
_preferences.setBool(_SharedPreferencesKeys.isDarkTheme, isDarkTheme);
}

Create a new dart file called theme_repo.dart inside the lib folder.

Inside the ThemeRepository class we will have two functions. One function will be responsible for getTheme and the other function will be responsible for setTheme.

In the code snippet, we created a ThemeRepository class. Inside this class, we have the getTheme and setTheme functions to utilize the functions of the SharedPreferencesController class.

import 'package:flutter_switch_theme_demo/repositories/share_pref.dart';

class ThemeRepository {
bool getTheme() => SharedPreferencesController.isDarkTheme;

Future<void> setTheme({required bool isDarkTheme}) async =>
SharedPreferencesController.setIsDarkTheme(isDarkTheme: isDarkTheme);
}

Create a new dart file called theme_state.dart inside the lib folder.

To guarantee that our application knows about the ongoing theme we made the ThemeState class that will be utilized in the forthcoming ThemeCubit class.

In the above code, we made a ThemeState class that expands the Equatable class. The expansion is expected to guarantee that we can contrast cases of the ThemeState class and each other to decide on changes. The ThemeState class has one attribute themeMode that will be utilized to store the ongoing theme.

part of 'theme_cubit.dart';

class ThemeState extends Equatable {
const ThemeState({this.themeMode = ThemeMode.light});

final ThemeMode themeMode;

ThemeState copyWith({ThemeMode? themeMode}) => ThemeState(
themeMode: themeMode ?? this.themeMode,
);

@override
List<Object?> get props => [themeMode];
}

Likewise, notice that the theme_state.dart file is a piece of the theme_cubit.dart file. In this manner, every one of the imports is finished inside the theme_cubit.dart file.

Create a new dart file called theme_cubit.dart inside the lib folder.

The ThemeCubit class will contain two capabilities that we will call inside our widgets to either get the current theme or switch the theme.

In the below code, we make the ThemeCubit class which broadens the Cubit class with a type of ThemeState. The ThemeCubit class has a constructor that takes the instance of the ThemeRepository class. Other than that we have a _isDarkTheme variable that is utilized to monitor the ongoing theme and we have two functions.

import 'dart:async';

import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_switch_theme_demo/repositories/theme_repo.dart';

part 'theme_state.dart';

class ThemeCubit extends Cubit<ThemeState> {
ThemeCubit({
required ThemeRepository themeRepository,
}) : _themeRepository = themeRepository,
super(const ThemeState());

final ThemeRepository _themeRepository;
static late bool _isDarkTheme;

void getCurrentTheme() {
final isDarkTheme = _themeRepository.getTheme();
_isDarkTheme = isDarkTheme;
emit(state.copyWith(themeMode: isDarkTheme ? ThemeMode.dark : ThemeMode.light));
}

Future<void> switchTheme() async {
_isDarkTheme = !_isDarkTheme;
await _themeRepository.setTheme(isDarkTheme: _isDarkTheme);
emit(state.copyWith(themeMode: _isDarkTheme ? ThemeMode.dark : ThemeMode.light));
}
}

The primary function is the getCurrentTheme function that calls the getTheme function from the ThemeRepository class. Given the result of the getTheme function we set the _isDarkTheme variable and update the state with the ongoing ThemeMode utilizing the emit function.

The second function switchTheme is utilized to switch between ThemeMode.light and ThemeMode.dark. Given the value of the _isDarkTheme variable, we update the actual variable and update the state with the refreshed ThemeMode.

Create a new dart file called main.dart inside the lib folder.

In the main.dat file, In the beneath code, we changed the main function to nonconcurrent. Inside the main function, we start by calling the WidgetsFlutterBinding.ensureInitialized capability to guarantee that the bindings are initialized. Solely after the bindings are introduced we can get to the SharedPreferences occurrence which is finished by calling the init capability of the SharedPreferencesController class.

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_switch_theme_demo/cubits/theme_cubit.dart';
import 'package:flutter_switch_theme_demo/repositories/share_pref.dart';
import 'package:flutter_switch_theme_demo/repositories/theme_repo.dart';
import 'package:flutter_switch_theme_demo/splash_screen.dart';

Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await SharedPreferencesController.init();
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({
super.key,
});

@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const Splash());
}
}

class HomePage extends StatefulWidget {
const HomePage({
required ThemeRepository themeRepository,
super.key,
}) : _themeRepository = themeRepository;

final ThemeRepository _themeRepository;

@override
State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return MultiRepositoryProvider(
providers: [
RepositoryProvider<ThemeRepository>(
create: (context) => widget._themeRepository,
),
],
child: MultiBlocProvider(
providers: [
BlocProvider(
create: (BuildContext context) =>
ThemeCubit(themeRepository: widget._themeRepository)
..getCurrentTheme())
],
child: BlocBuilder<ThemeCubit, ThemeState>(
builder: (BuildContext context, ThemeState state) => MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData.light(useMaterial3: true),
darkTheme: ThemeData.dark(useMaterial3: true),
themeMode: state.themeMode,
home: Scaffold(
appBar: AppBar(
title: const Text("Flutter Theme Switch Demo"),
backgroundColor: Colors.cyan,
actions: [
Switch(
value: state.themeMode == ThemeMode.dark,
onChanged: (_) async =>
context.read<ThemeCubit>().switchTheme(),
),
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: Image.asset(
"assets/logo.png",
height: MediaQuery.of(context).size.height * 0.14,
))
],
),
),
),
),
),
);
}
}

In a similar file, we will make a HomePage class. The HomePage widget requires a case of the ThemeRepository class. This case can be passed inside its constructor. Later on, the instance of the ThemeRepository class is utilized in the MultiRepositoryProvider and MultiBlocProvider class. Both provider classes are important to guarantee that we can around the globally access occurrences of ThemeRepository and ThemeCubit all through our application.

Additionally, to get the underlying subject we call the getCurrentTheme function quickly utilizing the cascade notation on the ThemeCubit case. To guarantee that our MaterialApp widget knows about the ongoing theme we enveloped the widget with a BlocBuilder widget. The BlocBuilder widget is of type ThemeCubit and ThemeState thusly we approach the ThemeState inside our MaterialApp widget.

Inside our MaterialApp widget, we characterize both the light theme utilizing the theme property and the dark theme utilizing the darkTheme attribute. We likewise set the themeMode trait to state.themeMode to guarantee that it is generally equivalent to the themeMode of the ThemeState example produced by the ThemeCubit.

When we run the application, we ought to get the screen’s output like the underneath screen capture.


Conclusion:

In the article, I have explained the Switch Theme Using Bloc With Cubit in a flutter; you can modify this code according to your choice. This was a small introduction to Switch Theme Using Bloc With Cubit On User Interaction from my side, and it’s working using Flutter.

I hope this blog will provide you with sufficient information on Trying up the Switch Theme Using Bloc With Cubit in your Flutter projects. We will show you what the Introduction is?. Make a demo program for working on Switch Theme Using Bloc with Cubit the flutter_bloc package and the equatable package in your flutter applications. So please try it.

❤ ❤ Thanks for reading this article ❤❤

If I got something wrong? Let me know in the comments. I would love to improve.

Clap 👏 If this article helps you.


Feel free to connect with us:
And read more articles from FlutterDevs.com.

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire a Flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter-related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences.


Leave comment

Your email address will not be published. Required fields are marked with *.