Flutter Course: Improving the Lotto App UI

Hello, developers! In this course, we will learn how to improve the user interface (UI) of the Lotto app. In the previous course, we implemented features to generate Lotto numbers and display the results. Now, let’s enhance the UI to improve the user experience further.

1. Project Setup and Existing Code Review

First, let’s take another look at the existing Lotto app project. The existing Lotto app has only basic features like a number generator. When the app is run, randomly generated Lotto numbers are displayed on the screen.

The structure of the existing code is as follows.


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

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

class LottoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Lotto App',
      home: LottoHome(),
    );
  }
}

class LottoHome extends StatefulWidget {
  @override
  _LottoHomeState createState() => _LottoHomeState();
}

class _LottoHomeState extends State {
  List lottoNumbers = [];

  void generateNumbers() {
    lottoNumbers = List.generate(6, (index) => Random().nextInt(45) + 1)..sort();
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Lotto Number Generator')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              'Generated Lotto Numbers:',
              style: TextStyle(fontSize: 24),
            ),
            SizedBox(height: 20),
            Text(
              lottoNumbers.join(', '),
              style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
            ),
            SizedBox(height: 30),
            ElevatedButton(
              onPressed: generateNumbers,
              child: Text('Generate Numbers'),
            ),
          ],
        ),
      ),
    );
  }
}

Now let’s explore various ways to improve the UI.

2. Establishing a UI Improvement Plan

To improve the UI, we can consider the following elements:

  • Changing the color scheme
  • Adjusting font styles and sizes
  • Applying card or grid layouts to make the numbers stand out more
  • Improving button design
  • Adding animation effects

2.1 Changing the Color Scheme

Using an eye-catching and enjoyable color combination instead of a simple color palette can provide a pleasant experience for users. For example, set a light color for the background and a contrasting dark color for the text.

2.2 Adjusting Font Styles and Sizes

To create a more attractive user experience, various font styles can be applied. Try using more unique fonts than the default one to change the mood of the app. You can easily apply a variety of fonts using Google Fonts.

2.3 Applying Card or Grid Layouts

By outputting Lotto numbers using cards, information can be conveyed more clearly. Additionally, let’s apply a grid layout to arrange the Lotto numbers.

2.4 Improving Button Design

Rather than using the default button, customize a button that includes selectable color combinations and text styles to emphasize button presses more.

2.5 Adding Animation Effects

Adding animation effects to buttons or UI elements can significantly enhance the user experience. Flutter provides various tools to easily implement animations.

3. Implementing UI Improvements

Now, based on the established plan, let’s modify the actual code to enhance the existing Lotto app by correcting certain elements.

3.1 Changing the Color Scheme

First, let’s change the color scheme to increase the contrast between the background and the text. Modify the build method in the main.dart file.


class LottoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Lotto App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        scaffoldBackgroundColor: Colors.lightBlue[50],
        textTheme: TextTheme(
          bodyText1: TextStyle(color: Colors.grey[800]),
          bodyText2: TextStyle(color: Colors.black),
        ),
      ),
      home: LottoHome(),
    );
  }
}

3.2 Adjusting Font Styles and Sizes

Next, let’s change the default text style. We can apply a more attractive font by adding the style property to the Text widget.


Text(
  'Generated Lotto Numbers:',
  style: TextStyle(
    fontSize: 28,
    fontWeight: FontWeight.bold,
    fontFamily: 'Roboto',
  ),
),

3.3 Applying Grid Layout

We will change the display of Lotto numbers to a grid format. Adding the code below will wrap each number in a card, making it visually appealing.


GridView.builder(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 3,
    childAspectRatio: 1,
    crossAxisSpacing: 10,
    mainAxisSpacing: 10,
  ),
  itemCount: lottoNumbers.length,
  itemBuilder: (context, index) {
    return Card(
      color: Colors.yellowAccent,
      child: Center(
        child: Text(
          lottoNumbers[index].toString(),
          style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold),
        ),
      ),
    );
  },
),

3.4 Improving Button Design

To enhance the button design, we will add properties to the ElevatedButton to change its style.


ElevatedButton(
  onPressed: generateNumbers,
  style: ElevatedButton.styleFrom(
    primary: Colors.blue,
    onPrimary: Colors.white,
    padding: EdgeInsets.symmetric(horizontal: 25, vertical: 15),
    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
  ),
  child: Text('Generate Numbers', style: TextStyle(fontSize: 20)),
),

3.5 Adding Animation Effects

We will use AnimatedContainer to apply animation effects when the button is clicked. The animation effect will be activated upon pressing the button.


AnimatedContainer(
  duration: Duration(milliseconds: 200),
  decoration: BoxDecoration(
    color: buttonPressed ? Colors.green : Colors.blue,
    borderRadius: BorderRadius.circular(30),
  ),
  child: ElevatedButton(
    onPressed: () {
      setState(() {
        buttonPressed = !buttonPressed;
      });
      generateNumbers();
    },
    child: Text('Generate Numbers', style: TextStyle(fontSize: 20)),
  ),
),

4. Final Code

We will integrate all of the above code to create the final code as follows.


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

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

class LottoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Lotto App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        scaffoldBackgroundColor: Colors.lightBlue[50],
        textTheme: TextTheme(
          bodyText1: TextStyle(color: Colors.grey[800]),
          bodyText2: TextStyle(color: Colors.black),
        ),
      ),
      home: LottoHome(),
    );
  }
}

class LottoHome extends StatefulWidget {
  @override
  _LottoHomeState createState() => _LottoHomeState();
}

class _LottoHomeState extends State {
  List lottoNumbers = [];
  bool buttonPressed = false;

  void generateNumbers() {
    lottoNumbers = List.generate(6, (index) => Random().nextInt(45) + 1)..sort();
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Lotto Number Generator')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Generated Lotto Numbers:', style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold, fontFamily: 'Roboto')),
            SizedBox(height: 20),
            Expanded(
              child: GridView.builder(
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 3,
                  childAspectRatio: 1,
                  crossAxisSpacing: 10,
                  mainAxisSpacing: 10,
                ),
                itemCount: lottoNumbers.length,
                itemBuilder: (context, index) {
                  return Card(
                    color: Colors.yellowAccent,
                    child: Center(
                      child: Text(
                        lottoNumbers[index].toString(),
                        style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold),
                      ),
                    ),
                  );
                },
              ),
            ),
            SizedBox(height: 30),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  buttonPressed = !buttonPressed;
                });
                generateNumbers();
              },
              style: ElevatedButton.styleFrom(
                primary: Colors.blue,
                onPrimary: Colors.white,
                padding: EdgeInsets.symmetric(horizontal: 25, vertical: 15),
                shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
              ),
              child: Text('Generate Numbers', style: TextStyle(fontSize: 20)),
            ),
          ],
        ),
      ),
    );
  }
}

5. Conclusion and Future Improvement Directions

So far, we have learned how to improve the UI of the Lotto app. By improving the app’s design in various ways, we can enhance the user’s experience. In the future, we can enrich the Lotto app even further by adding additional features, such as visualizing historical data for Lotto numbers or providing a record-keeping function for the numbers generated by the user.

I hope this course has been helpful to developers like you, and I look forward to bringing you another topic in the next course. Thank you for reading to the end!