65
FLUTTER WITH VSC MOBILE PROGRAMMING Ahmad Hanis Mohd Shabli 9/11/19 STIW2044

FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

FLUTTER WITH VSC MOBILE PROGRAMMING

Ahmad Hanis Mohd Shabli 9/11/19 STIW2044

Page 2: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

1

Table of Contents Introduction to Flutter ............................................................................................................................ 3

Why Flutter? ....................................................................................................................................... 3

Flutter Installation ................................................................................................................................... 4

Introduction ........................................................................................................................................ 4

Requirement ....................................................................................................................................... 4

Android Studio .................................................................................................................................... 4

XCode .................................................................................................................................................. 5

Visual Studio Code .............................................................................................................................. 5

Git ........................................................................................................................................................ 6

Flutter SDK .......................................................................................................................................... 6

Testing Flutter application .................................................................................................................. 7

Flutter Basic ............................................................................................................................................ 8

New Project ......................................................................................................................................... 8

Basic Layout ...................................................................................................................................... 12

Column Layout Widget ..................................................................................................................... 14

Text Widget ....................................................................................................................................... 15

TextField Widget ............................................................................................................................... 16

Button ............................................................................................................................................... 17

User Defined Widget ......................................................................................................................... 18

Simple Flutter Application .................................................................................................................... 21

Basic Input Output ............................................................................................................................ 21

Stateless vs Stateful Widget .......................................................................................................... 21

Simple Calculator .............................................................................................................................. 24

Widget Decoration (new widget!) ................................................................................................ 26

Assignment .................................................................................................................................... 28

BMI Calculator ................................................................................................................................... 28

Image Widget (new widget!) ........................................................................................................ 31

Pubspec.yaml ................................................................................................................................ 32

Play Audio (new widget!) .............................................................................................................. 34

Library ........................................................................................................................................... 34

Food Ninja ............................................................................................................................................. 39

Splash Screen .................................................................................................................................... 40

Debug Options .............................................................................................................................. 42

SizedBox (new widget!) ................................................................................................................. 43

LinearProgressIndicator Widget ................................................................................................... 43

Page 3: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

2

Renaming main.dart to splashscreen.dart .................................................................................... 43

Login Screen ...................................................................................................................................... 45

Page Navigation ............................................................................................................................ 45

Handling Layout Overflow ............................................................................................................ 49

Padding option .............................................................................................................................. 49

Alignment option .......................................................................................................................... 50

SizedBox Widget ........................................................................................................................... 50

MaterialButton Widget ................................................................................................................. 50

GestureDetector Widget ............................................................................................................... 50

CheckBox Widget .......................................................................................................................... 51

Navigator Widget .......................................................................................................................... 51

Handling Preferences .................................................................................................................... 52

Register User ..................................................................................................................................... 54

User Registration Process ............................................................................................................. 59

Server Application Directory ......................................................................................................... 63

Database Connector...................................................................................................................... 64

Page 4: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

3

Introduction to Flutter

Flutter is an open-source software development kit framework developed by Google to quickly build

IOS and Android mobile application with only single code base. Single code base allow developer to

develop application faster and cheaper. Flutter also compile code into native program that can run

much faster on IOS and Android. Flutter being supported by Google allow for wide variety of support

form the tech giant and also being open source in nature, with a lot of development communities

build sample application and libraries for Flutter.

Flutter use Dart programming language as its core programming code. Interface design and logic codes

can be combined into one Dart file. So far, Official Flutter dev didn’t release any GUI designer where

it allows for visual interface design using drag and drop feature something like what Android Studio

has provided. However, there are a number of online visual GUI design application available to

accelerate development.

Why Flutter?

There are a number of hybrid and cross platform mobile development platform such as Ionic, React,

React Native, Framework 7, and Xamarin. However, most of them are based on HTML technologies

where the application is wrap in a webview. Hybrid app needs native library to access to mobile

devices hardware such as sensors, camera, or other low-level hardware. Dependencies on these

libraries is quite difficult due to changes in mobile hardware is frequent. Webview wrapper also

produce bigger installation files compared to native application that produce small installation file.

These will lead to performance issue in hybrid application compared to native application. Read more

on hybrid vs native https://codeburst.io/native-app-or-hybrid-app-ca08e460df9.

The application written in flutter is compiled ahead-of-time into native ARM code, not at runtime as

in React Native. This gives better performance because there’s no JS bridge in the middle to parse and

execute the code.

Some big companies are already using it, such as Alibaba (Android, iOS), Tencent (Android, iOS), and

Google Ads (Android, iOS). Alibaba also used Flutter to build its Xianyu app (Android, iOS), currently

used by more than 50 million customers in China.

Page 5: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

4

Flutter Installation

Introduction Preparing a fast and trouble-free development environment is important to avoid any delays in

developing a solution. The following guideline shows how prepare and install Flutter in a computer.

The installation process might change in the future due to new Flutter version.

Requirement Minimum requirement – i3 Intel based processor with 4GB of RAM. With this requirement, most of

the application and services to run Flutter run at very low performance. However, it is not

recommended to use this requirement. It is recommended to upgrade computers RAM to at least 8GB

with SSD main drive.

Recommended requirement – i5 and above processor with 8GB of RAM and SSD drive. It is suggested

to use this setup to help ease development process. Even though Visual Studio Code is considered as

non-intensive IDE, the other development components such as Android SDK and AVD demand

substantial amount of resources from computer. That can further reduce the performance of

computer due to limited resources available.

Android Studio Android studio is a development environment for developing mobile application for Android only

operating system. Even though the IDE itself it is not needed to during development process, the other

component provided by Android Studio such as AVD is needed to run Android virtual devices. AVD use

to test application develop using Flutter framework. Android Studio also can be used to develop

Flutter; however, it is not recommended due to high resource usage by Android Studio IDE that can

further reduce computer performance. Android Studio installer is available for Windows, MacOS and

Linux operating system.

Page 6: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

5

Install Android studio with the latest SDK and tools using the recommended link suggested by official

Android Studio from the following website: https://developer.android.com/studio. Make sure to

Install and update SDK manager to the latest version of available SDK and tools. Download and create

new AVD to enable application testing on virtual device. Test newly created AVD to make sure it is

working as expected.

XCode XCode is development environment only available on MacOS computer. Please Install XCode to enable

IOS emulator.

Visual Studio Code Visual Studio Code is lightweight development IDE to be used with Flutter framework. The installer is

available on https://code.visualstudio.com for Window, MacOS and Linux operating system.

Download the required installer and perform installation according to guideline in the installer.

Page 7: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

6

Git Git is a free and open source distributed version control system that allow user to download files

