Flutter - Gmail redesign

Design Concept :- 
I copied the design from xda developer website and converted it into the app with Flutter. In this example, I have used many widgets. Reference Flutter website.

You can create a more beautiful design with flutter and with this post, you will come to know about more widgets.
In flutter, everything is a widget, you can create your own widget, which will be covered in a future post. In Gmail design, I have created my own widgets like mail widget, primary mail widget, and header widget.
Separating widgets makes code readable and clean. The big advantage of separating app or code with the widget is, it increase the reuse of widget.


In Gmail design, I have user Container widget, Expanded widget, Image widget to display image from URL and Text widget.
You can learn more about Container widget with the above link. Expanded, Image and Text widget will be covered in the next post.

Here we will look the code structure, font used and assets.

I will try to keep the explanation simple so that you can develop your design with this blog reference.

I will give a detail explanation of used widget in the next post.

Let's see the packages and fonts used.
pubspec.yaml file is used to add package, fonts, and images to project.

pubspec.yaml
community_material_icon:
outline_material_icons:
I have used two different package of icon community_material_icon and outline_material_icons to give beautiful look to Gmail design.

The Gmail design uses google sans font, which changes the design look and feel completely.
  1. GoogleSans-Bold.ttf.
  2. GoogleSans-Regular.ttf.
  3. GoogleSans-Medium.ttf
You can use your own font, just replace the below font with your font.
Note:- Create assets/fonts directory and put all the fonts inside the directory before adding them in pubspec.yaml.

pubspec.yaml

  fonts:
    - family: GoogleBold
      fonts:
        - asset: assets/fonts/GoogleSans-Bold.ttf
    - family: GoogleMedium
      fonts:
        - asset: assets/fonts/GoogleSans-Medium.ttf
    - family: GoogleRegular
      fonts:
        - asset: assets/fonts/GoogleSans-Regular.ttf

Now we will look to code.
I have divided the code with different-different widgets to make it simple to understand.
I have created the widget folder inside lib folder.
In this example, all widgets are used in main.dart.

Let's see the code.


main.dart
import 'package:flutter/material.dart';
import 'package:community_material_icon/community_material_icon.dart';
import 'package:flutter_gmail_redesign/widget/header.dart';
import 'package:flutter_gmail_redesign/widget/mails.dart';
import 'package:flutter_gmail_redesign/widget/primary_mail.dart';
import 'package:outline_material_icons/outline_material_icons.dart';

void main() {
  runApp(MaterialApp(
    theme: ThemeData.dark(),
    debugShowCheckedModeBanner: false,
    home: Home(),
  ));
}

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      floatingActionButton: FloatingActionButton(
        backgroundColor: Colors.white,
        onPressed: () {},
        child: Icon(
          CommunityMaterialIcons.plus,
          color: Colors.black,
        ),
      ),
      body: Container(
        padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
        child: Column(
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Header(),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 10),
              child: Text(
                'PRIMARY',
                style: TextStyle(
                    fontSize: 15,
                    fontFamily: 'GoogleMedium',
                    color: Colors.black54),
              ),
            ),
            PrimaryMail(
              iconData: OMIcons.supervisorAccount,
              title: 'Social',
              msg: 'YouTube',
              count: '12 new',
              colors: Color(0xff1a73e8),
            ),
            PrimaryMail(
              iconData: OMIcons.localOffer,
              title: 'Promotions',
              msg: 'Think with Google',
              count: '18 new',
              colors: Color(0xff1e8e3e),
            ),
            PrimaryMail(
              iconData: OMIcons.forum,
              title: 'Forums',
              msg: 'Google Play',
              count: '25 new',
              colors: Color(0xff8024cd),
            ),
            Mails(
              sender: "Cecilia, Nik",
              title: "Trip to Yosemite",
              time: "2:13 PM",
              hasFile: true,
              msg: "Check out the planning document",
            ),
            Mails(
              sender: "Jeroen, Tino",
              title: "Coffee-making class",
              time: "12:57 PM",
              hasFile: false,
              msg: "Hi, I made a reservation",
            )
          ],
        ),
      ),
    );
  }
}
widget/header.dart
import 'package:flutter/material.dart';
import 'package:community_material_icon/community_material_icon.dart';

class Header extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Container(
      height: 55,
      margin: EdgeInsets.all(16.0),
      padding: EdgeInsets.symmetric(horizontal: 10),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(8.0),
        boxShadow: [
          BoxShadow(
            blurRadius: 2.0,
            offset: Offset(0.2, 0.2),
            color: Colors.grey[400],
          )
        ],
        color: Colors.white,
      ),
      child: Row(
        mainAxisSize: MainAxisSize.max,
        children: <Widget>[
          Icon(
            CommunityMaterialIcons.menu,
            color: Colors.black,
          ),
          Expanded(
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 10),
              child: Text(
                "Search mail",
                style: TextStyle(
                  color: Colors.grey,
                  fontSize: 18,
                  fontFamily: 'GoogleRegular',
                ),
              ),
            ),
          ),
          Container(
            width: 35,
            height: 35,
            decoration: BoxDecoration(
              shape: BoxShape.circle,
              image: DecorationImage(
                image: NetworkImage(
                    'https://avatars2.githubusercontent.com/u/24294081?s=460&v=4'),
              ),
            ),
          )
        ],
      ),
    );
  }
}


