Flutter UI Design Tutorial – Flutter Homepage Dashboard UI – 2022

Flutter, Flutter Login App, Flutter UI / UX, UI UX

In this flutter UI Design tutorial, we will learn to design a modern Homepage Dashboard UI in a flutter. This Flutter dashboard UI will be divided into multiple segments and cover multiple core flutter design concepts. This dashboard UI tutorial is for all who are new or want to enhance their designing skills in a flutter.

This Dashboard UI tutorial will cover the following points.

  1. Responsive Text and Images
  2. Layouts in Horizontal and Vertical Direction
  3. Card & Chip Designs
  4. Scroll Behaviors
  5. Clean Code
  6. Custom Widgets
  7. Light and Dark Theme
  8. UnBounded Height and Width Errors

and much more…

1 – Project Structure

As we are creating Flutter Login App and at the start of this Course we had learned 2 types of Folder Structures.

Therefore, we are using Feature First Approach and as a Global theme we are using the theme we created in this theme tutorial.

After having basic setup, we will add all the assets and constants respectively. You can get assets from here and updated constants from Flutter Login App Homepage.

Now let’s create a new Feature inside Features Folder and name it whatever you like (Core in our case).

Inside Core folder add a new dart file called dashboard.dart and folder called widgets (for local widgets).

2 – Flutter Appbar

Inside our dashboard.dart create a StateLess Widget by simple writing stless and hit enter.

Name the Statless class as DashboardScreen

Wrap the Container widget with Scaffold to apply Material design and to create appbar.

To design a modern and minimal Appbar in Flutter and to make it reusable component, we have to convert it into seprate Custom Widget.

But first, let’s design the appbar in this Dashboard.

This appbar contains 3 items.

  1. Leading Icon (Menu Icon Button)
  2. Title(Center as True)
  3. Action(Profile Icon Button)
AppBar(
      elevation: 0,
      centerTitle: true,
      backgroundColor: Colors.transparent,
      leading: Icon(
        Icons.menu,
        //For Dark Color
        color: isDark ? tWhiteColor : tDarkColor,
      ),
      title: Text(tAppName, style: Theme.of(context).textTheme.headline4),
      actions: [
        Container(
          margin: const EdgeInsets.only(right: 20, top: 7),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(10),
            //For Dark Color
            color: isDark ? tSecondaryColor : tCardBgColor,
          ),
          child: IconButton(onPressed: () {}, icon: const Image(image: AssetImage(tUserProfileImage))),
        )
      ],
    ),

3 – Search Bar Flutter

There are many types of search designs that commonly created in Flutter Homepages like Search Icon in AppBar, Search TextField at the top of Flutter Homepage, and clickable Search Box Design that will lead to open a search in new screen.

So, we will follow the last one which is modern and being used widely in professional apps.

To create this design, we need a ROW and inside we have 2 items (Text and Icon).

Whereas the left Border will be created using Container Widget (left border). To add the space between Text(Search…) and Icon, we will use row(mainAxisAlignment as spaceBetween()).

Container(
      decoration: const BoxDecoration(border: Border(left: BorderSide(width: 4))),
      padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(tDashboardSearch, style: txtTheme.headline2?.apply(color: Colors.grey.withOpacity(0.5))),
          const Icon(Icons.mic, size: 25),
        ],
      ),
    ),

4 – Scrollable Categories

To create a scrollable cards as categories, we will use ListView.builder() with direction as horizontal.

Firstly, we will design a Card using Row with a Container as first child and Column as 2nd Child. Column will further contain 2 Texts.

After creating design card or chip, we will convert it into ListView and afterwards, convert it into ListView.builder().

In ListView.builder() we will get the dummy data from a model.

SizedBox(
      height: 45,
      child: ListView.builder(
        itemCount: list.length,
        shrinkWrap: true,
        scrollDirection: Axis.horizontal,
        itemBuilder: (context, index) => GestureDetector(
          onTap: list[index].onPress,
          child: SizedBox(
            width: 170,
            height: 45,
            child: Row(
              children: [
                Container(
                  width: 45,
                  height: 45,
                  decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: tDarkColor),
                  child: Center(
                    child: Text(list[index].title, style: txtTheme.headline6?.apply(color: Colors.white)),
                  ),
                ),
                const SizedBox(width: 5),
                Flexible(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Text(list[index].heading, style: txtTheme.headline6, overflow: TextOverflow.ellipsis),
                      Text(list[index].subHeading, style: txtTheme.bodyText2, overflow: TextOverflow.ellipsis)
                    ],
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    ),

5 – Banner Design

Banners are of many designs but the reason to design this type of banner is to keep design professional and make it easy to use for any type of app.

This banner design will contain 2 cards and 1 button.

We will divide the design into half using Row and inside 2 Expanded Widgets(to cover equal space).

@override
  Widget build(BuildContext context) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        //1st banner
        Expanded(
          child: Container(
            decoration: BoxDecoration(borderRadius: BorderRadius.circular(10),
              //For Dark Color
              color: isDark ? tSecondaryColor : tCardBgColor,
            ),
            padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 20),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: const [
                    Flexible(child: Image(image: AssetImage(tBookmarkIcon))),
                    Flexible(child: Image(image: AssetImage(tBannerImage1))),
                  ],
                ),
                const SizedBox(height: 25),
                Text(tDashboardBannerTitle1, style: txtTheme.headline4, maxLines: 2, overflow: TextOverflow.ellipsis),
                Text(tDashboardBannerSubTitle, style: txtTheme.bodyText2, maxLines: 1, overflow: TextOverflow.ellipsis),
              ],
            ),
          ),
        ),
        const SizedBox(width: tDashboardCardPadding),
        //2nd Banner
        Expanded(
          child: Column(
            children: [
              //Card
              Container(
                decoration: BoxDecoration(borderRadius: BorderRadius.circular(10),
                  //For Dark Color
                  color: isDark ? tSecondaryColor : tCardBgColor,
                ),
                padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 20),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: const [
                        Flexible(child: Image(image: AssetImage(tBookmarkIcon))),
                        Flexible(child: Image(image: AssetImage(tBannerImage2))),
                      ],
                    ),
                    Text(tDashboardBannerTitle2, style: txtTheme.headline4, overflow: TextOverflow.ellipsis),
                    Text(tDashboardBannerSubTitle, style: txtTheme.bodyText2, overflow: TextOverflow.ellipsis),
                  ],
                ),
              ),
              const SizedBox(height: 5),
              SizedBox(
                width: double.infinity,
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 10),
                  child: OutlinedButton(onPressed: () {}, child: const Text(tDashboardButton)),
                ),
              )
            ],
          ),
        ),
      ],
    );
  }

