Redux App: Getting To Start

Before we begin building, let's update your counter app to a bare-bones nothing app so we can begin fresh.

1. Bare Minimum Flutter App

  1. // main.dart
  2. import 'package:flutter/material.dart';
  3. void main() => runApp(new MainApp());
  4. class MainApp extends StatelessWidget {
  5. @override
  6. Widget build(BuildContext context) {
  7. return new Container();
  8. }
  9. }

NB: Container is the like <div> tag of Flutter, except you're supposed to use it. When you return a Container with children, it takes up no space. It's also a convenience widget that lets you add a ton of styles, layout, etc to it's children.

flutter run

This will give you a blank screen. But it runs.

Celebration 1: You've made a mobile app that can deploy to iOS and Android.

2. MaterialApp and Scaffold widgets

Turn that container into a MaterialApp with a title and a home:

  1. // main.dart
  2. import 'package:flutter/material.dart';
  3. void main() => runApp(new MusicParty());
  4. class MusicParty extends StatelessWidget {
  5. String title = 'Me Suite'; // new
  6. @override
  7. Widget build(BuildContext context) {
  8. return new MaterialApp( // updated
  9. title: title, // new
  10. home: new HomePage(title), // new
  11. );
  12. }
  13. }

That's it for this file, for now.

Also, we've broken the app by trying to render a widget we haven't created yet: HomePage. Let's do that.

Create a new directory called pages in the lib directory. Here, create a new file called home_page.dart;

  1. // lib folder:
  2. - pages
  3. - home_page.dart
  4. main.dart

Now, let's build that HomePage:

  1. // pages/home_page.dart
  2. import 'package:flutter/material.dart';
  3. class HomePage extends StatelessWidget {
  4. // We passed it a title from the app root, so we have to
  5. // set up the class to accept that arg.
  6. final String title;
  7. HomePage(this.title);
  8. @override
  9. Widget build(BuildContext context) {
  10. // Scaffold is almost always going to be your top-level widget
  11. // on each page.
  12. return new Scaffold(
  13. appBar: new AppBar(),
  14. body: new Container(),
  15. floatingActionButton: new FloatingActionButton(onPressed: null),
  16. );
  17. }
  18. }

NB: Scaffold is a super nice widget that gives you the basic layout of almost all mobile apps. In addition to the three arguments we've passed it, it can set you up with footer navigation, a drawer where you'd put a full menu, and more.


Import your new file into main.dart. Render your app now, and it'll look like this:

screen shot blank app

We just need to fill in some of that content:

  1. // pages/home_page.dart
  2. import 'package:flutter/material.dart';
  3. class HomePage extends StatelessWidget {
  4. final String title;
  5. HomePage(this.title);
  6. @override
  7. Widget build(BuildContext context) {
  8. return new Scaffold(
  9. // AppBar class takes a Widget for title, not a string
  10. // In order to get it to display our title, pass it a Text widget
  11. appBar: new AppBar(
  12. title: new Text(this.title), // new
  13. ),
  14. body: new Container(),
  15. // FloatingActionButton is literally a button that floats above
  16. // all other page content.
  17. floatingActionButton: new FloatingActionButton(
  18. // Pass it a callback to execute when tapped
  19. onPressed: () => print('PRESSED!'), // new
  20. // Pass it children to render in the button
  21. child: new Icon(Icons.add), // new
  22. ),
  23. );
  24. }
  25. }

With this, you now have text in app bar and a functioning floating action button. If you press it, you'll see some feedback in your console.

Finally, let's add some body content:

  1. // pages/home_page.dart
  2. ...
  3. @override
  4. Widget build(BuildContext context) {
  5. return new Scaffold(
  6. appBar: new AppBar(
  7. title: new Text(this.title),
  8. ),
  9. body: new Container(
  10. child: new Center(
  11. child: new Column(
  12. //mainAxisAlignment is an argument for Column, Row and other
  13. // layout widgets. It does what CSS's 'justify-content' does
  14. mainAxisAlignment: MainAxisAlignment.center,
  15. // If you recall, Column is a layout widget that
  16. // expects a List who's data is of type Widget:
  17. children: <Widget>[
  18. new Text(
  19. 'You have pushed the button this many times:',
  20. ),
  21. new Text('0'),
  22. ],
  23. ),
  24. ),
  25. ),
  26. floatingActionButton: new FloatingActionButton(
  27. onPressed: () => print('PRESSED!'),
  28. child: new Icon(Icons.add),
  29. ),
  30. );
  31. }
  32. }

Now, save this, and refresh it. You should be back to the starter app… minus any functionality at all.

This is zero for us. Since we're implementing Redux next, we don't want to make that counter work using StatefulWidgets.