Flutter Basic Training: A Complete Guide For Beginners
A guide on how to get started with Flutter. If you're new to Flutter, this guide will help you get started by building your first app.

Search for a command to run...
A guide on how to get started with Flutter. If you're new to Flutter, this guide will help you get started by building your first app.

Lessons from Code, Content, and Consistency

Reliability basics: Outbox pattern + why it matters

Introducing Kafka/Redpanda + move to event-driven workflow

Connect Orders ↔ Inventory (first working service-to-service flow)

Inventory service + gRPC + proto contracts



flutter create firstapp
Ctrl + Shift + p and write Flutter: New Project. This will create a new Flutter project for you.



flutter run

Find and change the color of primarySwatch inside MyApp class
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue, // <--- Change it to `Colors.red`
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}


main.dart file. We're going to write the app from the scratch.import 'package:flutter/material.dart';
main methodmain.dart file inside the lib folder. The main.dart file is the entry point of your application.void main(){} function like in any other programming language.void main() {
runApp(const MyApp());
}
main function there is one method called runApp which as the name suggests, runs the app by attaching the Widget on the device.
stl, and IDE will give you a snippet suggestion for creating a stateless widget
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container();
}
build() methodbuild method is a Material app. It's used as the root of the application and allows us to configure themes, routes, localization, title, etc of the application.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home:
);
}
}
Scaffold, which is used as a base for every screen.Let's give a Scaffold an AppBar
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Scaffold(
appBar: AppBar(),
),
);
}
}

name parameters where you can customize its appearance. ctrl+spacebar to bring up all the options.Go ahead and add a background color then add a title by creating a Text widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo Home Page'),
backgroundColor: Colors.deepOrange,
),
),
);
}
}

It takes one child widget as an argument. Let's put a Text widget for now.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Scaffold(
appBar: AppBar(...),
body: Container(
child: const Text('Hello Flutter 💙'),
),
),
);
}
}

Container(
height: 100,
width: 100,
decoration: BoxDecoration(
color: Colors.green,
border: Border.all(
color: Colors.black,
width: 2,
),
borderRadius: BorderRadius.circular(10),
),
child: const Text('Hello Flutter'),
),

class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(...),
home: Scaffold(
appBar: AppBar(...),
body: Column(
children: const [
Icon(Icons.category),
Icon(Icons.search),
Icon(Icons.person),
],
),
),
);
}
}

mainAxisAlignment while the opposite direction is called crossAxisAlignment
flex valueRow(
children: const [
Expanded(
flex: 1,
child: Icon(Icons.category),
),
Expanded(
flex: 2,
child: Icon(Icons.search),
),
Expanded(
flex: 3,
child: Icon(Icons.person),
),
],
),

class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(...),
home: Scaffold(
appBar: AppBar(...),
body: Center(
child: Stack(
children: [
Container(
height: 100,
width: 100,
color: Colors.green,
),
const Icon(
Icons.android,
color: Colors.white,
),
],
),
)),
);
}
}

top, left, bottom, right properties of the Positioned widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo Home Page'),
backgroundColor: Colors.deepOrange,
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Business',
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'School',
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.add),
),
drawer: Drawer(
child: ListView(
children: <Widget>[
const DrawerHeader(
decoration: BoxDecoration(
color: Colors.deepOrange,
),
child: Text('Header'),
),
ListTile(
title: const Text('Item 1'),
onTap: () {
Navigator.pop(context);
},
),
ListTile(
title: const Text('Item 2'),
onTap: () {
Navigator.pop(context);
},
),
],
),
),
),
);
}
}

ListView(
scrollDirection: Axis.vertical, // Axis.horizontal
children: [
Container(...),
Container(...),
Container(...),
Container(...),
Container(...),
Container(...),
],
),

ListView.builder(
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(
title: Text('Item $index'),
);
},
),

Convert to Stateful widget to convert it.
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo Home Page'),
backgroundColor: Colors.deepOrange,
),
),
);
}
}
build method too, but now, we can also define variables in this class.class _MyAppState extends State<MyApp> {
int counter = 0;
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo Home Page'),
backgroundColor: Colors.deepOrange,
),
),
);
}
}
setState((){}) function in our code like when a button is pressed.class _MyAppState extends State<MyApp> {
int counter = 0;
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo Home Page'),
backgroundColor: Colors.deepOrange,
),
body: Center(
child: Text('You have pressed button: $counter times'),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
counter++;
});
},
child: const Icon(Icons.add),
),
),
);
}
}

setState to change the value and the widget will automatically re-render to reflect the latest data.initState and disposeinitState method. It is called once when the widget is first initialized.dispose that runs when the widget is removed from the UI. @override
void initState() {
// TODO: implement initState
}
@override
void dispose() {
super.dispose();
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Home Page',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Home Page'),
),
body: Center(
child: ElevatedButton(
onPressed: () {},
child: const Text('About Page'),
)),
),
);
}
}
class AboutMe extends StatelessWidget {
const AboutMe({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('About Me'),
),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home Page'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const AboutMe(),
),
);
},
child: const Text('About Page'),
)),
);
}
}
class AboutMe extends StatelessWidget {
const AboutMe({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('About Me'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Back'),
),
),
);
}
}



