Flutter
Introduction
Why Flutter created in 2017
- Compiles to native, JIT and Ahead of Time
- Fast Development
- Single Code Base
- Uses Dart
Resources is https://github.com/simoales/flutter
Installation
Flutter
You can switch versions of flutter using the channel option where there are options of master, dev, beta etc. See https://github.com/flutter/flutter/wiki/Flutter-build-release-channels
sudo snap install flutter --classic
sudo snap install flutter-gallery
flutter channel dev
flutter upgrade
flutter config --enable-linux-desktop
You will need to specify the path to android studio
flutter config --android-studio-dir="/opt/android-studio-4.1/android-studio"
Android Studio
For Android Studio the flutter SDK will be in /home/(username)/snap/flutter/common/flutter
Flutter doctor
You can run flutter doctor to see if all went well. This is what I got
flutter doctor
[✓] Flutter (Channel dev, 1.25.0-8.0.pre, on Linux, locale en_NZ.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Linux toolchain - develop for Linux desktop
[!] Android Studio (not installed)
[✓] VS Code (version 1.52.0)
[✓] Connected device (1 available)
Creating a Project
In VS Code run flutter doctor and then flutter new project. Project names must be in lower case. e.g. hello_flutter. This opens a new VS Code with the project. The import contains the widgets to use and the rest just configures the widgets on the screen. I.E. Text is like a <Text /> tag in react or angular.
import 'package:flutter/material.dart';
void main() {
runApp(Center(
child: Text("Fred Was Ere",
textDirection: TextDirection.ltr,
style: TextStyle(backgroundColor: Colors.blue)),
));
}
When familar we can create a project with the flutter cli
flutter create app_widgets
A Bigger Example
So a bigger example might be
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: "My lovely App",
home: Scaffold(
appBar: AppBar(
title: Text("App Bar Title"),
),
body: Material(
color: Colors.deepPurple,
child: Center(
child: Text(
"Fred Was Ere",
textDirection: TextDirection.ltr,
style: TextStyle(color: Colors.white, fontSize: 36.0),
),
),
),
),
));
}
Classes
Things are getting a big large so we need to break the code down. We do this by writing our own classes. We can derive a class from StatelessWidget to do this.
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "My lovely App",
home: Scaffold(
appBar: AppBar(
title: Text("App Bar Title"),
),
body: Material(
color: Colors.deepPurple,
child: Center(
child: Text(
"Fred Was Ere",
textDirection: TextDirection.ltr,
style: TextStyle(color: Colors.white, fontSize: 36.0),
),
),
),
),
);
}
}
Fat Arrow
Dart supports the fat arrow approach so we can so
import './screens/home.dart';
void main() {
runApp(MyWidget());
}
Can become
import './screens/home.dart';
void main() => runApp(MyWidget());
Adding Logic
No surprises here. We can add functions within the class declaration.
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Material(
color: Colors.deepPurple,
child: Center(
child: Text(
sayHello(),
textDirection: TextDirection.ltr,
style: TextStyle(color: Colors.white, fontSize: 36.0),
),
),
);
}
String sayHello() {
var hello;
DateTime now = DateTime.now();
if (now.hour < 12) {
hello = "Good Morning";
} else if (now.hour < 18) {
hello = "Good Afternoon";
} else {
hello = "Good Evening";
}
return hello;
}
}
Basic Widgets and Concepts
The basic widgets and Concepts are
- Container
- Text
- Row & Column
- Image
- RaisedButton
- AlertDialog
- Box Constraints
- Size, Margin and Padding
Containers
They are as they sound. It is worth noting the width and height are controlled by the parent. Look at https://flutter.io/layout. To bypass the constraint of the parent you need to wrap your widget in a widget which supports this. E.g. Center widget.
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Container(
width: 192.0,
height: 96.0,
alignment: Alignment.center,
color: Colors.deepOrangeAccent,
child: Text(
"Pizza",
textDirection: TextDirection.ltr,
),
));
}
}
Margins And Padding
Margins and Paddings use the EdgeInsets.All and EdgeInsets.Only constructor. So to set a margin we can do.
...
child: Container(
width: 192.0,
height: 96.0,
margin: EdgeInsets.only(left:50.0),
padding: EdgeInsets.All(10.0),
...
Fonts
Copy the fonts to a directory. The file pubspec.yaml contains the configurations.
fonts:
- family: Oxygen
fonts:
- asset: fonts/Oxygen-Regular.ttf
- asset: fonts/Oxygen-Bold.ttf
weight: 700
- asset: fonts/Oxygen-Light.ttf
weight: 300
Now we can use the font with the Text Widget
...
child: Text(
"Pizza",
textDirection: TextDirection.ltr,
style: TextStyle(
fontFamily: 'Oxygen',
fontWeight: FontWeight.w300,
),
...
Rows and Columns
These seem to work the same as flex box.
...
child: Row(
children: <Widget>[
Text(
"Margherita",
textDirection: TextDirection.ltr,
style: TextStyle(
fontFamily: 'Oxygen',
fontWeight: FontWeight.w300,
),
),
Text(
"Tomato, Mozzarella, Basil",
textDirection: TextDirection.ltr,
style: TextStyle(
fontFamily: 'Oxygen',
fontWeight: FontWeight.w300,
),
),
],
),
...
The result is items which overflow the row because the text exceeds the width of the phone.

Wrapping in Expanded means that the row will wrap like flexbox wrapping.
Expanded(
child: Text(
"Tomato, Mozzarella, Basil",
textDirection: TextDirection.ltr,
style: TextStyle(
fontSize: 30,
fontFamily: 'Oxygen',
fontWeight: FontWeight.w300,
),
),
),