Flutter Class Curriculum and Resources

Updated: Dec 30, 2021

Learning how to code is becoming more and more essential as much of what we value now is digital. In this curriculum I will be walking through some basics and other useful widgets and functions within the programming language flutter. I teach a Flutter and Python class every Monday through Thursday at 9:00 AM EST.


If you are interested in joining you can submit an application at https://www.wequil.school/


--


Downloading Flutter

Before you can get started you have to download flutter. Here is the official documentation on how you can download Flutter on any operating system: https://flutter.dev/docs/get-started/install


If you want some more instruction, I've written out some of my own documentation with more guidance on how to do it easily and correctly here: https://coda.io/@sumay-mcphail/learning-flutter/getting-started-21



--



Curriculum


You can find my full curriculum here as well as other resources: https://coda.io/@sumay-mcphail/learning-flutter


import “package:flutter/material.dart”;

import ‘package:flutter/material.dart’; is what you always need to do when you start a new project or .dart file. This is because it gets all the materials you need to start coding.


Widget Tree’s

Everything in flutter is an object. Objects are also known as widgets. Different widgets can be stacked and create something called a widget tree, like this one!




Stateless and Stateful Widgets

In flutter you can make something called a class, a class is where you can start off a new widget tree. In other words, make a new page. There are two different types of classes, Stateless widgets and Stateful widgets.


Stateless widgets are for when you are making a page that doesn’t change in real time and the UI is absolute and there usually isn’t a lot of backend action.


A Stateful widget is when you are making changes in real time.


Scaffolds

Scaffolds are very important when coding in flutter because it provides a lot of different things that you would usually need in apps and provides default settings for text widgets, button widgets, etc.


AppBars

App bars are commonly used in most app and can only be accessed using Scaffolds.


Properties

Properties are the certain things you can do with a certain widget. For example the Scaffold widget has the some properties such as:


appBar and body


What are Buttons

Buttons are also commonly used in apps and it core function is something called onPressed. This is where you specify what you want to button to do when you press it.


Divider

A divider is a type of widget that displays a thin line to divide different parts of your app. An example of a divider is this:


Divider(
   height: 60.0,
)


persistentFooterButton

A persistentFooterButton is a button in the bottom right corner and is a property of the Scaffold. This allows you to put many buttons at the bottom of your screen. An example is this:



persistentFooterButtons: <Widget>[
   RaisedButton(
       elevation: 0,
       onPressed: () {
           Navigator.push(
               context,
               MaterialPageRoute(
                   builder: (context) => Login(),
               ));
           },
       color: Colors.black,
       child: Icon(
           Icons.arrow_back,
           color: Colors.white,
       ),
   ),
],




Navigator

Navigator is usually used with buttons to make it so when you press a button it goes to another screen. Here’s an example of it being used.



onPressed: () => Navigator.push(
   context, SlideLeftRoute(screen: Screen())),


This is inside an onPressed function which means that it will be activated once a button is clicked. Then it is pushing another screen in front of another screen.


DebugShowCheckedModeBanner

In the corner of your simulator you may notice a red banner in the corner the says debug.


To get rid of it in your main.dart you can write debugShowCheckedModeBanner: false in order to get rid of it.


MainAxisAlignment

Rows and Columns both allow you to do something called MainAxisAlignment that allow you to change how the Widgets inside the Row and Column are positioned.


For example:


Row(
   mainAxisAlignment: MainAxisAlignment.start,
   children: <Widget>[
       Icon(Icons.star, size: 50),
       Icon(Icons.star, size: 50),
       Icon(Icons.star, size: 50),
   ],
)


This would make it so that all the Widgets inside the Row would start at the beginning of where the Row started. There are many other formatting options as well such as:


mainAxisAlignment: MainAxisAlignment.center
mainAxisAlignment: MainAxisAlignment.end
mainAxisAlignment: MainAxisAlignment.spaceBetween
mainAxisAlignment: MainAxisAlignment.spaceEvenly

Formatting widgets

Formatting widgets are used for formatting. They are invisible but are still used for the UI. Let’s say you have five Text widgets that you want in a row. You can use the Row() widget to put them in a row. The row isn’t actually visible but the Text widgets are now in a row.


Columns and rows are commonly used but there are a lot of formatting widgets that you can use in flutter


Circle Avatar

Circle Avatars are a type of widget that takes either a photo or something else and makes it into a circle.


Here are the properties of the Circle Avatar widget:


backgroundColor

This allows you to change the background color if you are not putting an image in your circle avatar widget


backgroundImage

This is where you can add an image to make your image in a circular shape


child

