The enum is the short form of enumerated type. Therefore, enum is just like any other data type.
Moreover, enum is a set of named values that we call elements or enumerators.
As a result, we can use enum “Type” value where we want them. And, enumerator names act as constant values.
In Natural Language the word enumeration means an action of mentioning names one by one.
In any Dart and Flutter, we write enum the following way.
enum Names {
John,
Json,
}
Now, we can access the enumerator values as follows.
Names.John
Names.Json
However, the question remains, why we need enum?
We have seen static constant class variables before. Does it not look same?
The answer is no. We cannot do that.
The enums are useful when the method parameter can only take one value out of a small set of possible values.
Suppose we have two types of robots. One robot thinks. And the other robot works.
Consequently, we can create two types of Robots.
void main() {
Robot worker = Robot(robotType: RobotType.worker);
Robot thinker = Robot(robotType: RobotType.thinker);
if(worker.robotType == RobotType.worker) {
print('My robot has just cleaned the room.');
} else {
print('My robot has not done anything.');
} // My robot has just cleaned the room.
if(thinker.robotType == RobotType.thinker) {
print('My robot has just solved a Mathematical problem.');
} else {
print('My robot has not done anything.');
} // My robot has just solved a Mathematical problem.
}
class Robot {
RobotType? robotType;
Robot({this.robotType});
}
enum RobotType {
worker,
thinker,
}
The above code does make sense. Why? Because we wanted to create two types of Robot.
On the contrary, when we use static constant class variables instead of enums, the perspective completely changes.
Not only that, it no longer remains meaningful as before.
Consider the code below where we use static constant class variables.
void main() {
Robot worker = Robot(name: RobotType.worker);
Robot thinker = Robot(name: RobotType.thinker);
if(worker.name == RobotType.worker) {
print('My robot has just cleaned the room.');
} else {
print('My robot has not done anything.');
} // My robot has just cleaned the room.
if(thinker.name == RobotType.thinker) {
print('My robot has just solved a Mathematical problem.');
} else {
print('My robot has not done anything.');
} // My robot has just solved a Mathematical problem.
}
class Robot {
String? name;
Robot({this.name});
}
class RobotType {
static const worker = 'Worker';
static const thinker = 'Thinker';
}
Although it serves our purpose, yet it is not meaningful as before.
Ask yourself one simple question. From name can you guess the type of a person?
But when you precisely define the type, you can predict the output. That is also true when we apply the same concept.
Let us see how enum changes the code in Flutter.
How to use enum in Flutter?
It will be clearer, if we see the images firstly. Let us explain what we are going to achieve.
We have created two Container Widgets of the same color. Yellow.
![Why we need enum in Flutter_ first example](https://i0.wp.com/sanjibsinha.com/wp-content/uploads/2022/03/Why-we-need-enum-in-Flutter_-first-example-.jpg?ssl=1)
As we press the first Container, the color changes to red. However, the second container remains yellow.
![Why we need enum in Flutter_ second example](https://i0.wp.com/sanjibsinha.com/wp-content/uploads/2022/03/Why-we-need-enum-in-Flutter_-second-example-.jpg?ssl=1)
Next, when we press the second Container, it becomes red this time. But the first becomes yellow again.
We can achieve this state change with the help of a Stateful Widget. In addition we need setState() method, where we can call another method that changes the color.
As a consequence, we can pass an integer through that method. If the number is 1, the first Container changes color.
If the number is 2, the second Container changes the color.
import 'package:flutter/material.dart';
// this is a new branch enum and color change
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Happiness Calculator'),
);
}
}
const inactiveColor = Colors.amber;
const activeColor = Colors.red;
class MyHomePage extends StatefulWidget {
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Color firstContainerColor = inactiveColor;
Color secondContainerColor = inactiveColor;
void _changeColor(int container) {
if (container == 1) {
firstContainerColor = activeColor;
secondContainerColor = inactiveColor;
} else {
firstContainerColor = inactiveColor;
}
if (container == 2) {
secondContainerColor = activeColor;
firstContainerColor = inactiveColor;
} else {
secondContainerColor = inactiveColor;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(18.0),
child: GestureDetector(
onTap: () {
setState(() {
_changeColor(1);
});
},
child: Container(
alignment: Alignment.center,
color: firstContainerColor,
width: 250.0,
height: 250.0,
child: const Text('Press Me'),
),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(18.0),
child: GestureDetector(
onTap: () {
setState(() {
_changeColor(2);
});
},
child: Container(
alignment: Alignment.center,
color: secondContainerColor,
width: 250.0,
height: 250.0,
child: const Text('Press Me'),
),
),
),
),
],
),
],
),
),
);
}
}
By changing two integer variables we can easily do this. However, when someone else will read this code, what will happen?
It will not be clear from our code snippet. Right? We have to explain the whole process in great detail
Instead of that, we can use enum. Which is self explanatory. Even we do not have to add any comment why we are doing this.
Why we need enum?
Exactly for this reason, we need enum. It makes our code more readable. In addition, it will make our code more self explanatory.
Therefore, we will rewrite our code, this way.
import 'package:flutter/material.dart';
// this is a new branch enum and color change
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Happiness Calculator'),
);
}
}
//TODO: we will use enum in this branch
enum ContainerColor {
first,
second,
}
const inactiveColor = Colors.amber;
const activeColor = Colors.red;
class MyHomePage extends StatefulWidget {
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Color firstContainerColor = inactiveColor;
Color secondContainerColor = inactiveColor;
void _changeColor(ContainerColor selectedContainer) {
if (selectedContainer == ContainerColor.first) {
firstContainerColor = activeColor;
secondContainerColor = inactiveColor;
} else {
firstContainerColor = inactiveColor;
}
if (selectedContainer == ContainerColor.second) {
secondContainerColor = activeColor;
firstContainerColor = inactiveColor;
} else {
secondContainerColor = inactiveColor;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(18.0),
child: GestureDetector(
onTap: () {
setState(() {
_changeColor(ContainerColor.first);
});
},
child: Container(
alignment: Alignment.center,
color: firstContainerColor,
width: 250.0,
height: 250.0,
child: const Text('Press Me'),
),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(18.0),
child: GestureDetector(
onTap: () {
setState(() {
_changeColor(ContainerColor.second);
});
},
child: Container(
alignment: Alignment.center,
color: secondContainerColor,
width: 250.0,
height: 250.0,
child: const Text('Press Me'),
),
),
),
),
],
),
],
),
),
);
}
}
In the above code, we created two separate Container Color type by a set of two constant values.
enum ContainerColor {
first,
second,
}
As a result, now it becomes clear. We know, when we should use the first Container color, and when we should use the second Container color.
We get the same result. But this time, we do not have to explain why we’re doing this.
Leave a Reply