through terminal based application. Git is required to download Flutter SDK to local directory.

Download git from its official website: https://git-scm.com. The installer is available for Windows,

MacOS and Linux. Follow the Installation guide provided by the installer. Once the installation

completed, test the following git command through terminal. It should return current git version.

Flutter SDK Flutter SDK is available for download from https://flutter.dev/docs/get-started/install. Select the

operating system version that needed for the installation. The following guide is for Windows however

for other operating system, refers to online documentation available in official Flutter website. To

install Flutter SDK, create a new directory call flutter in drive C:\ (also can be in any other directory).

Then use command prompt terminal and access the directory. Do not install Flutter in a directory like

C:\Program Files\ that requires elevated privileges).

Page 8: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

7

Next, download Flutter sdk using git clone command as follows:

git clone -b stable https://github.com/flutter/flutter.git

Update Flutter Environment

Update Flutter using Flutter Doctor

Install Flutter extensions to Visual Studio Code.

Testing Flutter application

on Android AVD/or IOS simulator.

Page 9: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

8

Flutter Basic Creating new flutter project using Visual Studio Code is quite different then what available through

Android Studio or XCode. The following steps will describe how a new Flutter project can be created.

These processes might change in the future with new Flutter/Visual Studio Code release.

New Project Create new flutter project by selecting menu View/Command Palette and type “Flutter: New Project”

or press “Ctrl+Shift+P”.

Provide project name using only single words with all small letters.

Save the project into a workspace folder.

Page 10: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

9

The following process may take a while due to VSC downloading all the required component from the

Internet. Wait for VSC to completely create project directory. This step requires Internet connection

(only require for every new project creation).

Once project have been successfully created, the following interface will be presented.

The default code provided by Flutter shows quite a lot of unnecessary code. To understand basic

Flutter programming structure, proceed to install Awesome Flutter Snippets by downloading from

Extensions Marketplace from Command Palette or press “Ctrl+Shift+X”. Search for Awesome Flutter

Snippets then download and install. Snippets make available a collection of ready-made code that can

be easily access from keywords type on a keyboard. Proceed with Awesome Flutter Snippets

installation (installation process will only require once).

Page 11: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

10

Download and install the extension above then delete all the codes from default main.dart. Then

inside the main.dart workspace, press button “m” and select “mateapp” from the first popup menu

option and then press enter.

The following code will be automatically appear in main.dart. This is the most basic code structure for

Flutter Dart programming layout. It shows a simple layout screen with a text in the middle with Hello

World writing inside.

import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Material App', home: Scaffold( appBar: AppBar( title: Text('Material App Bar'), ), body: Center( child: Container( child: Text('Hello World'), ), ), ), ); } }

Page 12: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

11

The above code can be tested on AVD or IOS emulator. Press button F5 on Windows computer or

menu Debug/Start Debugging. Make sure at least one AVD is available. If no AVD available please

configure new AVD from Android Studio AVD manager. Application can also be tested using real device

by connecting the device to the development computer with development/debug mode enable. A

selection of device/avd will be presented with this option. Allow the device fingerprint debug mode.

Select the required testing platform and wait until the installation completed on device or AVD.

Once installation completed, the application will display a simple interface with a text in the middle

with “Hello World” text. On the right side, a bar display “DEBUG” shows the app is in debug mode.

Flutter allow fast development mode call “Hot Reload” that allow developer to modify their code and

quickly view their modified interface/code in an instant on the AVD or device. This handy feature is a

time saver where most of the time taken is when updated code need time to reinstall back on the

device on Android Studio or XCode.

Any new Flutter mobile application project will follow the above process except for installation of

Awesome Flutter Snippets plugin where it only needed once. Get use to these procedures for any

new Flutter project.

Page 13: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

12

Basic Layout import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Material App', home: Scaffold( appBar: AppBar( title: Text('Material App Bar'), ), body: Center( child: Container( child: Text('Hello World'), ), ), ), ); } }

Flutter code like any other programming language start with statement to import required package

and for Flutter it is a mandatory library from ‘flutter/material.dart’. This package contains all basic

interface component/widget such as buttons, and text input which follow Android material design.

Next statement which is void main() method is the method that first initialized when application first

execute. Main method then called the class called MyApp() class to initialized and draw interface

based on defined widget.

Layout interface in flutter handle by a class and in above example define by MyApp() class that extend

to another parent class call Stateless Widget. Stateless widget is a component that do not store any

data (more on this later). Another type of layout widget is Statefull Widget that manage widget that

requires update to be redrawn back on the layout.

Page 14: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

13

The overall structure of a widget is hold by Scaffold widget. Scaffold contain an AppBar (Application

Bar) and a Body that host all the interface widgets. Body of the layout set to center using Center

widget. Center widget contain one child Container and finally Container widget contain one Text

Widget. Container in this code hold the entire layout interface where text display in the middle of the

screen.

The above layout displays overall layout structure using basic Flutter code. However, no other

component can be added to the interface since widget container can only host one child widget. To

add more widget to the above layout such as button, image, and input text; continue with basic layout

management using column in the next section.

Page 15: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

14

Column Layout Widget

Linear layout or column-based layout is the most basic layout for mobile interface. All widget

component can be arranged in column-based stack right on top of each other. To allow the above

awesome basic Flutter code snippet to accept multiple widget, a few modifications needed as follows.

Right click on body and choose Refactor menu.

Select Wrap with Column from menu option.

code will turn into the following:

import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Material App', home: Scaffold( appBar: AppBar( title: Text('Material App Bar'), ), body: Column( children: <Widget>[ Center( child: Container(

Page 16: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

15

child: Text('Hello World'), ), ), ], ), ), ); } }

The Above code now will accept multiple Widget components such as button, text input and label.

This is due to the changes in body structure that accept row with multiple widget children’s using

arrays[].

children: <Widget>[ Center( child: Container( child: Text('Hello World'), ), ), ],

Text Widget Text widget is a simple widget that allow text to be drawn on the layout. To add text widget, simply

by adding the following Widget arrays.

import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Material App', home: Scaffold( appBar: AppBar( title: Text('Material App Bar'), ), body: Column( children: <Widget>[ Text('Hello, How are you?'), Text('Welcome to Flutter'), Text('Develop with Visual Code Studio'), ],

Page 17: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

16

), ), ); } }

There are three texts display in rows from the above example. Each on top of each other.

body: Column( children: <Widget>[ Text('Hello, How are you?'), Text('Welcome to Flutter'), Text('Develop with Visual Code Studio'), ], ),

There are more options that available to Text such as formatting, event handling, etc. For further

reference go to https://api.flutter.dev/flutter/widgets/Text-class.html.