This is in a lot of widgets such as Columns, Rows, and Containers. This is just for the next widget in the widget tree branching down from your Circle Avatar


foregroundColor

This is the default color for Text in the Circle Avatar.


radius

This is where you set the size of your Circle Avatar


maxRadius

This is where you can set the maximum radius you would like your Circle Avatar to be


minRadius

This is where you can set the minimum radius you would like your Circle Avatar to be


onBackgroundImageError

This is for when there is an error retrieving the image you would like to display in your Circle Avatar. Then you can tell it what to do in that scenario.


Custom Widgets

Custom Widgets are used when you are making things multiple times. Why Re-write the same code over and over again when you can just make a custom widget?


Custom widgets can also be made to have certain parts of it changed based on your needs. For example, a menu. Every item on the menu is going to have a title, a picture, a price, a calorie count, and a list on ingredients. The formatting is the same, but all the different components will change. You can use a custom widget for this as well!


Drawers

Drawers are a type of Widget in flutter that is a flap that comes out. They are part of Scaffolds...here is an example of a Drawer:



drawer: Drawer(
   elevation: 16,
   child: Column(
       children: [
       UserAccountsDrawerHeader(
           accountName: Text(
               "Sumay McPhail",
               style: TextStyle(fontWeight: FontWeight.bold),
           ),
           accountEmail: Text("sumay.l.mcphail@gmail.com"),
           currentAccountPicture: CircleAvatar(
               backgroundColor: Colors.white,
               child: Text("SM"),
               ),
           ),
       ]
   ),
)



As you can see I added something called UserAccountsDrawerHeader. This is a built in Widget that created the setup we see above it come with the properties:


accountName

accountEmail

currentAccountPicture



Icons

Icons are a type of widget in flutter that allows you to make things like email icons and all different types like this one:




Some icons need to have a dependency in pubspec.yaml. But some of them can just be used like this:


Icon(
   Icons.email
)


Variables


Variables are used in coding a lot in all different coding languages. Variables are basically just things you can store data in. Here’s the syntax you use in flutter.


In flutter you can specify which type of data you want to store in a variable. Strings, integers, booleans, lists, etc. In flutter the syntax is this:


What type of data you want to store the name of your variable = your data;


For example:


String name = “Samantha”;


If you were to put in a integer in the variable like this:


String name = 42;


It would give you an error because you specified that it would be String, but you put in an integer.


Dynamic


Dynamic is also a specification you can use that makes it so you can put in any type of data inside your variable.


For example:


dynamic var = 42;

dynamic var = "Hello World”;

dynamic var = [2, 3, 4, 5, 6];

dynamic var = true;


This would not give us any errors. But, it is usually better to specify which type of data you need because if you need a String stored in your variable you’ll remember that when you put in an integer because it’ll give you an error.


If and Else Statements

If and else statements are structured like this:


if (perimeters) {
     
} else {
   
}


Pubspec.yaml and Images

Pubspec.yaml is where you can add extensions that can allow you to do more things with your code. Pubspec.yaml is where you can add the ability to add images to your app.


If you go into the pubspec.yaml file you will see this # assets this is where you can enable the ability to use images. Right now assets is commented out so remove the #. Then make a folder somewhere else that you want to store your images. Then you can put a dash and then put the name of your image folder and then a /.


Here’s an example:


assets:
   - images/


Then you would use the image like this: Image.asset(””) in the quotations you would say the name of your folder (in this case, images) and then a / and then the name of your image along with .png, .jpeg, .gif, etc.


You may have to stop your simulator and then run it again in order to run the image in your app.


YouTube Videos

Importing YouTube videos is something that requires a package in pubspec.yaml called youtube_player_flutter that allows you to display YouTube videos in Flutter applications. It even includes some of the YouTube functionality like speeding up videos. So how can we do this?


Fist, go to pubspec.yaml, and go to the dependencies. Then import youtube_player_flutter: with the latest version:


dependencies:
   flutter:
       sdk: flutter

       # YouTube Player
       youtube_player_flutter: ^7.0.0+7


Then you need to import the youtube_player_flutter in the .dart file you plan on using the extension in:



import 'package:youtube_player_flutter/youtube_player_flutter.dart';


Afterwards you need to create a controller for the YouTube video that get the videoID out of the URL and therefore allows us to display the YouTube video:


YoutubePlayerController _controller = YoutubePlayerController(
   initialVideoId:
       YoutubePlayer.convertUrlToId("YouTube Link"),
   flags: YoutubePlayerFlags(
       autoPlay: true,
       mute: false,
   ),
);


Now that we have the controller, we need to display the YouTube video:


YoutubePlayer(
   controller: _controller,
   liveUIColor: Colors.amber,
),


