Flutter: How to Create a Custom Text Widget 2021

How to Create a Custom Text Widget 2021

While developing the Flutter app, sometimes the code might get too messy, so it’s hard to read and maintain. This might happened not because the code is bad, or written poorly, it’s just the code that gets too large. In this article, I want to show you how to create a custom text widget and make it reusable.

You may ask: Why would I want to create a Custom Text Widget?

To answer this question, let me just show you an example. Assume that you are building the Flutter app, and you have a specific design pattern that is used over and over again in your Text Widget. For example, font-weight: 500font-size: 17, default color is grey, and maybe sometimes you want to make the text clickable. This is what will most likely be without using Custom Widgets:

flutter large text code

What if I tell you that you can create your own custom text widget so that the result would be exactly the same, but the length of the code will be dramatically decreased. Like this:

Custom NeoText Widget Flutter

That’s much better! Right? Okay, I don’t want to waste your time with wording. Let’s just dive into coding!

Step #1: Create NeoText Stateless Widget in Separated File

We want to have our custom Widget to be organized and reusable. To do so, let’s create a separate folder widgets inside our lib folder. And inside our widgets folder create a file neo_text.dart.

Your app structure should look like this:

Flutter App structure for custom widgets

Great! Now it’s time to create our Custom Text Widget. When you create your own widget, you can name it however you want. In my case, it will be – NeoText().

Let’s open neo_text.dart file and create a stateless widget with a name NeoText.

import 'package:flutter/material.dart';

class NeoText extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

Awesome! Now, it’s time to create important arguments for our NeoText widget.

Step #2: Create Text Arguments for NeoText Widget

Since our custom NeoText widget will be a better version of the Text widget, we need to create main arguments for our NeoText widget.

In our example, it will be:

  • text – Text input
  • size – Size of the text
  • fontWeight – Font weight of the text
  • color – Color of the text
  • wordSpacing – Spacing between words
  • onClick – On click even on the text

You can have much more arguments if you want. But we will keep it simple, so these are enough for this tutorial.

Add these arguments inside your NeoText stateless widget

import 'package:flutter/material.dart';

class NeoText extends StatelessWidget {
  final String text;
  final double size;
  final FontWeight fontWeight;
  final Color color;
  final double wordSpacing;
  final VoidCallback onClick;

  const NeoText({
    @required this.text,
    this.size,
    this.fontWeight,
    this.color,
    this.wordSpacing,
    this.onClick,
  });
  
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

Note: Make sure that the text argument is set as @required because this is an essential argument for our widget.

Grate! Now let’s build our custom

Step #3: Build NeoText Widget

In this step, we will build a NeoText Widget. Since our NeoText widget can be also as a TextButton widget, inside Container() widget we will first check if onClick argument is set.

For example:

  • if you use NeoText(title: ‘Hello World’)
    • Container’s child widget should be a Text() widget.
  • if you use NeoText(title: ‘Hello World’, onClick: () => null)
    • Container’s child widget should be a TextButton() widget.

import 'package:flutter/material.dart';

class NeoText extends StatelessWidget {
  final String text;
  final double size;
  final FontWeight fontWeight;
  final Color color;
  final double wordSpacing;
  final VoidCallback onClick;

  const NeoText({
    @required this.text,
    this.size,
    this.fontWeight,
    this.color,
    this.wordSpacing,
    this.onClick,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      child: onClick == null
          ? Text('')
          : TextButton(
              onPressed: () => onClick.call(),
              child: Text(''),
            ),
    );
  }
}

We have declared many arguments. Next let’s populate the Text() and TextButton() widgets with these arguments.

import 'package:flutter/material.dart';

class NeoText extends StatelessWidget {
  final String text;
  final double size;
  final FontWeight fontWeight;
  final Color color;
  final double wordSpacing;
  final VoidCallback onClick;

  const NeoText({
    @required this.text,
    this.size,
    this.fontWeight,
    this.color,
    this.wordSpacing,
    this.onClick,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      child: onClick == null
          ? Text(
              text,
              style: TextStyle(
                fontSize: size,
                fontWeight: fontWeight,
                color: color,
                wordSpacing: wordSpacing,
              ),
            )
          : TextButton(
              onPressed: () {
                onClick.call();
              },
              child: Text(
                text,
                style: TextStyle(
                  fontSize: size,
                  fontWeight: fontWeight,
                  color: color,
                  wordSpacing: wordSpacing,
                ),
              ),
            ),
    );
  }
}

Okay, that’s much better! However, we still did not finish our custom widget. If you have some custom design pattern, and it’s been used very often. You should set your own default parameters for the NeoText() Widget. For example, font-weight: 500font-size: 16, default color is grey,

To do so, you should add ?? after the argument and set a parameter to that.

          ? Text(
              text,
              style: TextStyle(
                fontSize: size ?? 16,
                fontWeight: fontWeight ?? FontWeight.w500,
                color: color ?? Colors.grey,
                wordSpacing: wordSpacing,
              ),
            )
          : TextButton(
              onPressed: () {
                onClick.call();
              },
              child: Text(
                text,
                style: TextStyle(
                  fontSize: size ?? 16,
                  fontWeight: fontWeight ?? FontWeight.w500,
                  color: color ?? Colors.grey,
                  wordSpacing: wordSpacing,
                ),
              ),
            ),

By setting your own default parameters, you will only need to use NeoText(text: ‘My text’), without setting any additional arguments.

Step #4: Import NeoText Widget

Finally, after we finished building our custom reusable widget, you can import the widget anywhere in your project by using:

import 'widgets/neo_text.dart';

or

import 'package:[app_name]/widgets/neo_text.dart';

This is an example of the main.dart file use case of our custom NeoText() widget:

class _MainPageState extends State<MainPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: SafeArea(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              NeoText(text: 'Custom Text Widget'),
              NeoText(text: 'You can reuse it anywhere in your project'),
              NeoText(
                text: 'How to create?',
                color: Colors.blue,
                size: 16,
                onClick: () {
                  print('Go to how to create page');
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}

And the result is:

Custom NeoText Widget Flutter

Final Code

import 'package:flutter/material.dart';

class NeoText extends StatelessWidget {
  final String text;
  final double size;
  final FontWeight fontWeight;
  final Color color;
  final double wordSpacing;
  final VoidCallback onClick;

  const NeoText({
    @required this.text,
    this.size,
    this.fontWeight,
    this.color,
    this.wordSpacing,
    this.onClick,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      child: onClick == null
          ? Text(
              text,
              style: TextStyle(
                fontSize: size,
                fontWeight: fontWeight,
                color: color,
                wordSpacing: wordSpacing,
              ),
            )
          : TextButton(
              onPressed: () {
                onClick.call();
              },
              child: Text(
                text,
                style: TextStyle(
                  fontSize: size,
                  fontWeight: fontWeight,
                  color: color,
                  wordSpacing: wordSpacing,
                ),
              ),
            ),
    );
  }
}

Conclusion

Creating your custom widget is essential in Flutter development. Not only you write less code and save time. But new developers that come to work with you will be easy to read and understand the code. As a result, your project becomes more scalable, readable, and easier to maintain.

You May Also Like

2 Comments

Leave a Reply

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

5 × three =