widget/mails.dart

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

class Mails extends StatelessWidget {
  final String sender;
  final String title;
  final String msg;
  final String time;
  final bool hasFile;
  Mails(
      { this.sender,
       this.title,
       this.msg,
       this.time,
       this.hasFile});
  
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.fromLTRB(30, 16, 16, 16),
      child: Row(
        mainAxisSize: MainAxisSize.max,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Container(
            width: 45,
            height: 45,
            decoration: BoxDecoration(
              shape: BoxShape.circle,
              image: DecorationImage(
                image: NetworkImage(
                  'https://avatars2.githubusercontent.com/u/24294081?s=460&v=4',
                ),
              ),
            ),
          ),
          Padding(
            padding: const EdgeInsets.only(left: 10),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Container(
                  width: MediaQuery.of(context).size.width * 0.7,
                  child: Row(
                    mainAxisSize: MainAxisSize.max,
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      Text(
                        this.sender,
                        style: TextStyle(
                            color: Colors.black,
                            fontSize: 18,
                            fontFamily: 'GoogleMedium'),
                      ),
                      Text(
                        this.time,
                        style: TextStyle(
                            color: Colors.black,
                            fontSize: 16,
                            fontFamily: 'GoogleRegular'),
                      ),
                    ],
                  ),
                ),
                Text(
                  this.title,
                  style: TextStyle(
                      color: Colors.black,
                      fontSize: 16,
                      fontFamily: 'GoogleMedium'),
                ),
                Container(
                  width: MediaQuery.of(context).size.width * 0.7,
                  child: Row(
                    mainAxisSize: MainAxisSize.max,
                    children: <Widget>[
                      Expanded(
                        child: Text(
                          this.msg,
                          overflow: TextOverflow.ellipsis,
                          softWrap: true,
                          style: TextStyle(
                              color: Colors.grey[700],
                              fontSize: 16,
                              fontFamily: 'GoogleMedium'),
                        ),
                      ),
                      Container(
                        padding:
                            EdgeInsets.symmetric(horizontal: 8, vertical: 3),
                        decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(4),
                            color: Color(0xffe6f4ea),
                            shape: BoxShape.rectangle),
                        child: Text(
                          'Trip',
                          style: TextStyle(
                              color: Color(0xff449e47),
                              fontSize: 12,
                              fontFamily: 'GoogleRegular'),
                        ),
                      ),
                      Padding(
                        padding: const EdgeInsets.only(left: 10),
                        child: Icon(
                          CommunityMaterialIcons.star_outline,
                          color: Colors.grey[700],
                        ),
                      )
                    ],
                  ),
                ),
                this.hasFile
                    ? Container(
                        width: 140,
                        height: 35,
                        padding: EdgeInsets.symmetric(horizontal: 10),
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(20),
                          shape: BoxShape.rectangle,
                          border: Border.all(color: Colors.grey[400], width: 1),
                          color: Colors.white,
                        ),
                        child: Row(
                          mainAxisSize: MainAxisSize.min,
                          children: <Widget>[
                            Icon(
                              CommunityMaterialIcons.file_document_box,
                              color: Color(0xff1a73e8),
                            ),
                            Expanded(
                              child: Padding(
                                padding: const EdgeInsets.only(left: 10),
                                child: Text(
                                  'Yosemite Trip Document',
                                  overflow: TextOverflow.ellipsis,
                                  style: TextStyle(
                                      fontSize: 15,
                                      color: Color(0xff1a73e8),
                                      fontFamily: 'GoogleMedium'),
                                ),
                              ),
                            )
                          ],
                        ),
                      )
                    : Container()
              ],
            ),
          )
        ],
      ),
    );
  }
}

widget/primary_mail.dart



import 'package:flutter/material.dart';

class PrimaryMail extends StatelessWidget {
  final IconData iconData;
  final String title;
  final String msg;
  final String count;
  final Color colors;
  PrimaryMail(
      { this.iconData,
       this.title,
       this.msg,
       this.count,
       this.colors});

  
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.fromLTRB(30, 16, 16, 16),
      child: Row(
        mainAxisSize: MainAxisSize.max,
        children: <Widget>[
          Icon(
            this.iconData,
            color: this.colors,
          ),
          Expanded(
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 20),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Text(
                    this.title,
                    style: TextStyle(
                        color: Colors.black,
                        fontSize: 17,
                        fontFamily: 'GoogleMedium'),
                  ),
                  Text(
                    this.msg,
                    style: TextStyle(
                        color: Colors.black87,
                        fontSize: 15,
                        fontFamily: 'GoogleRegular'),
                  ),
                ],
              ),
            ),
          ),
          Container(
            padding: EdgeInsets.symmetric(horizontal: 8, vertical: 5),
            child: Text(
              this.count,
              textAlign: TextAlign.center,
              style: TextStyle(fontSize: 12, fontFamily: 'GoogleMedium'),
            ),
            decoration: BoxDecoration(
                color: this.colors,
                shape: BoxShape.rectangle,
                borderRadius: BorderRadius.circular(20)),
          )
        ],
      ),
    );
  }
}




After combining above code will get output like this.



Flutter gmail design


Hope you like this post, happy reading.