Stack

A Stack is a widget that is like a Row and a Column, but instead of going side-to-side or up and down, it Stacks widgets on top of each other.


You can create a Stack widget by calling Stack();


Here are some of the commonly used properties of the Stack widget:


Stack(
   children: [],
   alignment: ,
   fit: ,
   textDirection: ,
);


WebApp

In flutter you are able to put your app on ios, android, and the web. To get it on the web is very easy. All you need to do is go into your terminal and say flutter run -d chrome and it will run your code on the web. Your UI will probably look weird if you designed it for mobile but if you change the code it can look nice for both.


MediaQuery

MediaQuery is used to get data on the size of your screen, the positioning of your screen, etc. to help you better tailor your app to different phone variants.


The two main ones I’ll be talking about are the size and orientation function of MediaQuery that allows you to get the size and orientation of the phone. You can make a variable using MediaQuery and store the size of the screen in it like this:


Size size = MediaQuery.of(context).size;


Now, all you have to do is call size to get the size of the screen, like this!



import 'material.dart';

class Home extends StatelessWidget () {
   @override
   Widget build(BuildContext context) {

   Size size = MediaQuery.of(context).size;

       return Scaffold(
           body: ListView(
               children: [
                   Container(
                       color : Colors.red,
                       height: size.height,
                       width: size.width,
                   )
               ]
           );
       );
   }
}


This will make it so the container will take up the whole screen since I specified that it should take up the screen width and screen height. You can also do something like this!


import 'material.dart';

class Home extends StatelessWidget () {
   @override
   Widget build(BuildContext context) {

   Size size = MediaQuery.of(context).size;

       return Scaffold(
           body: ListView(
               children: [
                   Container(
                       color : Colors.red,
                       height: size.shortestSide,
                       width: size.shortestSide,
                   )
               ]
           );
       );
   }
}

I made it so that the Container would have a height and width of the shortestSide. You can also do this with longestSide and it will get the value of the longest side.


kIsWeb

kIsWeb is a function that you can use to detect whether or not your code is running on a mobile or on the web. Here’s an example:


import 'material.dart';

class Home extends StatelessWidget () {
   @override
   Widget build(BuildContext context) {
       return Scaffold(
           appBar : AppBar(
               title: Text("Home")
           ),
           body: ListView(
               children: [
                   Builder(builder: (context) {
                           if (kIsWeb) {
                               return Row(
                                   Container(color : Colors.red),
                                   Container(color : Colors.green)
                               );
                           } else {
                               return Row(
                                   Container(color : Colors.orange),
                                   Container(color : Colors.blue)
                               );
                           }
                       }
                   )
               ]
           );
       );
   }
}


You can create an if and else statement to build out you app depending on whether it’s on a mobile or on the web to build out different UI’s that work with the interface.


With the if and else statement you can also use !kIsWeb to say if it isn’t on the web aka on a mobile, then do this.


Different Kinds of Buttons

While buttons seem like a pretty simple thing to have in an app they are very important. And in flutter, there are a lot of buttons you can use. So here’s a list of buttons with descriptions:


Flat Button

A button with not much decoration and no elevation. The two required fields are child and onPressed().


Raised Button

A raised button is pretty much the same as the FlatButton just with an elevation that increases when you press it.


Floating Action Button

A floating action button is a button that can have a child as an icon but can also have anything else as its child including a Text Widget. It is usually used in a Scaffold using the floatingActionButton function.


Icon Button

A icon button is a button that has an icon as its child.


InkWell

An InkWell is a button you can put anything in and then if you click it it will do whatever you say it should do. Instead of an onPressed() function is uses an onTap() function instead.


Gesture Doctor

Gesture Doctor is basically an InkWell except with a lot of other functions it can preform when pressed.


Activity Button

An activity button is another button you can use that allows you to put borders around your button directly. And you are able to put images inside your button along with some other functions.


Ghost Button

A ghost button cannot have images but you specify your border color, your fill color, your text color, etc. directly inside of the button.


These are just some buttons that you are able to use and there are probably more that you can use with different functions you can use inside of them.



GestureDetector

GestureDetector s a way to make anything a button that is able to carry out a function wen pressed. This becomes especially useful when you want a certain UI to your buttons but it would be extremely hard to do it with a RaisedButton for example.


All you have to do is wrap whatever you want to be a button in a GestureDetector and then use the onTap property to carry out whichever function you would like.


Making Your Own Widgets

Sometimes you want to use something with the same design over and over again without anything changing. This will be a waste of code if you build it and specify all the UI properties multiple times. This doesn’t need a custom widget, what is needs is a new widget you build yourself.