TextField Widget

Text fields is another usefull widget that allow users to type text into an app. They are used to build

to get input from user. It is one of the most used widgets in mobile application interface.

children: <Widget>[ Container( child: Text('Email'), alignment: Alignment.centerLeft, ), TextField(), ],

Noted that a container has been used to control alignment for the Text above and set it to left

alignment. A simple widget call using TextField() allow the widget to appear on the layout.

Page 18: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

17

More reference available from Flutter cookbook for TextField from the following link

https://flutter.dev/docs/cookbook/forms/text-input.

Button

Button is another interaction widget that allow user to click and perform task. There are a number of

button widget available for Flutter such as RaisedButton, FlatButton, Material Button, Floating

Button, and etc. To add button widget, simply insert RaisedButton with the following options inside

Widget array.

children: <Widget>[ Container( child: Text('Email'), alignment: Alignment.centerLeft, ), TextField(), RaisedButton( child: Text("Press Me"), onPressed: _pressMe, )

RaisedButton widget requires one child widget for label and one event method onPressed: that calls

_pressMe method. Add press_me method inside the class or click on the yellow lightbulb option to

quickly access method creation. Add a simple print statement to print on debug console a text.

void _pressMe() { print("Hello World"); }

Page 19: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

18

User Defined Widget

“Everything in Flutter is a widget”. Understanding this concept is critical in order to fully recognized

the full potential of Flutter. User can define their own widget by combining several widgets together

or making their own custom widget. User defined widget allow for better grouping of similar widget

performing operation.

To create user defined widget, create a new project. Use “mateapp” plugin to create basic Application

interface. Then refactor Container with “Wrap with Column” to create Widget array. This will allow

layout to accept multiple widget. Remove the container from Widget array.

import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Material App', home: Scaffold( appBar: AppBar( title: Text('Material App Bar'), ), body: Center( child: Column( children: <Widget>[], ), ), ), ); } }

Page 20: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

19

Create another stateless class inside main.dart by press key s. A menu will appear after button s is

pressed. Select statelessW to automatically add a stateless class

Give the class name MyWidget and update with the following code

class MyWidget extends StatelessWidget { const MyWidget({Key key}) : super(key: key); @override Widget build(BuildContext context) { return Container( child: Column( children: <Widget>[ Text('Hello from MyWidget'), Text('Welcome to MyWidget'), ], ), ); } }

Update MyApp class widget array with the three Text widgets as follows then run the project.

children: <Widget>[ Text('Hello from MyApp'), Text('Welcome to MyApp'), MyWidget(), ],

Page 21: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

20

The project shows user defined widget with two Text widgets in MyWidget class. This shows the

grouping of multiple Widgets can be done using multiple classes (class can also be in different dart

file).

Page 22: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

21

Simple Flutter Application

The following section will describe how to build simple application using just three basic widgets

introduced in the previous section. These applications will contain basic input, process and output.

Basic Input Output

The following application example will take input from input TextField and then when user press a

button, the value will be transferred to a Text. In this example a new state will be introduce called

StatefulWidget. This is due to when a widget needs to be able to accept dynamic new changes to its

content such as changes in the content display in a Text.

The following code is based on the previous topic that shows a simple interface with additional one

output text at the bottom.

children: <Widget>[ Container( child: Text('Email'), alignment: Alignment.centerLeft, ), TextField(), RaisedButton( child: Text("Press Me"), onPressed: _pressMe, ), Text("Output"), //new Text for output is here ],

Stateless vs Stateful Widget

The default class that contain this widget extends to StatelessWidget class. Stateless widget cannot

change its state and only suitable for widget that immutable (don’t change). These widgets such as

Text and icon don’t change most of the time and only need to be called once during build hence

suitable for StatelessWidget.

Page 23: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

22

Stateless widget need to be refactored as StatefulWidget if the application needs widget to be able

to change its state. To refactor, right click on the class and select Refactor from the menu. Then select

Convert to StatefulWidget from the menu.

This option will automatically convert the widget into StatefulWidget class with class that extend to

State. The rest of the interface remain the same. StatefulWidget can change (redraw) their state many

times throughout the application lifecycle. Checkbox, Radio and TextField are some of the stateful

widgets.

class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { @override Widget build(BuildContext context) { .../

To get value from TextField, a controller and a variable needed to be defined inside _MyAppState

above. Add the following two instruction inside the class.

class _MyAppState extends State<MyApp> { final TextEditingController _emcontroller = TextEditingController(); String _email2 = "";

A controller allows for TextField to store its value and later access by another widget. Next step is to

update Widget array with the following:

children: <Widget>[ Container( child: Text('Email'), alignment: Alignment.centerLeft, ), TextField(controller: _emcontroller), RaisedButton( child: Text("Press Me"), onPressed: _onPressed,

Page 24: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

23

), Text("Submitted Text: $_email2"), ],

The TextField widget define its controller as _emcontroller and any changes to its value will be stored

by this controller. The button implements onPressed with _onPressed method. This method should

be located inside the class MyAppState. This method contain setState method that perform the

setting of variable _email2 to the value of _emcontroller.

_onPressed() { setState(() { _email2 = _emcontroller.text; }); }

The last Text shows the value back to user by displaying the variable value when user click on the press

me button.

Full project code is as follows:

import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { final TextEditingController _emcontroller = TextEditingController(); String _email2 = ""; @override Widget build(BuildContext context) {

Page 25: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

24

return MaterialApp( title: 'Material App', home: Scaffold( appBar: AppBar( title: Text('Material App Bar'), ), body: Column( children: <Widget>[ Container( child: Text('Email'), alignment: Alignment.centerLeft, ), TextField(controller: _emcontroller), RaisedButton( child: Text("Press Me"), onPressed: _onPressed, ), Text("Submitted Text: $_email2"), ], ), ), ); } _onPressed() { setState(() { _email2 = _emcontroller.text; }); } }

Simple Calculator

Simple calculator takes two number from TextField and perform basic arithmetic operation such as

addition, subtraction, multiplication and division. Create new Flutter project call mycalculator. Clear

all the codes from default main.dart and import mateapp snippet. Then refactor StatelessWidget

class into StatefulWidget and also body into Wrap with Column. Finally remove the content of Widget

array.

Add two TextFields, a button and a Text as output on the layout. The following Widget arrays display

basic Widgets placement using its basic definition.

children: <Widget>[ TextField(), TextField(),

Page 26: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

25

RaisedButton( child: Text("+"), onPressed: null, ), Text("Result:"), ],

The output from above code.

Full code for simple calculator.

import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { final TextEditingController _acontroller = TextEditingController(); final TextEditingController _bcontroller = TextEditingController(); double a = 0.0, b = 0.0, result = 0.0; @override Widget build(BuildContext context) { return MaterialApp( title: 'Material App', home: Scaffold( appBar: AppBar( title: Text('Material App Bar'), ), body: Column( children: <Widget>[ TextField(

Page 27: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

26

controller: _acontroller, ), TextField( controller: _bcontroller, ), RaisedButton( child: Text("+"), onPressed: _onPress, ), Text("Result: $result"), ], ), ), ); } void _onPress() { setState(() { a = double.parse(_acontroller.text); b = double.parse(_bcontroller.text); result = a + b; }); } }

The application above shows basic calculator that able to perform simple addition operation.

Widget Decoration (new widget!)

However, the interface can be further improved by using several other Widgets. The following Scaffold

has been updated with additional widget.

home: Scaffold( resizeToAvoidBottomPadding: false, appBar: AppBar(

Page 28: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

27

title: Text('Basic Calculator App'), ), body: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Padding( padding: EdgeInsets.fromLTRB(50, 0, 50, 0), child: TextField( decoration: InputDecoration( hintText: "First Number", ), keyboardType: TextInputType.numberWithOptions(), controller: _acontroller, ), ), Padding( padding: EdgeInsets.fromLTRB(50, 0, 50, 0), child: TextField( decoration: InputDecoration( hintText: "Second Number", ), keyboardType: TextInputType.numberWithOptions(), controller: _bcontroller, ), ), Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Padding( padding: EdgeInsets.all(5), child: RaisedButton( child: Text("+"), onPressed: _onPress, ), ), Padding( padding: EdgeInsets.all(5), child: RaisedButton( child: Text("-"), onPressed: _onPress, ), ), ], ), Text("Result: $result"), ], ), ),

Page 29: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

28

The interface has gone a lot of changes by including several widgets and options such as Padding and

InputDecoration, resizing and alignment. Noticed that new nested Row (red box) also has been used

in the Widget with new array Row allowing additional new button to the right. Padding also allow

Widget to move inwards and center making the interface look more accessible.

Assignment Complete the above simple calculator application with additional 3 arithmetic operations. Add two

more button below the “+” and “– “buttons. Each button must perform their own arithmetic

operation.

BMI Calculator

BMI calculator is another simple application that allow user to enter their weight and height and the

application will return BMI value back to user. Create new flutter project and insert two TextFields

and one Button and one Text as output. Use the previous example as guideline since the operation

more or less the same.

Page 30: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

29

The application takes two input from user and then convert the value using BMI formula (height x

height) / Weight) Full code is available as follows:

import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { final TextEditingController _acontroller = TextEditingController(); final TextEditingController _bcontroller = TextEditingController(); double a = 0.0, b = 0.0, result = 0.0; String bmi; @override Widget build(BuildContext context) { return MaterialApp( title: 'Material App', home: Scaffold( resizeToAvoidBottomPadding: false, appBar: AppBar( title: Text('BMI Calculator'), ), body: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Padding( padding: EdgeInsets.fromLTRB(50, 0, 50, 0), child: TextField( decoration: InputDecoration(

Page 31: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

30

hintText: "Height(cm)", ), keyboardType: TextInputType.numberWithOptions(), controller: _acontroller, ), ), Padding( padding: EdgeInsets.fromLTRB(50, 0, 50, 0), child: TextField( decoration: InputDecoration( hintText: "Weight(kg)", ), keyboardType: TextInputType.numberWithOptions(), controller: _bcontroller, ), ), Padding( padding: EdgeInsets.all(5), child: RaisedButton( child: Text("Calculate BMI"), onPressed: _onPress, ), ), Text("BMI: $bmi"), ], ), ), ); } void _onPress() { setState(() { a = double.parse(_acontroller.text); b = double.parse(_bcontroller.text); result = (b * b) / a; bmi = format(result); }); } String format(double n) { return n.toStringAsFixed(n.truncateToDouble() == n ? 0 : 2); } }

Page 32: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

31

Image Widget (new widget!) Let’s add new Widget to the BMI application call image. Image allow user to show image from

application resources or from the Internet. Download the following file to drive

http://slumberjer.com/bmires.zip. Create a new folder call assets and sub folder inside assets call

images in the root of the project directory as follows.

Then right click on the images folder and select Reveal in Explorer menu or press Shift+Alt+R keys.

Unzip all the images and audio files into the folder.

The content of the images folder should appear inside the project explorer.

Page 33: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

32

Pubspec.yaml

The next step is to register all images into the pubspec.yaml file under section assets. Pubspec is a file

within the project directory that responsible for project library import and assets management. More

on pubspec.yaml available here (https://flutter.dev/docs/development/packages-and-plugins/using-

packages ). Any new asset uses by Flutter project needed to be updated inside this file. For assets,

enable assets sections as follows.

# To add assets to your application, add an assets section, like this:

assets: - assets/images/

Then create a new variable call img under the widget class.

String img = "assets/images/default.jpg";

Add Image widget into widget array with in first column.