6 – Top Courses

This section can be utilized to create any type of Top Items, Courses, Top Products, and anything that suits.

We will create a SizedBox with specific width and height because we cannot cover it using Expanded to make it unbounded.

Then inside a Sizedbox create a Container.

Container will have a BoxDecoration with border Radius and background Color.

Create 2 rows inside it and each contain 2 items.

First Row will have 1 text and 1 Image whereas, 2nd row will have 1st ElevatedCircular Button and 2nd will have Column with 2 texts.

SizedBox(
      height: 200,
      child: ListView.builder(
        shrinkWrap: true,
        scrollDirection: Axis.horizontal,
        itemCount: list.length,
        itemBuilder: (context, index) => GestureDetector(
          onTap: list[index].onPress,
          child: SizedBox(
            width: 320,
            height: 200,
            child: Padding(
              padding: const EdgeInsets.only(right: 10, top: 5),
              child: Container(
                decoration: BoxDecoration(borderRadius: BorderRadius.circular(10),
                  //For Dark Color
                  color: isDark ? tSecondaryColor : tCardBgColor,
                ),
                padding: const EdgeInsets.all(10),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Flexible(
                          child: Text(
                            list[index].title,
                            style: txtTheme.headline4,
                            maxLines: 2,
                            overflow: TextOverflow.ellipsis,
                          ),
                        ),
                        Flexible(child: Image(image: AssetImage(list[index].image), height: 110)),
                      ],
                    ),
                    Row(
                      children: [
                        ElevatedButton(
                          style: ElevatedButton.styleFrom(shape: const CircleBorder()),
                          onPressed: () {},
                          child: const Icon(Icons.play_arrow),
                        ),
                        const SizedBox(width: tDashboardCardPadding),
                        Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              list[index].heading,
                              style: txtTheme.headline4,
                              overflow: TextOverflow.ellipsis,
                            ),
                            Text(
                              list[index].subHeading,
                              style: txtTheme.bodyText2,
                              overflow: TextOverflow.ellipsis,
                            ),
                          ],
                        )
                      ],
                    )
                  ],
                ),
              ),
            ),
          ),
        ),
      ),
    )

6 – Clean Code

So far we were creating everything inside dashboard.dart but at the end you will see our code size has increased alot and become unmanageable.

Therefore, we have to convert our code into separate Custom widgets.

CODING with T

🚀 Supercharge your Flutter skills! Subscribe to my YouTube channel now for mind-blowing coding insights, expert tips, and exclusive content. Don’t miss out!

23 - Product Detail Screen, How to create Products Details Screen in Flutter. Flutter eCommerce app UI Design

Source code

COURSES

Flutter E Commerce App Modern and latest
Flutter Login App UI Source Code - Flutter Complete App - Flutter App Design - Flutter App 2023 - Complete Flutter App 2023
Learn flutter from scratch in 4 hours - Flutter Crash Course - Coding with T

Learn Flutter

1.2 # How to install flutter on android studio 2022 - Flutter Basic Crash Course
2.2 - Add Image in Flutter - Assets Network- Flutter Basic Crash Course 2022

flutter Design

How to create a Custom Shape in Flutter. Flutter E Commerce app Design. Ecommerce app design Flutter. Flutter clippath tutorial
How to create a Custom Appbar in flutter. Custom Appbar Design. Flutter App Design
16 - Product Card and Grid Layout, How to create a Grid View in Flutter. How to add Products in GridView Layout. Flutter eCommerce app UI Design
Bottom Navigation bar in Flutter. Flutter Material 3 bottom navigation bar. How to design background color of Flutter bottom navigation bar. Flutter ecommerce app design
23 - Product Detail Screen, How to create Products Details Screen in Flutter. Flutter eCommerce app UI Design

Flutter Backend

33 - How to Setup Firebase - Firebase Basics - Flutter Firebase - Flutter ecommerce app with firebase as backend
38 - How to Sign-in with Google in flutter Firebase, Firebase Basics, Flutter Firebase, Flutter ecommerce app with firebase as backend
40 - Flutter Firebase CRUD,  Firebase Basics, Flutter Firebase, Flutter ecommerce app with firebase as backend