Flutter
Introduction
Installing Flutter
A comprehensive installation guide can be found on the flutter website.
Setup a Flutter-project in VS Code
Open Visual Studio Code and choose the “Flutter: New Project” command.
To start the iPhone simulator, type the following command into your terminal:
open -a Simulator
To run your app in an iPhone Simulator, start your app using the play button on the top right of the text editor.
Tips for using Dart & Flutter in VS Code
The Dart & Flutter extensions of VS Code offer some neat features:
- Using
cmd+shift+p
and using the “Quick fix…”-command you can encapsulate your widget in a new widget, swap it with its parent-widget…
Flutter
Architecture of a Flutter app
Everything in Flutter is a widget and you build widgets upon widgets like lego-blocks. In a new app you create a Scaffold. Within the Scaffold you can create e.g. an AppBar and a Container for the body of your app. This Container can contain a Column that contains widgets that stack vertically or a Row that contains widgets that get aligned horizontally. This creates a widget tree.
Scaffold
/ \
AppBar Container
\
Column
\
other widget
The information, where your widget is located in the widget tree is saved in the BuildContext. Every build function needs a BuildContext, to save where the widget goes.
The boilerplate stuff
First you import the packages i.e. for the style sheets:
import 'package:flutter/material.dart';
Then you define the main function (the starting point of your app):
void main() {
// starts your app
runApp( // defines the style sheets that you can use
MaterialApp( : Scaffold( // organizes layout of your app
home: Text("Hello World"),
body,
),
)
);}
Scaffold
The Scaffold is used to organize the layout of your (material) app and contains the widgets. These are the common components
: Scaffold(
home: AppBar(...),
appBar: Text("Hello World"),
body: FloatingActionButton(...),
floatingActionButton: Drawer(...), //menu that you can pull in from the side
drawer: BottomNavigationBar(...)
bottomNavigationBar )
<img src=“/img/Scaffold.png”, height=500px>
AppBar
AppBars are usually title bars in your app that also contain iconButtons.
AppBar(: const Text('test'),
title: Colors.blueGrey[900],
backgroundColor: <Widget>[ // action that happens when you click on the button
actions: const Icon(Icons.add_alert),
IconButton(icon: () {...}
onPressed )
Image
You can integrate Images from different sources by using different image objects from different parent classes.
// displays content from image class
Image( :NetworkImage('https://api.flutter.dev/flutter/widgets/Image-class.html'), // displays image from network
image )
If you load images from your image assets folder, you need to change the pubspec.yaml file in your project’s root directory. Under assets
you need to add the relative location of your image:
flutter:
uses-material-design: true
assets:
- images/
Container
A container is a layout box that you can position and fill with content.
Container(: Colors.white,
color: Text("Hallo"),
child: 50,
width: 50,
height: EdgeInsets.all(20), // the margin on all 4 sides to your container
margin: EdgeInsets.fromLTRB(5, 5, 10, 10) // the padding of the content in your container padding
To add a background image, you can use the decoration parameter:
Container(: BoxDecoration(
decoration: DecorationImage(
image: AssetImage("images/background.png"),
image: BoxFit.cover),
fit,
)...)
SafeArea
The SafeArea widget constraints its children to the area of the screen that is easily visible (not below the notch of the selfie-camera).
SafeArea(: ...
child )
Column and Row
Column and Row widgets organize their children vertically and horizontally respectively.
Column(<Widget>: [
children ...),
Container(:10), // This provides some spacing between the elements
SizedBox(height...)
Container(,
]: MainAxisSize.min, // if you don't want it to spread across the whole height
mainAxisSize: VerticalDirection.up, // if the children should be ordered reversely
verticalDirection: MainAxisAlignment.end, // if you want the children to stack up from the bottom
mainAxisAlignment: CrossAxisAlignment.stretch, // this stretches the children to the width of the screen
crossAxisAlignment )
Expanded
The expanded widget must be contained in a Column or a Row widget. If fills out the available space in its parent container.
Row(: <Widget>[
children
Expanded(: Image(...)
child
) )
Padding
To add padding around another widget (e.g. that does not have a padding-attribute), you can use the padding widget:
Padding(
child:
padding )
Slider
If you use a slider, you need to set its starting value, min and max. To be able to drag the slider around, you need to update the state of the slider:
double sliderVal = 20.0;
Slider(: sliderVal,
value: 10,
min: 30,
max: (double newVal) {
onChanged{
setState(() = mewVal;
sliderVal });
}
)
Visibility
You can conditionally show your buttons or contents using the Visibility widget:
Visibility(: FlatButton(...),
child: true
visible )
Icons
Icons are accessible like this (check mark as example):
Icon(.check
Icons )
Custom widgets
The basic idea of widgets in flutter is composition: The widgets are composed of several simpler widgets that depend on one another (not inhereted). This is also how you’d make custom widgets.
class myOwnButton extends StatelessWidget {
@override
{
Widget build(BuildContext context) return RawMaterialButton(
... // here you combine/define what you want
);}
}
Gesture Detector
You can check if an widget got tapped, forcedPressed, doubletapped… with a Gesture Detector as a parent:
GestureDetector(: () {
onTap{...});
setState(() },
: ... child
Theme
The coloring, fonts, styles throughout the app are defined in the ThemeData
widget. You can switch themes
MaterialApp(:ThemeData.dark() //uses the standard dart theme
theme )
You can adapt the default themes
MaterialApp(.ThemeData.dark().copyWith(
theme: ...
primaryColor
) )
or you can define your own ones.
MaterialApp(: ThemeData(
theme: Colors.lightBlue,
primaryColor: textTheme(...) //Text has its own theme
textTheme...
) )
You can also use very detailed themes for other widgets. You do it by wrapping the widget in its theme:
SliderTheme(: SliderTheme.of(context).copyWith(
data... // adapt theme to your liking
,
): Slider(
child... // define Slider min, max, onChanged...
) )
Creating App Icons
To create an app icon from an image file, go to www.appicon.co and have it transformed to different resolutions. For Android, you use the newly created “mipmap-…”-folders and replace the respecitve folders in “/android/app/src/main/res” with them. For iOS, you use the newly created folder “Assets.xcassets” and replace the folder “/ios/Runner/Assets.xcassets” with it.
Run the app on a physical device
To run your app on a physical iPhone or Android device, you can follow the steps on this flutter-webpage.
Stateful and Stateless widgets
The state of your app can be imagined as the “state of ahffairs” in your app during runtime. There are two categories of widgets if it comes to state:
- Stateless widgets: These are not meant to change their state during runtime -> The text, images aso. stay the same. Like in a museum.
- Stateful widgets: These are supposed to change their state during runtime -> menues that appear, values that change upon user input. Like in a workshop.
Stateless widgets have a build function:
class myClass extends StatelessWidget {
@override
{
Widget build(BuildContext context) return Container(
);}
}
Stateful widgets have a State on top of the widget itself:
class myWidget extends StatefulWidget {
@override
=> _myWidgetState();
_myWidgetState createState() }
class _myWidgetState extends State<myWidget> { // The State-part tracks and updates the screen as the state changes. This is where you'd put the stuff normally in a stateless widget.
@override
{
Widget build(BuildContext context) return Container(
);}
}
Change the state
If you want to change the State of your app, you need to call setState()
:
FlatButton(: () {
onPressed{
setState(() ... // The new state you want to have
});
},
...)
The variables that you changed are marked and the widgets that use them, are redrawn on the screen.
Multi-Screen Apps
Multi-screen apps contain different pages that are accessible by different routes. The screens are organized in a stack. You push and pop pages/screens on and off your stack. You need to specify the context you are coming from (where you are in the app -> BuildContext
) and a route (where we want to go).
: FloatingActionButton(
child: () {
onPressed.push(
Navigator,
context
MaterialPageRoute(: (context) {
builderreturn Screen2();
}));
}),
If you have several buttons, it’s easier to use named routes. You define these routes in the main build function of your app:
MaterialApp(: '/zero',
initialRoute: {
routes'/zero': (context) => Screen0(),
'/first': (context) => Screen1(),
'/second': (context) => Screen2(),
},
)