children: <Widget>[

Image.asset(img, height: 200.0, fit: BoxFit.cover), The application will display an image loaded from images directory using Image widget. Restart

application debug to take effect of the new assets. Static image will be displayed on the first column

of the application.

Page 34: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

33

The following steps allow the application to change the image widget asset dynamically based on the

BMI value. When the BMI value is between certain ranges, image widget will be updated with different

image. Update the _onPress method with the following code:

void _onPress() { setState(() { a = double.parse(_acontroller.text); b = double.parse(_bcontroller.text); result = (b * b) / a; bmi = format(result); if (result > 25) { img = "images/overweight.jpg"; } else if ((result <= 24.9) && (result >= 18.5)) { img = "images/normal.jpg"; } else if (result < 18.5) { img = "images/underweight.jpg"; } }); } String format(double n) { return n.toStringAsFixed(n.truncateToDouble() == n ? 0 : 2); }

Finally change Image widget as follows to set img variable defined above. Run the project.

new Image.asset(img, height: 200.0, fit: BoxFit.cover),

Page 35: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

34

Run the project and test with different value. The image widget displays different images based on

the BMI value.

Play Audio (new widget!) Audio is an auditory clue that can be one of the features of an application. Event such as button click,

or result from processing can use audio as part of the user experience. Handling audio can be quite

challenging due to the way Android and IOS architecture of handling audio. Library audioplayers is

one of many libraries that can handle audio for Flutter.

The following application is an extension from BMI calculator. User result can trigger an audio cues to

show the perceptions of value such as producing trombone sound for overweight and underweight

result and success sound for normal BMI.

Library

Library is a preprogram code that can be used by a program. It is reusable code that make

programming easy and faster by including into a project. Flutter import library through pubspec.yaml

file. A section called dev_dependecies allow any online library to be directly downloaded and

imported into project. The name of the library is needed and included into pubspec.yaml. Be aware

with the tab indentation.

To use audioplayers library, access pubspec.yaml and update with the following dev_dependencies

section. Save and update the new dependencies.

dev_dependencies: flutter_test: sdk: flutter

Page 36: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

35

audioplayers: ^0.13.1

Continue to create new folder call inside assets folder call audio and add the included two wav audio

files (fail.wav and ok.wav) into this folder. Save

Import the following libraries into the main.dart.

import 'package:audioplayers/audioplayers.dart'; import 'package:audioplayers/audio_cache.dart';

then continue to add the following two objects (audioCache and audioPlayer) inside the state class.

AudioCache audioCache = new AudioCache(); AudioPlayer audioPlayer = new AudioPlayer();

Insert two methods (loadOk and loadFail) inside the state class.

Future loadOk() async { audioPlayer = await AudioCache().play("audio/ok.wav"); } Future loadFail() async { audioPlayer = await AudioCache().play("audio/fail.wav"); }

and finally call this method from _onPress method.

if (result > 25) { img = "assets/images/overweight.jpg"; loadFail(); } else if ((result <= 24.9) && (result >= 18.5)) { img = "assets/images/normal.jpg"; loadOk(); } else if (result < 18.5) {

Page 37: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

36

img = "assets/images/underweight.jpg"; loadFail(); }

Rerun the project on AVD and try one value for each three different BMI result. A short sound will be

played for each result.

The following is full project code for reference:

import 'package:flutter/material.dart'; import 'package:audioplayers/audioplayers.dart'; import 'package:audioplayers/audio_cache.dart'; void main() => runApp(MyApp()); class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { final TextEditingController _acontroller = TextEditingController(); final TextEditingController _bcontroller = TextEditingController(); double a = 0.0, b = 0.0, result = 0.0; String bmi; String img = "assets/images/default.jpg"; AudioCache audioCache = new AudioCache(); AudioPlayer audioPlayer = new AudioPlayer(); @override Widget build(BuildContext context) { return MaterialApp( title: 'Material App', home: Scaffold( resizeToAvoidBottomPadding: false, appBar: AppBar( title: Text('BMI Application'), ), body: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Image.asset(img, height: 200.0, fit: BoxFit.cover), Padding( padding: EdgeInsets.fromLTRB(50, 0, 50, 0), child: TextField( decoration: InputDecoration( hintText: "Height(cm)",

Page 38: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

37

), keyboardType: TextInputType.numberWithOptions(), controller: _acontroller, ), ), Padding( padding: EdgeInsets.fromLTRB(50, 0, 50, 0), child: TextField( decoration: InputDecoration( hintText: "Weight(kg)", ), keyboardType: TextInputType.numberWithOptions(), controller: _bcontroller, ), ), Padding( padding: EdgeInsets.all(5), child: RaisedButton( child: Text("Calculate BMI"), onPressed: _onPress, ), ), Text("BMI: $bmi"), ], ), ), ); } void _onPress() { setState(() { a = double.parse(_acontroller.text); b = double.parse(_bcontroller.text); result = (b * b) / a; bmi = format(result); if (result > 25) { img = "assets/images/overweight.jpg"; loadFail(); } else if ((result <= 24.9) && (result >= 18.5)) { img = "assets/images/normal.jpg"; loadOk(); } else if (result < 18.5) { img = "assets/images/underweight.jpg"; loadFail(); } }); }

Page 39: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

38

Future loadOk() async { audioPlayer = await AudioCache().play("audio/ok.wav"); } Future loadFail() async { audioPlayer = await AudioCache().play("audio/fail.wav"); } @override void dispose() { audioPlayer = null; super.dispose(); } String format(double n) { return n.toStringAsFixed(n.truncateToDouble() == n ? 0 : 2); } }

Page 40: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

39

Food Ninja

In the previous topic, this book look into installation process, basic state and stateless widget layout

and with common layout Widgets such as Text, TextField, and RaisedButton. Simple layout manager

such as row and column widget have been used to manage widget placement on layout. Finally, Image

and audio widgets is use to allow application to provide visual and audio cue.

The following section will be based on a single application called FoodNinja. FoodNinja is an

application inspired by FoodPanda and GrabFood for online food delivery services. It is a complete

user side application that allow user to order food from participating local restaurants. User then can

pay online using online payment system and finally order can be delivered.

This application will serve as fundamental mobile application development stages with Flutter where

every step taken in developing this application will demonstrate certain topic that can be useful in

developing your complete application. The application starts from a splash screen where a form shows

a simple layout with a progress bar and a product logo. The screen then automatically moves to login

screen that allow user to login using email and password. User can also register using register layout.

Once successfully register, user can back to login and proceed to Main screen with listing of

participating restaurants. This application uses MySQL as its database and PhP as middleware.

Full source code is available from author Github page and will be used throughout this book as

reference if needed (https://github.com/ahmadhanis/FlutterWS/tree/master/food_ninja ). Some of

the code might be too long to put into this book, please refer to the link above for complete code.

Use the following YouTube tutorial how to clone github project to your computer

(https://www.youtube.com/watch?v=2Pi6ZKSbCp8).

Page 41: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

40

Splash Screen

Splash screen is a simple screen with or without loading bar and a brand logo. This screen is normally

being use as product branding and only appear 2-3 seconds. It also provides first impression for user

how the overall look and feel of application.

Create new project called food_ninja in you VSC and proceed with the basic application structure

using mateapp plugin shortcut. Create a folder called /assets/images in Flutter project directory and

register the asset directory into pubspec.yaml. Download foodninja.png from

http://slumberjer.com/foodninja/images/foodninjared.png and copy into /assets/images directory.

Refactor container into column from basic mateapp code add two widgets into widget array.

import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( theme: new ThemeData( primarySwatch: Colors.red), debugShowCheckedModeBanner: false, home: Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Image.asset( 'assets/images/foodninjared.png', width: 230, height: 230, ), SizedBox( height: 20, ), new ProgressIndicator(), ], ), ), ), ); } }

Page 42: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

41

Pubspec.yaml assets section update.

# To add assets to your application, add an assets section, like this: assets: - assets/images/

Create a new Statefull class for ProgressIndicator() in the main.dart using stl shortcut as follows and

set the name of the class as ProgressIndicator.

Update ProgressIndicator class with the following code:

class ProgressIndicator extends StatefulWidget { @override _ProgressIndicatorState createState() => new _ProgressIndicatorState(); } class _ProgressIndicatorState extends State<ProgressIndicator> with SingleTickerProviderStateMixin { AnimationController controller; Animation<double> animation; @override void initState() { super.initState(); controller = AnimationController( duration: const Duration(milliseconds: 2000), vsync: this); animation = Tween(begin: 0.0, end: 1.0).animate(controller) ..addListener(() { setState(() { //updating states if (animation.value > 0.99) { //Navigator.pushReplacement( // context, // MaterialPageRoute( // builder: (BuildContext context) => LoginPage())); } }); }); controller.repeat();

Page 43: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

42

} @override void dispose() { controller.stop(); super.dispose(); } @override Widget build(BuildContext context) { return new Center( child: new Container( width: 200, color: Colors.redAccent, child: LinearProgressIndicator( value: animation.value, backgroundColor: Colors.black, valueColor: new AlwaysStoppedAnimation<Color>(Colors.red), ), )); } }

Run the project on AVD. The layout should show as follows.

Debug Options

There are a few new options introduced in this code. Under MaterialApp widget,

debugShowCheckedModeBanner is set to false where the debug banner is removed.

return MaterialApp(

Page 44: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

43

debugShowCheckedModeBanner: false,

SizedBox (new widget!)

SizedBox is a widget a box drawn on the layout with a specific size. It is useful widget in managing

position of another widget or it can be parent to another widget for managing the widget size. More

on SizedBox from https://api.flutter.dev/flutter/widgets/SizedBox-class.html.

LinearProgressIndicator Widget

Progress indicator controller and animation is needed for the progress bar to show its progress value.

AnimationController controller; Animation<double> animation;

LinearProgressIndicator widgets is define in ProgressIndicator class in a container. A few other

parametes is set such as animation value and background color.

child: LinearProgressIndicator( value: animation.value, backgroundColor: Colors.black, valueColor: new AlwaysStoppedAnimation<Color>(Colors.red), ),

AnimationController set the duration of the animation for the splash screen to 2000ms (2 seconds).

Tween class is use to set animation range between 0.0 to 1.0 (0-100 percent).

controller = AnimationController( duration: const Duration(milliseconds: 2000), vsync: this); animation = Tween(begin: 0.0, end: 1.0).animate(controller)

Renaming main.dart to splashscreen.dart

File main.dart is the default file name when new Flutter project is created. Since this is the default

debug configuration, to change this file name into another name requires a few configuration changes.

First, start with renaming the file from main.dart to splashscreen.dart by right right click and choose

rename. Then open launch.json file under .vscode folder or through Debug/Open Configurations

menu.

Page 45: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

44

Change launch.json configuration as follows:

{ "name": "Flutter", "type": "dart", "request": "launch", "program": "lib/splashscreen.dart" }

Then open widget_test.dart under test folder and update library from main.dart to

splashscreen.dart. Save all the updated files and rebuild the project.

import 'package:food_ninja/splashscreen.dart';

For better understanding open the following link for full splashscreen.dart available at

https://github.com/ahmadhanis/FlutterWS/blob/master/food_ninja/lib/splashscreen.dart.

Page 46: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

45

Login Screen

Most of online database type application will require a login page. Login page allow the application to

store and access user profile when using the application. But first the layout need to navigate from

splashscreen.dart (rename from main.dart) to new layout for loginpage.dart.

Page Navigation

Create new file in the lib folder call loginpage.dart. User “mateapp” to include base code for a layout.

Go back to splashscreen.dart and update the following code:

if (animation.value > 0.9) { Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => LoginPage())); }

Navigator Widget with MaterialPageRoute allow current layout context to move from one layout to

the other. LoginPage() is the name of the class in loginpage.dart which handle login information.

and then remove everything inside MaterialApp widget. Update MaterialApp with the following code:

return new MaterialApp( title: 'Login', theme: new ThemeData(primarySwatch: Colors.red), home: new LoginPage(), );

Then create a statefull widget using “stl” shortcut text and name the class LoginPage. Create Scaffold

widget with Container for its body. Create child Column with widget array to host all other 3 widgets.

Full LoginPage class is as follows:

class LoginPage extends StatefulWidget { @override _LoginPageState createState() => _LoginPageState(); } class _LoginPageState extends State<LoginPage> { @override Widget build(BuildContext context) { return new Scaffold( body: new Container( child: Column( children: <Widget>[ Image.asset(

Page 47: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

46

'assets/images/foodninjared.png', width: 150, height: 150, ), TextField( decoration: InputDecoration( labelText: 'Email', )), TextField( decoration: InputDecoration( labelText: 'Password', ), obscureText: true, ), RaisedButton(child: Text("login"),onPressed: null,) ], ), ), ); } }

The following layout is outcome from loginpage.dart class above.

Login shows product image with two TextFields with text input decoration email and password.

However, the positioning of all the widgets is quite off for example TextField needs padding to left

and right section, location of all the widgets should be in the middle of the screen and button doesn’t

seems suitable with overall design for the application. Update the class above with the following code:

Page 48: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

47

import 'package:flutter/material.dart'; bool _isChecked = true; final TextEditingController _emcontroller = TextEditingController(); String _email = ""; final TextEditingController _pscontroller = TextEditingController(); String _pass = ""; class LoginPage extends StatefulWidget { @override _LoginPageState createState() => _LoginPageState(); } class _LoginPageState extends State<LoginPage> { @override Widget build(BuildContext context) { return new Scaffold( resizeToAvoidBottomPadding: false, body: new Container( padding: EdgeInsets.all(30.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Image.asset( 'assets/images/foodninjared.png', scale: 2.5, ), TextField( controller: _emcontroller, decoration: InputDecoration( labelText: 'Email', )), TextField( controller: _pscontroller, decoration: InputDecoration( labelText: 'Password', ), obscureText: true, ), Row( children: <Widget>[ Checkbox( value: _isChecked, onChanged: (bool value) { _onChange(value); }, ), Text('Remember Me', style: TextStyle(fontSize: 16))

Page 49: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

48

], ), SizedBox( height: 10, ), MaterialButton( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20.0)), minWidth: 300, height: 50, child: Text('Login'), color: Color.black, textColor: Colors.white, elevation: 20, onPressed: _onPress, ), SizedBox( height: 20, ), Text("Register new account"), SizedBox( height: 10, ), Text('Forgot password') ], ), ), ); } void _onPress() { print(_emcontroller.text); print(_pscontroller.text); } void _onChange(bool value) { setState(() { _isChecked = value; print('Check value $value'); }); } }

The above update produces the following login page. It transforms the application with better look

and feels through widget positioning and sizing.

Page 50: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

49

