Non material vs material flutter

Certainly there are non material widgets in Flutter, and we, knowingly or unknowingly use them. However, we cannot imagine Flutter without Material design.

Whether we want to navigate to another screen, or we want to use a particular theme, or we want to add localization support, we cannot do it without the assistance of Material App widget. It includes many material design specific features that we’ll learn as we progress.

Firstly, MaterialApp is a widget that introduces many captivating tools and fascinating features. As we’ve just reminded, there are Navigator or Theme to help you develop our Flutter Application.

There seems to be some confusions about MaterialApp and Material class in Flutter. However, they are not same. Although they are linked.

Let us build a simple Flutter Application where we use some simple basic widgets and we’ll follow the Material design. As a result, we’ll place MaterialApp near root widget.

After watching the code, we’ll discuss Material principles in great detail.

import 'package:flutter/material.dart';

void main() {
  runApp(
    const OurSecondApp(),
  );
}

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'First Material App',
      debugShowCheckedModeBanner: false,
      home: OurSecondAppHome(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('First Material App'),
      ),
      body: const OurSecondAppBody(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    /// Here we're going to use basic widgets
    /// such as, Text, Container, Row, Column, etc.
    ///
    return Column(
      children: [
        Center(
          child: Row(
            children: [
              Container(
                padding: const EdgeInsets.all(10),
                child: const Text(
                  'ID',
                  textAlign: TextAlign.left,
                ),
              ),
              Container(
                padding: const EdgeInsets.all(10),
                child: const Text(
                  'Name',
                  textAlign: TextAlign.left,
                ),
              ),
              const Expanded(
                child: Text(
                  'Phone Number',
                  textAlign: TextAlign.center,
                ),
              ),
              Container(
                padding: const EdgeInsets.all(10),
                child: const Text(
                  'Gender',
                  textAlign: TextAlign.left,
                ),
              ),
              Container(
                padding: const EdgeInsets.all(10),
                child: const Text(
                  'Country',
                  textAlign: TextAlign.left,
                ),
              ),
            ],
          ),
        ),
        Center(
          child: Row(
            children: [
              Container(
                padding: const EdgeInsets.all(10),
                child: const Text(
                  '1',
                  textAlign: TextAlign.left,
                ),
              ),
              Container(
                padding: const EdgeInsets.all(10),
                child: const Text(
                  'John',
                  textAlign: TextAlign.left,
                ),
              ),
              const Expanded(
                child: Text(
                  '123645',
                  textAlign: TextAlign.center,
                ),
              ),
              Container(
                padding: const EdgeInsets.all(10),
                child: const Text(
                  'Male',
                  textAlign: TextAlign.left,
                ),
              ),
              Container(
                padding: const EdgeInsets.all(10),
                child: const Text(
                  'Germany',
                  textAlign: TextAlign.left,
                ),
              ),
            ],
          ),
        ),
        Center(
          child: Row(
            children: [
              Container(
                padding: const EdgeInsets.all(10),
                child: const Text(
                  '2',
                  textAlign: TextAlign.left,
                ),
              ),
              Container(
                padding: const EdgeInsets.all(10),
                child: const Text(
                  'Jenifer',
                  textAlign: TextAlign.left,
                ),
              ),
              const Expanded(
                child: Text(
                  '652341',
                  textAlign: TextAlign.center,
                ),
              ),
              Container(
                padding: const EdgeInsets.all(10),
                child: const Text(
                  'Female',
                  textAlign: TextAlign.left,
                ),
              ),
              Container(
                padding: const EdgeInsets.all(10),
                child: const Text(
                  'France',
                  textAlign: TextAlign.left,
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }
}

Quite a long code where we have used some basic widgets like Scaffold, Column, Row, Container, Expanded, Text, etc.

Moreover, we’ve wrapped the root widget with MaterialApp Widget.

return const MaterialApp(
      title: 'First Material App',
      debugShowCheckedModeBanner: false,
      home: OurSecondAppHome(),
    );

Therefore, we get this screenshot.

Basic widgets in Flutter
Basic widgets in Flutter

Why do we use MaterialApp in Flutter?

There are many reasons to use MaterialApp. But one of the most important reasons is MaterialApp gives constraints to the child widget to fit into the screen.

Now we can refactor the above code as there are many use cases, such as we’ve used Container widget many times.

As a consequence, we can refactor a model Container class.

import 'package:flutter/material.dart';

void main() {
  runApp(
    const OurThirdApp(),
  );
}

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'First Material App',
      debugShowCheckedModeBanner: false,
      home: OurThirdAppHome(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('First Material App'),
      ),
      body: const OurThirdAppBody(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    /// Here we're going to use basic widgets
    /// such as, Text, Container, Row, Column, etc.
    ///
    return Column(
      children: const [
        ColumnOne(),
        ColumnThree(),
        ColumnTwo(),
      ],
    );
  }
}

class ModelContainer extends StatelessWidget {
  const ModelContainer({
    Key? key,
    required this.modelText,
  }) : super(key: key);

  final Text modelText;

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(10),
      color: Colors.amber,
      child: modelText,
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Row(
        children: const [
          ModelContainer(
            modelText: Text('ID'),
          ),
          ModelContainer(
            modelText: Text('Name'),
          ),
          ModelContainer(
            modelText: Text('Phone'),
          ),
          ModelContainer(
            modelText: Text('Gender'),
          ),
          ModelContainer(
            modelText: Text('Country'),
          ),
        ],
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Row(
        children: const [
          ModelContainer(
            modelText: Text('2'),
          ),
          ModelContainer(
            modelText: Text('Juliet'),
          ),
          ModelContainer(
            modelText: Text('100023'),
          ),
          ModelContainer(
            modelText: Text('Female'),
          ),
          ModelContainer(
            modelText: Text('Britain'),
          ),
        ],
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Row(
        children: const [
          ModelContainer(
            modelText: Text('1'),
          ),
          ModelContainer(
            modelText: Text('Romeo'),
          ),
          ModelContainer(
            modelText: Text('489023'),
          ),
          ModelContainer(
            modelText: Text('Male'),
          ),
          ModelContainer(
            modelText: Text('France'),
          ),
        ],
      ),
    );
  }
}

Now, as a result, we can design the model Container widget and that will change the look of the whole app.

Material App second sample
Material App second sample

To put it simply, each widget now knows how to behave and the instruction comes from the MaterialApp.

As a result, we don’t have to bother about the text direction property of any Text Widget anymore. MaterialApp handles that through material design principles.

What is the difference between material and MaterialApp in flutter?

Actually, there is more friendship than difference between these two Widgets. One needs another. And we should use them both.

Many widgets, such as Scaffold, AppBar, Card, Dialog, FloatingButton, and many more, which are Material instances. Through Material guidelines they define User Interface elements that respect Material rules.

If we don’t define Material guidelines near any Text widget, the screen will be black and the text will have a yellow underline. It takes as a fallback theme.

That is the reason, why we use MaterialApp near the root of our Flutter Application.

To sum up, we need to use Material and MaterialApp widgets both. As far as Flutter design and layout are concerned, we need to use them both. If we want that a Text widget should adopt a certain theme, we need to introduce a Material instance like Scaffold widget first.

As we progress, we’ll learn more about these features, in great detail.

What Next?

Books at Leanpub

Books in Apress

My books at Amazon

GitHub repository

Technical blog

Twitter

Comments

6 responses to “Non material vs material flutter”

  1. […] We’ll discuss in a separate post how we can utilise Dart’s new features. Some features will definitely boost the development of Flutter User Interfaces. […]

  2. […] have seen how invisible widgets like Row, Column, or Stack have been used in our previous section – What is Layout in […]

  3. […] have seen how invisible widgets like Row, Column, or Stack have been used in our previous section – What is Layout in […]

  4. […] need the function “showDialog()” to display the Material Dialog on the Page or the Screen. Subsequently the Dialog Box appears on the current content of the […]

  5. […] It basically fills the fill color to use for an app bar’s Material. […]

  6. […] We have already seen the First Step where we have mainly built the home page. In this section, we will build a few other pages. In addition, we will also use some material deign-related Widgets. […]

Leave a Reply