Your First Flutter App: Polishing the App

Apr 12 2022 · Dart 2.14.1, Flutter 2.5, Visual Studio Code

Part 3: Style the App

23. Style Buttons

Episode complete

Play next episode

Next
About this episode
Leave a rating/review
See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 22. Style Text Next episode: 24. Style the Slider

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Transcript: 23. Style Buttons

At this point, Bullseye is starting to look great, but we still need to add some styling to the buttons. In the previous episode, we styled Text widgets by creating style classes that we applied to the widgets.

An alternative way to add styling is to create your own widgets that return styled widgets in their build methods. Then you can use those widgets in place of similar widgets in our app. In this example, a StyledButton class is a RawMaterialButton with an icon, a circular border, and some particular colors.

In this episode we’ll use a StyledButton to replace some of our TextButtons, and we’ll do similar for the Hit Me button.

To get started, open up your project in progress or download the starter project for this episode. We’re going to create a new button. Create a new file and call it styled_button.dart.

The first thing we’ve done is import the material library. Remember, this widget gives us all our widgets.

import 'package:flutter/material.dart';

Next, we’ll create a new stateless widget. Type ST then select the StatelessWidget option. Give it the name, StyledButton.

class StyledButton extends StatelessWidget {
  const StyledButton({ Key? key }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      
    );
  }
}

This widget will contain two different properties. It will contain one property for an icon. This property will be a type of IconData. This is data that flutter provides so we can display the icon. We also pass in a callback.

final IconData icon;
final GestureTapCallback onPressed;

Next, update the constructor to set those properties.

const StyledButton({Key? key, required this.icon, required this.onPressed})
      : super(key: key);

Now, let’s update our build method. First we’ll return a RawMaterialButton, setting the fill color and splash color.

    return RawMaterialButton(
      fillColor: Colors.black,
      splashColor: Colors.redAccent)

We’ll add an Icon widget to it. First we will wrap it in padding, then set the icon with a white color.

    return RawMaterialButton(
      fillColor: Colors.black, // old
      splashColor: Colors.redAccent, // old
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Icon(
          icon,
          color: Colors.white,
        ),
      ),
    );

Next, we’ll assign the onPressed callback and add a shape.

    return RawMaterialButton(
      fillColor: Colors.black,
      splashColor: Colors.redAccent,
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Icon(
          icon,
          color: Colors.white,
        ),
      ), // old code
      onPressed: onPressed,
      shape: const CircleBorder(side: BorderSide(color: Colors.white)),
    );

Okay, our button is ready to be used. Open up score.dart and import our new styled button class.

import 'styled_button.dart';

Now, let’s replace the text buttons with our new styled button. First, we’ll update the Start Over button.

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[ // old code
        StyledButton(
            icon: Icons.refresh,
            onPressed: () {
            onStartOver();
            },
        ),

Now lets replace our info button.

Padding(
    padding: const EdgeInsets.only(left: 32, right: 32.0),
    child: Column(
    children: <Widget>[
        Text('Round:', style: LabelTextStyle.bodyText1(context)),
        Text('$round', style: ScoreNumberTextStyle.headline4(context)),
    ],
    ),
), // old code
StyledButton(
    icon: Icons.info,
    onPressed: () {},
),

Now build and run or hot reload the the app. Now you’ll see that we have a couple of new styling buttons.

Okay, now let’s create a new button for the Hit Me button. Create a new file called hit_me_button.dart. Import the material library.

import 'package:flutter/material.dart';

Now type ST and select the Stateless Widget option. Give it the name HitMeButton.

class HitMeButton extends StatelessWidget {
  const HitMeButton({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

This will have two properties: a string for the button’s text and a callback.

final String text;
final GestureTapCallback onPressed;

Then update the the constructor.

const HitMeButton({Key? key, required this.text, required this.onPressed})
      : super(key: key);

Next we’ll create a new RawMaterial button and add some styling to it.

return RawMaterialButton(
    fillColor: Colors.red[700],
    splashColor: Colors.redAccent,
    child: Padding(
        padding: const EdgeInsets.all(14.0),
        child: Text(
            text,
            maxLines: 1,
            style: const TextStyle(
                color: Colors.white,
                fontWeight: FontWeight.bold,
                letterSpacing: 2.0,
            ),
        ),
    ),

Notice that we created a new text style this time, setting bolded white lettering with increased spacing. Let’s add an onPressed event with a rounded shape to it.

 @override
  Widget build(BuildContext context) {
    return RawMaterialButton(
      fillColor: Colors.red[700],
      splashColor: Colors.redAccent,
      child: Padding(
        padding: const EdgeInsets.all(14.0),
        child: Text(
          text,
          maxLines: 1,
          style: const TextStyle(
            color: Colors.white,
            fontWeight: FontWeight.bold,
            letterSpacing: 2.0,
          ),
        ),
      ), // old code
      onPressed: onPressed,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(12.0),
        side: const BorderSide(
          color: Colors.white,
        ),
      ),
    );
  }

Now let’s open up main.dart and and import hit_me_button.dart

import 'hit_me_button.dart';

Now scroll down to the Hit Me Text Button and replace it with our new button.

HitMeButton(
    text: 'HIT ME',
    onPressed: () {
        _showAlert(context);
    },
),

Now if you switch back to the app, you’ll see our app is looking better. One last fix, let’s update the button in the alert. First, we need to import the styled button. Add the following:

import 'styled_button.dart';

Now scroll down to _showAlert and update it replace the TextButton with the StyledButton.

var okButton = StyledButton(
    icon: Icons.close,
    onPressed: () {
    Navigator.of(context).pop();
    setState(() {
        _model.totalScore += _pointsForCurrentRound();
        _model.target = Random().nextInt(100) + 1;
        _model.round += 1;
    });
    },
);

Now return back to our app. You’ll see that we have our buttons. When you tap the Hit Me button, we have a new close button. Things are a light cramped, but before we address the padding, we need to update our slider and we’ll do that in the next episode.