There are a number of new widgets and properties updated in the above code (check on the new

comment).

Handling Layout Overflow

Overflow widget displayed as black yellow marker that shows the UI widget element overflow the

overall display pixels. It is a common problem in Flutter interface design. To avoid this problem, use

option resizeToAvoidBottomPadding set to false added to scaffold.

resizeToAvoidBottomPadding: false,

Padding option

Padding allow for widget to have padding. Padding is an empty cushion surrounding a widget. Padding

use below set 30 pixels edge in all directions of the selected container.

padding: EdgeInsets.all(30.0),

Page 51: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

50

Alignment option

Alignment option available for certain widget allow for widget to set its alignment to multiple types

such as center, start, and end.

mainAxisAlignment: MainAxisAlignment.center,

SizedBox Widget

SizedBox is a great widget for managing space in a layout or controlling other widget positioning and

sizing. The above code use SizedBox for managing spacing between password and login button at

the bottom.

SizedBox( height: 10, ),

MaterialButton Widget

Material button is just another type of button widget that allow widget to be resized using minWidth

option.

MaterialButton( minWidth: 300, child: Text('Login'), color: Colors.black, textColor: Colors.white, elevation: 15, onPressed: _onPress, ),

There are a number of other options available that follows material design concept from Android.

Explore more option using flutter cookbook (https://flutter.dev/docs/cookbook).

GestureDetector Widget

Gesture detector is a widget that allow the application to detect any gesture from user. It enables any

widget to implement action such as onTap enabling the widget to call certain method. Set the widget

that need gesture as a child to GestureDetector and automatically the widget can implement

interactivity.

GestureDetector( onTap: _onRegister, child: Text('Register New Account',

Page 52: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

51

style: TextStyle(fontSize: 16))),

CheckBox Widget

CheckBox widget use in the login screen to store user credential in the application preference. This

give option not to type in their credential every time using the application. CheckBox widget in the

code is wrap in a Row widget with widget array to allow row positioning of checkbox and textbox in a

single row. Then isChecked method is used to allow checked operation

Row( children: <Widget>[ Checkbox( value: _isChecked, onChanged: (bool value) { _onChange(value); }, ), Text('Remember Me',style: TextStyle(fontSize: 16)) ], ),

Navigator Widget

Before user can proceed with login operation, they first need to register their account using

registration layout. Create new file call registeruser.dart and add “mateapp” script to the file. Update

onRegister method from loginpage.dart with Navigator widget to navigate to a new page call

registeruser.dart. Navigator widget allow layout to navigate from one to the other by calling the class

name.

void _onRegister() { Navigator.push( context, MaterialPageRoute(builder: (context) => RegisterUser())); }

import 'package:food_ninja/registeruser.dart';

Remember to import package registeruser.dart in the import section. Named route is another option

that can be used to navigate around layouts.

Page 53: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

52

Handling Preferences Preferences is a simple paired data stored in a file application directory. It uses to store simple

preference data such as settings, username or password. Application can load from preference and

use the data. The following async method is use to save email and password data in preference. When

user press checkbox to store their username and password, prefs object store using setString method.

void savepref(bool value) async { print('Inside savepref'); _email = _emcontroller.text; _pass = _pscontroller.text; SharedPreferences prefs = await SharedPreferences.getInstance(); if (value) { //true save pref if (_isEmailValid(_email) || _pass.length < 5) { await prefs.setString('email', _email); await prefs.setString('pass', _pass); print('Save pref $_email'); print('Save pref $_pass'); Toast.show("Preferences saved succesfully", context, duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM); } else { print('No email'); setState(() { _isChecked = false; }); Toast.show("Invalid Preferences", context, duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM); } } else { await prefs.setString('email', ''); await prefs.setString('pass', ''); setState(() { _emcontroller.text = ''; _pscontroller.text = ''; _isChecked = false; }); print('Remove pref'); Toast.show("Preferences removed", context, duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM); } }

The other part of preference is to load data back into application. The following method loadpref()

handle load data from pref object.

Page 54: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

53

void loadpref() async { print('Inside loadpref()'); SharedPreferences prefs = await SharedPreferences.getInstance(); _email = (prefs.getString('email')); _pass = (prefs.getString('pass')); print(_email); print(_pass); if (_email.length > 1) { _emcontroller.text = _email; _pscontroller.text = _pass; setState(() { _isChecked = true; }); } else { print('No pref'); setState(() { _isChecked = false; }); } }

To load preference, call the method from initState override method. This method load everytime the

login page loaded.

@override void initState() { loadpref(); print('Init: $_email'); super.initState(); }

Full code for login screen implemented by loginpage.dart is available from the following github link (

https://github.com/ahmadhanis/FlutterWS/blob/master/food_ninja/lib/loginpage.dart).

Don’t forget to update pubspec.yml for dependencies required.

https://github.com/ahmadhanis/FlutterWS/blob/master/food_ninja/pubspec.yaml

Page 55: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

54

Register User

Registration page allow user to register their account. This page is call from login page where new user

is required to create new account. The following code use statefull widget for registration page. There

are 5 inputs required from user; an image, name, email, password and phone number.

import 'dart:io'; import 'package:flutter/material.dart'; import 'dart:async'; import 'package:flutter/services.dart'; import 'loginpage.dart'; import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:image_picker/image_picker.dart'; import 'package:toast/toast.dart'; import 'package:progress_dialog/progress_dialog.dart'; String pathAsset = 'assets/images/profile.png'; File _image; String urlUpload = "http://slumberjer.com/foodninja/php/register_user.php"; final TextEditingController _namecontroller = TextEditingController(); final TextEditingController _emcontroller = TextEditingController(); final TextEditingController _passcontroller = TextEditingController(); final TextEditingController _phcontroller = TextEditingController(); String _email, _password, _phone,_name; class RegisterUser extends StatefulWidget { @override _RegisterUserState createState() => _RegisterUserState(); const RegisterUser({Key key, File image}) : super(key: key); } class _RegisterUserState extends State<RegisterUser> { @override void initState() { super.initState(); } @override Widget build(BuildContext context) { return WillPopScope( onWillPop: _onBackPressAppBar, child: Scaffold( resizeToAvoidBottomPadding: false,

Page 56: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

55

appBar: AppBar( title: Text('New User Registration'), backgroundColor: Colors.black, ), body: SingleChildScrollView( child: Container( padding: EdgeInsets.fromLTRB(40, 20, 40, 20), child: RegisterWidget(), ), ), ), ); } Future<bool> _onBackPressAppBar() async { _image = null; Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => LoginPage(), )); return Future.value(false); } } class RegisterWidget extends StatefulWidget { @override _RegisterWidgetState createState() => _RegisterWidgetState(); } class _RegisterWidgetState extends State<RegisterWidget> { @override Widget build(BuildContext context) { return Column( children: <Widget>[ GestureDetector( onTap: _choose, child: Container( width: 180, height: 200, decoration: BoxDecoration( shape: BoxShape.circle, image: DecorationImage( image: _image == null ? AssetImage(pathAsset) : FileImage(_image), fit: BoxFit.fill, )),

Page 57: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

56

)), Text('Click on the image above to take profile picture'), TextField( controller: _namecontroller, keyboardType: TextInputType.text, decoration: InputDecoration( labelText: 'Name', icon: Icon(Icons.person), )), TextField( controller: _emcontroller, keyboardType: TextInputType.emailAddress, decoration: InputDecoration( labelText: 'Email', icon: Icon(Icons.email), )), TextField( controller: _passcontroller, decoration: InputDecoration(labelText: 'Password', icon: Icon(Icons.lock)), obscureText: true, ), TextField( controller: _phcontroller, keyboardType: TextInputType.phone, decoration: InputDecoration(labelText: 'Phone', icon: Icon(Icons.phone))), SizedBox( height: 10, ), MaterialButton( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)), minWidth: 300, height: 50, child: Text('Register'), color: Colors.black, textColor: Colors.white, elevation: 15, onPressed: _onRegister, ), SizedBox( height: 10, ),

Page 58: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

57

GestureDetector( onTap: _onBackPress, child: Text('Already Register', style: TextStyle(fontSize: 16))), ], ); } void _choose() async { _image = await ImagePicker.pickImage(source: ImageSource.camera); setState(() {}); // file = await ImagePicker.pickImage(source: ImageSource.gallery); } void _onRegister() { print('onRegister Button from RegisterUser()'); print(_image.toString()); uploadData(); } void _onBackPress() { _image = null; print('onBackpress from RegisterUser'); Navigator.pushReplacement(context, MaterialPageRoute(builder: (BuildContext context) => LoginPage())); } void uploadData() { ProgressDialog pr = new ProgressDialog(context,type: ProgressDialogType.Normal, isDismissible: false); pr.show(); _name = _namecontroller.text; _email = _emcontroller.text; _password = _passcontroller.text; _phone = _phcontroller.text; print(_image); if ((_image == null) || (!_isEmailValid(_email)) || (_password.length < 5) || (_phone.length < 5)) { Toast.show("Invalid Registration Data", context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM); return; } String base64Image = base64Encode(_image.readAsBytesSync()); http.post(urlUpload, body: {

Page 59: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

58

"encoded_string": base64Image, "name": _name, "email": _email, "password": _password, "phone": _phone, }).then((res) { print(res.statusCode); print(res.body); _image = null; _namecontroller.text=''; _emcontroller.text = ''; _phcontroller.text = ''; _passcontroller.text = ''; Toast.show(res.body, context, duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM); Navigator.pushReplacement(context, MaterialPageRoute(builder: (BuildContext context) => LoginPage())); }).catchError((err) { print(err); }); pr.dismiss(); } bool _isEmailValid(String email) { return RegExp(r"^[a-zA-Z0-9.]+@[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(email); } }

RegisterUser widget above wrap all body layout into SingleChildScrollView widget where it allow for

the layout to be scrollable if run on smaller screen. The register screen contain four textfield widgets,

a text widget, a button widget and an image widget respectively for name, email, password, phone,

profile image and text return link. Four controllers attached to each of the textfield. Image widget

surrounded with gesture detector widget to enable on tap operation. When user click on the image,

_choose method is call and imagepicker object initiated to run camera. User are required to capture

image and insert data all data into textfields. Image for profile.png image can be downloaded from

from http://slumberjer.com/foodninja/images/profile.png add then add into assets/images folder.

The next step will require backend processing to upload profile image into server directory and Mysql

database to store all user information. FoodNinja uses PhP as backend script to manage operation

between mobile application and database.

Page 60: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

59

Reinstall the application on AVD test the application layout flows with new plugin. Comment if any

of the code above shows error at this stage.

User Registration Process Image and user data from above need to be stored in an online storage. For this step, a web hosting

is needed. You can use local web hosting by installing XAMPP or WAMP application. However, it is

recommended to purchase your own domain. This can benefit in the long run where the application

can be run anywhere.

Create Database The first step is to create MySQL database. Login to cpanel and access MySQL Database Wizard.

Page 61: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

60

Give the database a name and press next step button.

Then create user admin for the database. Set username and password and make sure to keep this

information. Choose strong password using auto generated password.

Next step is to add user admin to the database. Select all privileges for the user admin.

Page 62: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

61

Database creation completed. Make sure to store all the required information later needed for

database connector in PhP as follows:

DB name: slumber6_myhelper DB pass: xxxxxxxxxxxx (your password) DB user: slumber6_myhelperadmin Server: Localhost

Table creation Once database successfully created, the next step from here is to create table to store data. Back to

main CPanel menu and access phpMyAdmin page. Select the database name from the list.

Create table USER with 5 columns.

Page 63: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

62

Set 5 fields as follows:

And finally press create table.

To test if the table can be used to insert data, access SQL tab and enter the following SQL query.

INSERT INTO `USER`(`NAME`, `EMAIL`, `PASSWORD`, `PHONE`) VALUES

('hanis','[email protected]','12312334234324325','01944556554')

Page 64: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

63

Server Application Directory

Once database is ready, the next step is to start preparing for PhP database connector. However,

before that an application directory is needed to store all PhP files or any other files for the application.

Open File Manager from CPanel main menu and access to public_html folder. This folder is the root

of a web server.

Create a folder call foodninja in public_html folder. This folder can be access using web URL

htt://slumberjer.com/foodninja. Disable directory browsing for added security or better enable SSL

for the web server. As for now, use default setting. Create three folders images, php and profile inside

foodninja directory. Images will store any images uses by the application, php store all php files and

profile for user image profile.

Page 65: FLUTTER WITH VSCslumberjer.com/book/Flutter.pdf · 2019. 10. 13. · Ahmad Hanis Mohd Shabli 9/11/19 STIW2044 . 1 . Table of Contents ... Save the project into a workspace folder

64

Database Connector

Database connector is a php file use as establishing database connection. It contains information on

server name, username, password and database name. Create a new file call dbconnect.php in folder

PHP. Copy the following code into this folder and save. Make sure to change your dbname, password

and username accordingly.

<?php $servername = "localhost"; $username = "slumber6_adminfoodninja"; $password = "dG2=KVSSxyRm"; $dbname = "slumber6_foodninja"; $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } ?>