Flutter: The Power of Named Constructors

Naveed Jamali
6 min readSep 25, 2021

--

Writing reusable code is one of the qualities which make sure your code is manageable and maintainable. Code Re-Usability also makes sure that you write less code to achieve even more.

Today we will demonstrate how to write reusable code to create many forms of Text e.g. Heading, Sub Heading, Paragraph, Caption and so on in a single widget.

We are going to get help from a Dart feature called — Named Constructor.

What is a Named Constructor in Dart?

Dart.dev states:

Use a named constructor to implement multiple constructors for a class or to provide extra clarity

It is like Overloading a constructor and naming it to identify and use it easily.

Let's get started

Let's suppose we are going to create an app that uses text in the form of Heading, Sub Heading, Paragraph, Caption etc. The idea is shown below.

One widget with different Named Constructors.

We will create a widget and name it “Write” and it will be a Stateless widget.

Remove the default constructor.

import 'package:flutter/material.dart';class Write extends StatelessWidget {@overrideWidget build(BuildContext context) {return Container();}}

Add two fields, a String to store the text, and an enum _Action to store the type of the text e.g heading etc. The code will look like this

// The text we are going to disply (e.g. Mr John and Miss Joe)final String label;
// Type of text (heading, subheading etc.)_Action myAction = _Action.paragraph;

We will add an enum _Action at the end of the file, after the Write class. We will use it to differentiate among different types of our widgets.

enum _Action { heading, subheading, paragraph, caption }

In dart, anything which starts with underscore _ has a private scope.

It is time to use Named Constructor

We already have discussed Named Constructor in the Dart, let’s use it now. Constructors are functions that do not return anything and have the same name as the Class. In our case, the constructor for the Write class will be Write() { /** code in constructor*/ }.

To write a named constructor with the “heading” in the Write class, we write Write.heading(String text){ /** heading is the name of constructor.. hence Named Constructor **/ }. In our named constructors, we just pass the text, which will be shown on the screen. everything else will be handled internally.

In the code below, we are writing 4 Named Constructors with the names heading, subheading, paragraph, and caption. In the body of each constructor, we just assign a value to the action variable, which is an enum _Action. e.g. in Write.heading, we are assigning it _Action.heading. We will use this value in the build method of our widget.

Write.heading(this.label, {Key? key}) : super(key: key) 
{
myAction = _Action.heading;}Write.subheading(this.label, {Key? key}) : super(key: key) {myAction = _Action.subheading;}Write.paragraph(this.label, {Key? key}) : super(key: key) {myAction = _Action.paragraph;}Write.caption(this.label, {Key? key}) : super(key: key) {myAction = _Action.caption;}

Create different styles for the Write widget

Every widget contains a build method. We are going to write our text style code in our build method.

@overrideWidget build(BuildContext context) {// create a text style for our text.TextStyle style = const TextStyle();// modify textStyle with respect to text type.switch (myAction) {case _Action.heading:{style = const TextStyle(fontSize: 24, fontWeight: FontWeight.bold, color: Colors.black);break;}case _Action.subheading:{style = const TextStyle(fontSize: 17, fontWeight: FontWeight.w600, color: Colors.black);break;}case _Action.paragraph:{style = const TextStyle(fontSize: 14, fontWeight: FontWeight.w200, color: Colors.black);break;}case _Action.caption:{style = const TextStyle(fontSize: 14, fontWeight: FontWeight.w200, color: Colors.grey, fontStyle: FontStyle.italic);break;}default:{style = const TextStyle(fontSize: 14, color: Colors.black);break;}}return Container(padding:myAction == _Action.heading ? EdgeInsets.all(16) : EdgeInsets.all(8),child: Text(label,style: style,),);}

Full code of Write widget:

import 'package:flutter/material.dart';class Write extends StatelessWidget {final String label;_Action myAction = _Action.paragraph;Write.heading(this.label, {Key? key}) : super(key: key) {myAction = _Action.heading;}Write.subheading(this.label, {Key? key}) : super(key: key) {myAction = _Action.subheading;}Write.paragraph(this.label, {Key? key}) : super(key: key) {myAction = _Action.paragraph;}Write.caption(this.label, {Key? key}) : super(key: key) {myAction = _Action.caption;}@overrideWidget build(BuildContext context) {TextStyle style = const TextStyle();switch (myAction) {case _Action.heading:{style = const TextStyle(fontSize: 24, fontWeight: FontWeight.bold, color: Colors.black);break;}case _Action.subheading:{style = const TextStyle(fontSize: 17, fontWeight: FontWeight.w600, color: Colors.black);break;}case _Action.paragraph:{style = const TextStyle(fontSize: 14, fontWeight: FontWeight.w200, color: Colors.black);break;}case _Action.caption:{style = const TextStyle(fontSize: 14, fontWeight: FontWeight.w200, color: Colors.grey, fontStyle: FontStyle.italic);break;}default:{style = const TextStyle(fontSize: 14, color: Colors.black);break;}}return Container(padding:myAction == _Action.heading ? EdgeInsets.all(16) : EdgeInsets.all(8),child: Text(label,style: style,),);}}enum _Action { heading, subheading, paragraph, caption }

The wait is over, now it's time to get the Fruit of our efforts.

Now add as many widgets of the Write class as you want, in your app to see them in action.

I have created a Home class and added a few widgets too. here is the code.

import 'package:flutter/material.dart';import 'package:flutter_named_constructor/widgets/my_text.dart';class Home extends StatelessWidget {const Home({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(body: Column(mainAxisAlignment: MainAxisAlignment.start,crossAxisAlignment: CrossAxisAlignment.start,children: [Write.heading("Heading: Essays"),Write.subheading("Sub heading: Journey of a Homeless"),Write.caption("caption of story should be small"),Write.paragraph("Lorem spum dolar sit amet. Lorem spum dolar sit amet. Lorem spum dolar sit amet. Lorem spum dolar sit amet. Lorem spum dolar sit amet. "),Write.subheading("Buffalo must fly"),Write.paragraph("Lorem spum dolar sit amet. Lorem spum dolar sit amet. Lorem spum dolar sit amet. Lorem spum dolar sit amet. Lorem spum dolar sit amet. "),Write.subheading("Wonderful Scenes in Europe"),Write.paragraph("Lorem spum dolar sit amet. Lorem spum dolar sit amet. Lorem spum dolar sit amet. Lorem spum dolar sit amet. Lorem spum dolar sit amet. "),Write.subheading("The Crow in the City"),Write.paragraph("Lorem spum dolar sit amet. Lorem spum dolar sit amet. Lorem spum dolar sit amet. Lorem spum dolar sit amet. Lorem spum dolar sit amet. ")],),);}}

Here is the code for the main

import 'package:flutter/material.dart';import 'package:flutter_named_constructor/screens/home.dart';void main() {runApp(const MyApp());}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: Home(key: GlobalKey(),),);}}

Time for OUTPUT, let's check it.

Single widget in its different forms.

Moral of the story:

Get rid of repeating widgets.

Reuse code.

Avail features of the frameworks.

link to GITHUB repository:

Thank you for your precious time. Open for your valuable feedbacks.

--

--

Naveed Jamali
Naveed Jamali

No responses yet