The way you do this is by creating a new dart file and importing material.dart. Then, instead of saying Class, you would say widget. Or, let’s say you were customizing your own TextStyle, then you would say TextStyle. For example:



import package:flutter/material.dart”;

Widget nameOfWidget(BuildContext context) {

}


This is an example of a blank widget. Inside you would say return and then build out whatever widget you would like. Then you would call the widget by the name you set in order to build the widget you created. For example:



appBar: nameOfWidget(context)


ListTile

ListTile is a type of widget that can be a button. The two properties you’ll mainly be using is:


title

leading


These two creates two things in a row...for example:



ListTile(
   title: Text("Email"),
   leading: Icon(Icons.mail),
),


You are also able to use the property onTap


TextFormFields

TextFormFields are things that you can write stuff in. TextFromFields are used very often in apps of all kind. There are lots of different functions you can use with text form fields.



Void

A void is a function that doesn’t return anything. So, if you were making a function that validates whether or not you put in the right username and password, it doesn’t return anything, so you would use a void for that.


CupertinoActionSheet

CupertinoActionSheets are the things in iOS platforms that pops up from the bottom like this:


Here’s how you would usually make a CupertinoActionSheet:



RaisedButton(  // First create a button that will show the CupertinoActionSheet
   color: Colors.black,
   child: Text(
       'Click me',
       style: TextStyle(color: Colors.white),
   ),
   onPressed: () {  // onPressed property open the CupertinoActionSheet
       final act = CupertinoActionSheet(
           title: Text('Select Option'),  // This is a Text that is at the top
           actions: <Widget>[
               CupertinoActionSheetAction(  // option
                   child: Text('1'),
                   onPressed: () {},
               ),
               CupertinoActionSheetAction(
                   child: Text('2'),
                   onPressed: () {},
               ),
               CupertinoActionSheetAction(
                   child: Text('3'),
                   onPressed: () {},
               )
           ],
           cancelButton: CupertinoActionSheetAction(  // Cancel
               child: Text('Cancel'),
               onPressed: () {
                   Navigator.pop(context);
               },
           )
       );
       showCupertinoModalPopup(  // makes it pop up
           context: context, builder: (BuildContext context) => act);
   },
),


One negative of the CupertinoActionSheet is that it only works with iOS so if you are trying to make an iOS and Android compatible app you probably shouldn’t use this.


CupertinoActivityIndicator

A CupertinoActivityIndicator is used to create a loading icon that spins around just like what you would see in many other apps. This is used for when retrieving data and it is taking a long time you can say go to this screen with a CupertinoActivityIndicator.


The widget is this CupertinoActivityIndicator and has a few perimeters including:


animating: this is a bool value (which means either true or false) that you put to say whether or not you want it to move

radius: this is for setting how big you want your CupertinoActivityIndicator to be


One negative of the CupertinoActivityIndicator is that it only works with iOS so if you are trying to make an iOS and Android compatible app you probably shouldn’t use this.


CupertinoAlertDialog

CupertinoAlertDialog is a widget that displays a popup message. The things about pop up messages is that you will need to put a button that shows the message or something to trigger it.


Here’s the code to make on:


RaisedButton(
 child: Text('Open popup'),
 onPressed: () {
   showCupertinoDialog(
     context: context,
     builder: (context) => CupertinoAlertDialog(
       title: Text('My message!'),
       actions: [
         CupertinoDialogAction(
           child: Text('Close'),
           onPressed: () => Navigator.pop(context)
         ),
       ],
     )
   );
 },
)


One negative of the CupertinoAlertDialog is that it only works with iOS so if you are trying to make an iOS and Android compatible app you probably shouldn’t use this.


Maps

Maps are like dictionaries. There is a word, and then a definition. They are both linked together because you don’t want to ask for a word and get a definition to a different word, that wouldn’t make sense. Maps can be used to store usernames and passwords because you want your username and password to be linked just like in a dictionary.


Here’s an example of a Map:


Map<String, String> database = {"username" : "password"};

The <String, String> part of the code above is specifying which type of data you want stored in your map. Afterwards I say database. That is me naming the Map. And then I put in the data. The : is to link the data together.



Basic Database

Database


Sign Up

Sign Up


What are _ used for?

Underscores are often used before variables. This is because adding an underscore makes it so that the variable can only be modified or used in that .dart file. And becomes particularly useful when you are using a database. For example, let’s say you’re trying to create a new user and you accidentally modify another user's username. That could be prevented with an underscore before the variable you use.



--


Resources


To learn the basics of Flutter, you can watch my flutter basics video here:



To learn more and expand your knowledge I have many other videos you can check out: