Skip to main content

Flutter Theme Creation, Programmatic Way


Flutter and Dart is an excellent combination for creating the mobile app with material design with nice GUI. Its lots of widget which help the developer for creating the app UI very fast with respect to the other language. You may face some problem in starting due to comm, curly brace and semicolon but after some time you will find the way how to work with these all stuff and it becomes very easy for you. But in this article, we are not going to discuss all these. In this article, we will handle a very interesting topic on how to create a custom theme or multiple themes and let's user decide which theme to use.





Create a flutter project





So let's create a flutter project by selecting the appropriate option from the File menu in android studio or Visual Code. If you are new to Flutter and Dart you can check out our recent post to get started Creating Cross-platform app using flutter.





Once your project is created you will get the default counter app and you try running the app in the emulator just to check that everything is fine.





Create Dark and Light Theme in Flutter





So, first of all, we are going to create two themes in separate files so that we can customize later on as required.





Just right click on the lib directory of your flutter project and create a new directory/project. After that create the two file with the name of light_theme.dart and dark_theme.dart as given below.





//dark_theme.dart
import 'package:flutter/material.dart';

ThemeData darkTheme(){
return ThemeData(
brightness: Brightness.dark,
);
}




//light_theme.dart
import 'package:flutter/material.dart';

ThemeData lightTheme(){
return ThemeData(
brightness: Brightness.light,
);
}




Create a Theme Controller





Next, we need a controller which will provide the selected theme to our widget. So we are creating a file with the name of theme_controller.dart inside the theme directory.





Create a Theme Type Enum class





First of all, we will create a Theme type enum class inside the theme_controller.dart file like below.





class ThemeTypeEnum{
static const Light=ThemeTypeEnum("light");
static const Dark=ThemeTypeEnum("dark");

static const allType=[Light,Dark];
final String _themeKey;

const ThemeTypeEnum(this._themeKey);
String get themeKey => _themeKey;

static fromThemeKey(String themeKey){
return allType.firstWhere((t) => t._themeKey==themeKey);
}
}




Create Provider of the theme





We need a controller which will return the ThemeData of Light and Dark theme. So Let's create it like given below in the theme_controller.dart file.





ThemeData themeProvider(BuildContext context,ThemeTypeEnum theme){
if(theme==ThemeTypeEnum.Dark) return darkTheme();
else return lightTheme();
}




If you check the constructor of theme Provider function, it takes two input context and ThemeTypeEnum.





In this demo, we only use the theme type demo but context is useful when we need to save the user theme choice into the shared preference, so that respective theme can be loaded at startup based on the shared preference value stored in the user device.





Create Setting using Flutter PopupMenuButton





Now, we need to provide an interface to the user from where the user can select the theme. So we are creating the setting button in the app bar and will provide the option to select the dark and light theme.





So let's create the setting using the flutter PopupMenuButton. First of all, we will create a class with the menu option to store the value of the setting item.





class MenuOption {
const MenuOption({this.title, this.icon,this.theme});
final String title;
final IconData icon;
final ThemeTypeEnum theme;
}




Now, Create the List of Menu Option Item as constant as like below.





const List<MenuOption> choices = const <MenuOption>[
const MenuOption(title: 'Dark Theme', icon: Icons.sentiment_neutral,theme: ThemeTypeEnum.Dark),
const MenuOption(title: 'Light Theme', icon: Icons.sentiment_very_satisfied,theme: ThemeTypeEnum.Light),
];




Now, time to add these menu items to our app bar.





appBar: AppBar(

title: Text(widget.title),
actions: <Widget>[

PopupMenuButton(
elevation: 3.2,
onCanceled: ()=>{},
onSelected: _select,
itemBuilder: (BuildContext context)
{

return choices.map((MenuOption choice) {
return PopupMenuItem<MenuOption>(
value: choice,
child: Text(choice.title),
);
}).toList();
},

),
],
),




If you check the above code there is one point to note is onSelected attribute of PopMenuButton.





So let you know that this is a method which will assign the user selected theme to theme controller using the theme controller will provide the respective theme to our application.





 MenuOption _selectedMenu=choices[0]; //these will store the selected theme

void _select(MenuOption choice) {
setState(() {
_selectedMenu = choice;
});
}




Hook the Theme with your root flutter layout





So we are almost done the implementation part of the Flutter Theme Creation, Programmatic Way. We just need to hook our theme controller in the root view of our app. So let 's do this. To apply the theme based on the user input we need to wrap our root view with theme widget and pass our controller as data(themeProvide).





Theme(
data: themeProvider(context,_selectedMenu.theme),
child: Scaffold(
-----
-----
),
);




Test our Flutter Theme





There are some other items as well added into the body part fo Scaffold like Button, text and the floating button that you can see in the below Screenshots.





Flutter Programmatic Theme Management




Full Code of this Flutter Theme Demo App





//dark_theme.dart
import 'package:flutter/material.dart';

ThemeData darkTheme(){
return ThemeData(
brightness: Brightness.dark,
);
}




//light_theme.dart
import 'package:flutter/material.dart';

ThemeData lightTheme(){
return ThemeData(
brightness: Brightness.light,
);
}




//theme_controller.dart
import 'package:custom_theme_demo/theme/dark_theme.dart';
import 'package:flutter/material.dart';

import 'light_theme.dart';
class ThemeTypeEnum{
static const Light=ThemeTypeEnum("light");
static const Dark=ThemeTypeEnum("dark");

static const allType=[Light,Dark];
final String _themeKey;

const ThemeTypeEnum(this._themeKey);
String get themeKey => _themeKey;

static fromThemeKey(String themeKey){
return allType.firstWhere((t) => t._themeKey==themeKey);
}
}

ThemeData themeProvider(BuildContext context,ThemeTypeEnum theme){
if(theme==ThemeTypeEnum.Dark) return darkTheme();
else return lightTheme();
}




//main.dart
import 'package:flutter/material.dart';

import 'theme/theme_controller.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Programatic Theme Creation Demo'),
);
}
}

class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}

class MenuOption {
const MenuOption({this.title, this.icon,this.theme});
final String title;
final IconData icon;
final ThemeTypeEnum theme;
}

const List<MenuOption> choices = const <MenuOption>[
const MenuOption(title: 'Dark Theme', icon: Icons.sentiment_neutral,theme: ThemeTypeEnum.Dark),
const MenuOption(title: 'Light Theme', icon: Icons.sentiment_very_satisfied,theme: ThemeTypeEnum.Light),
];

class _MyHomePageState extends State<MyHomePage> {
MenuOption _selectedMenu=choices[0];
void _select(MenuOption choice) {
setState(() {
_selectedMenu = choice;
});
}
@override
Widget build(BuildContext context) {

return Theme(
data: themeProvider(context,_selectedMenu.theme),
child: Scaffold(

appBar: AppBar(

title: Text(widget.title),
actions: <Widget>[

PopupMenuButton(
elevation: 3.2,
onCanceled: ()=>{},
onSelected: _select,
itemBuilder: (BuildContext context)
{

return choices.map((MenuOption choice) {
return PopupMenuItem<MenuOption>(
value: choice,
child: Text(choice.title),
);
}).toList();
},

),
],
),
body: Center(

child: Column(

mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Selected Theme ',style: TextStyle(fontSize: 24),
),
RaisedButton(
child: Text(" ${_selectedMenu.title}"),
onPressed: (){

},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){},
tooltip: 'Increment',
child: Icon(Icons.add),
),
),
);
}

}




Wrapping up





So, we have implemented the theme management in Flutter. Here in this demo, we have just given basic theme which provides the material design default dark and light theme. But there are lots of option and item which can be modified to fit your specific need, form text, button style to app bar and many more. You can explore it further and let us know by commenting below in case of any query from your side.





Reference










Comments

  1. If you're one of the millions the shadow fight 4 who have never heard of emulation hacking, get a load of this! I give you my guide to emulation hacking.

    ReplyDelete
  2. Hello, Everybody In this Session Providing You That How to Install Cartoons HD App for Blackberry Phones. CartoonHD App works on This Device Which Is Support Operating System or app like swordigo mod apk god mode. In before Lectures, I Am Share You That You can Easily download And Install Cartoons HD APK on your Laptop and it Apps Runs very easy and well on Android Smartphone.

    ReplyDelete
  3. Thanks for your post. It's very helpful post for us. You can also visit Flutter routing for more Victor Steel related information. I would like to thanks for sharing this article here.

    ReplyDelete
  4. Well ideas to keep everything sustainable. I would like to try this theme on my riding blog. Thank You

    ReplyDelete
  5. I appreciate you sharing this useful information. I hope a large number of people learn about this and find it useful. And kindly keep updating in this manner.


    ReplyDelete
  6. Your course stands out regarding clarity, depth, and practical examples.
    please keep posting

    ReplyDelete
  7. I appreciate the depth of your insights and the engaging writing style. Looking forward to more enriching post
    /a<

    ReplyDelete

Post a Comment

Popular posts from this blog

Flutter How to Start Android Activity from Flutter View

Flutter and Dart is an excellent combination for creating the UI, but for accessing the platform-specific service we need to open platform-specific activity. So lets in this article we will explore how to start an android activity and access the service from Flutter View. Create a Project for this Android Activity Flutter View Demo Create a Project From File menu select the New Flutter Project Enter the project name Select the AndroidX support and click on next After the above, we step click on Finish We will have the following project structure created. Create the Second Activity in Android Just go to the android folder and open it in separate windows. We will have the following project structure. Create the Activity Just right-click on the Kotlin folder and create a blank activity from the menu. If you create the activity then you may be required to upgrade the Gradle and do some import. So Just click on update and wait for the project s

Kotlin Parcelable Array Objects Send To Activity

We know that IPC (Inter Process Communication) between the activity is an extremely important part of any application development. We often required that we need to send some data to other activity. For example, we may be required to send an array of data, data could be an Integer, String, Long, Double, Float or any other custom data objects. So, In this example, we are going to learn how to implement the Kotlin Parcelable Array object to send the data from one activity to second activity. What is Parcel? The parcel class is designed as a high-performance IPC transport. A Parcel can contain both flattened data that will be unflattened on the other side of the IPC, and references to live IBinde r objects that will result in the other side receiving a proxy IBinder connected with the original IBinder in the Parcel. Create Kotlin Parcelable Array Objects Parcelable is API for placing the arbitrary objects into the Parcel. In Actual in android app development, Parcelable is an interface

Create Custom EditText View in Android

We use the EditText for taking the input from the user and use it at several places in our project. We required to do lots of customization for each time and there are lots of redundant code we write. Writing and managing these redundant codes is very difficult for example if we want to change the look and feel of the view them we need to modify it at each place where our EditText is getting used. So to avoid these kinds of the problem we can create our own Custom EditText View by just. The EditText view is just an extension of the TextView with lots of editing option and properties that required for the user input. How To Create Custom EditText View For creating the Custom EditText we need to extend the AppCompatEditText and override all three constructors of the view as given below. import android.content.Context; import android.graphics.Typeface; import android.support.annotation.Nullable; import android.support.v7.widget.AppCompatEditText; import android.util.AttributeSet; public