# **Flutter Codelab: Counter App**
# **Introduction**
Flutter is an open source SDK for creating high-performance, high-fidelity mobile apps for iOS and Android. The Flutter framework makes it easy for you to build user interfaces that react smoothly in your app, while reducing the amount of code required to synchronize and update your app's view.
Flutter makes it easy to get started building beautiful apps, with its rich set of Material Design and Cupertino (iOS) widgets and behaviors. Your users will love your app's natural look and feel, because Flutter implements platform-specific scrolling, navigational patterns, fonts, and more. You'll feel powerful and productive with Flutter's functional-reactive framework and our extremely fast hot reloads on devices and emulators.
You'll write your Flutter apps in Dart. Dart syntax should look familiar if you already know Java, JavaScript, C#, or Swift. Dart is compiled using the standard Android and iOS toolchains for the specific mobile platform where your app needs to run. You get all the benefits of the Dart language, including familiar and concise syntax, first-class functions, async/await, rich standard libraries, and more.
This codelab provides a deeper dive into Flutter than Write Your First [Flutter Counter App](). If you want a gentler introduction to Flutter, start with those
---
# **Codelab Outline**
* How to write a Flutter app that looks natural on both iOS and Android.
* Basic structure of a Flutter app
* Finding and using packages to extend functionality.
* How to implement a stateful and stateless widget.
* How to play with widget.
* Using hot reload for a quicker development cycle.
---
# Set up your Flutter environment
You need two pieces of software to complete this lab: the Flutter SDK, and an editor. This codelab assumes Android Studio, but you can use your preferred editor.
You can run this codelab using any of the following devices:
* A physical device (Android or iOS) connected to your computer and set to developer mode.
* The iOS simulator. (Requires installing Xcode tools.)
* The Android emulator. (Requires setup in Android Studio.)
---
# Create the initial Flutter app
#### **[Android Studio / IntelliJ](https://flutter.io/docs/get-started/test-drive#androidstudio)**
1. Select File > New Flutter Project.
2. Select Flutter application as the project type, and press Next.
3. Make sure that the Flutter SDK Path text field specifies the location of the SDK. Install the SDK if you haven’t yet done so.
4. Enter a project name (ie. **CounterApp**), and press Next.
5. Click Finish.
6. Wait for Android Studio to install the SDK, and create the project.
#### **[Webstorm / Visual Studio Code](https://flutter.io/docs/get-started/test-drive#vscode)**
1. Invoke View > Command Palette.
2. Type "flutter", and select the Flutter: New Project.
3. Enter a project name, ie. **CounterApp**, and press Enter.
4. Create or select the parent directory for the new project folder.
5. Wait for project creation to complete and the **main.dart** file to appear.
#### **[Terminal & editor](https://flutter.io/docs/get-started/test-drive?tab=terminal#terminal)**
Use the **flutter create** command to create a new project:
```dart
$ flutter create counterapp
$ cd counterapp
```
---
# Let's Create Counter App
Create a simple templated Flutter app, using the instructions in [Getting Started with your first Flutter app](https://flutter.dev/docs/get-started/test-drive?tab=androidstudio). Name the project [counterapp]() (instead of myapp). we'll be creating this counter app from scratch to learn the basics of flutter.
In this codelab, we will show you how the pre-built demo Flutter app, i.e., the “Counter App” works and hot u can make a counter app of your own.
|  |
| -------- | -------- |
In these codelab, we'll mostly be writing/editing ./lib/main.dart, where the Dart code lives.
Delete all of the code from **lib/main.dart**. Replace with the following code, which displays "Hello Devfest Rjk" in the center of the screen.
```
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: const Text('Welcome to Devfest'),
),
body: const Center(
child: const Text('Hello Rajkot!'),
),
),
);
}
}
```
**Observations**
* This example creates a Material app. Material is a visual design language that is standard on mobile and the web. Flutter offers a rich set of Material widgets.
* The main method uses arrow (=>) notation, Use arrow notation for one-line functions or methods.
* The app extends StatelessWidget, which makes the app itself a widget. In Flutter, almost everything is a widget, including alignment, padding, and layout.
* The Scaffold widget, from the Material library, provides a default app bar, a title, and a body property that holds the widget tree for the home screen. The widget subtree can be quite complex.
* A widget's main job is to provide a build method that describes how to display the widget in terms of other, lower-level widgets.
* The body for this example consists of a Center widget containing a Text child widget. The Center widget aligns its widget subtree to the center of the screen.
## Understand the Code
You will find a lot of comments in the demo Counter App, if you are a beginner then you should surely go through these comments as they are very well written and would help you in understanding the basics of a Flutter app.
So, Let's get started.
**First, whats going on in the the directory structure:**
```
counterapp
|- android
| ... some cool stuff
|- ios
| ... some cool stuff
|- lib
| main.dart
|- test
pubspec.lock
pubspec.yaml
README.md
...
```
```90%``` of the time, you only care about the **lib** folder and the **pubspec.yaml** file, which is where you list your projects dependencies
The ```lib``` folder is where you'll build your app. The only file here now is **main.dart**
**main.dart** must exist and it must be in the root of lib. This is the file that Dart and Flutter know to run as the entry point to your app.
`main.dart` must contain the `main()` function that will starts the execution of your app.
Now we need to remove everything except the imports and main function.
## Import
First, we have the **import statement**. This imports the material.dart package which helps in implementing the Material Design throughout the app and for most of the Dart files that are used for UI design you have to import this package.
```
import 'package:flutter/material.dart';
```
## Main
The `main()` and `runApp()` function definitions are the same as in the default app. The `runApp()` function takes as its argument a Widget which the Flutter framework expands and displays to the screen of the app at run time.
```dart
void main() => runApp(MyApp());
```
## Stateless Widget
This widget is the root of the app. Here, inside the build method, it returns a **Material App** widget containing the three properties: ```title, theme & home```
Now let's crate our first widget named `MyApp` which is a stateless widget.we will override the build Method and pass context.
Since we are going to use Material Design in the app, create a new `MaterialApp` Widget and return it to the build method.it will have Title `Counter App` and we will also set the `debugShowCheckedModeBanner` to false to make that annoying banner go away.
```dart
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Counter App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Welcome to Devfest'),
);
}
}
```
# **title**
This property takes the name of the app which would be displayed in the ***AppBar***
# **theme**
This property defines the ***ThemeData*** widget containing information about different colors, fonts and other theme data that would be used throughout the app. Here, only one property is defined, ***primarySwatch*** which stores the color blue. But, in your app, you can define any number of theme properties you want.
# **home**
This property contains a Stateful Widget, ***MyHomePage*** to which the title is passed on. When you start this app for the first time this is the widget that will be displayed as the first screen on your device.
## Stateful Widget (MyHomePage)
This Stateful Widget ***MyHomePage*** takes a constructor containing a key and a title. Here, the title is passed on from the previous class. You can see that the String title is marked final, this is done because the fields in a Widget subclass are always marked **final** if you do not mark this as a final you will get a warning.
```
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
```
Now, we have the overridden createState method which returns the instance of the class ***MyHomePageState***
## State class
In this class at first, a private integer variable ***_counter*** is initialized to zero. After that, we have a private void method defined called ***incrementCounter***
```
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
}
```
# **_incrementCounter**
This method calls the ```setState``` method, this setState is used to rebuild the widget tree. In this counter app, we have incremented the ***_counter*** variable within this ```setState```. If we just increment the ***_counter*** variable without defining any ```setState``` method, then this variable would get updated behind the scene but we will not see any UI changes as the widget tree would not be rebuilt.
# **build method**
Now, we have the overridden **build** method.
This method is rerun every time setState is called, for instance as done by the ***_incrementCounter*** method above.
The Flutter framework has been optimized to make rerunning build methods fast, so that you can just rebuild anything that needs updating rather than having to individually change instances of widgets.
```
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
```
In this app, the build method returns a Scaffold widget containing three properties: ```Scaffold, appBar, body & floatingActionButton```
# **Scaffold**
Scaffold is another build in app that gives us a standard mobile app layout. You'll most likely use this on every page of your app
# **appBar**
This property takes the ***AppBar*** widget containing a Text widget which displays the title of the app.
the bar accross the top of the app
```
appBar: AppBar(
title: Text(widget.title),
),
```
# **body**
This property contains a ***Column*** widget which is centered using the ***Center*** widget. The column widget contains two Text widgets, one displaying a text and another displaying the number of counts. The second text widget contains a property, style which defines the text **style** for this text widget.
```
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
```
**Column** is also layout widget. It takes a List of children and arranges them vertically. By default, it sizes itself to fit its children horizontally, and tries to be as tall as its parent.
**Column** has various properties to control how it sizes itself and how it positions its children. Here we use mainAxisAlignment to center the children vertically; the main axis here is the vertical axis because Columns are vertical (the cross axis would be horizontal).
**mainAxisAlignment** and **crossAxisAlignment** should feel very familiar if you're used to using CSS's Flexbox or Grid.
**Text** takes a String as it's first argument. We're passing in the value of the counter as an interpolated String.
# **floatingActionButton**
Floating action buttons are special button
It takes the **FloatingActionButton** widget which displays a FAB at the bottom right corner of the screen. The FAB widget takes three properties: ```onPressed, tooltip & child ```.
```
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
```
# **onPressed**
The onPressed property is used to call the **_incrementCounter** method which increments the counter by 1 and rebuilds the widget tree
# **tooltip**
This property can take a **String**. The text is displayed when the user long-presses on the button and is used for **accessibility**, which means that it won’t be displayed in normal circumstances.
# **child**
As you know, this child widget is used to show anything inside the parent widget. Here, it is used to show a **add** icon.
# Final Notes
So in simple words, the working of this app is that, when the FAB (Floating Action Button) is pressed the _incrementCounter method is called which increments the counter and rebuilds the widget tree.

# **Hot Reload**
1. Run the app on the emulator or a real device.
1. Let’s change the primarySwatch color to red.
1. Save the file [Command + S (for MAC), or Ctrl + S (for Windows)]. And you would immediately see that the color of the appBar and the FAB change to red.
Wow!. We learned a lot of in this codelab
---
### Thank you! :sheep:
You can find us on
- GitHub
- Twitter
- LinkedIn
---