In this course, we aim to gain a deeper understanding of the basic code in Flutter, by practicing with simple examples and explaining important concepts along the way. In conjunction with the content covered in the previous course, we will review the basic syntax and structure of Flutter and the Dart language, while exploring how to utilize additional features.
1. Flutter Basic Code Structure
Flutter is a framework that allows for the combination of various widgets for app development. The most fundamental component of a Flutter application is the ‘widget’. Everything is written as a widget, which serves to compose elements of the screen. Below is the structure of a simple Flutter application.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Understanding Basic Flutter Code 2'),
),
body: Center(
child: Text('Hello, Flutter!'),
),
),
);
}
}
In the code above, the ‘main’ function is the entry point of the Flutter application. It starts the application using the MyApp class by calling the ‘runApp()’ function.
2. StatelessWidget and StatefulWidget
In Flutter, widgets can be broadly categorized into StatelessWidget and StatefulWidget.
2.1 StatelessWidget
StatelessWidget is a widget that does not have state. This means that this widget does not change its state after it has been created. For example, the code below describes a simple StatelessWidget.
class Greeting extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text('Hello, user!');
}
}
The above widget always displays the same text each time an instance is created.
2.2 StatefulWidget
StatefulWidget is a widget that can have state. When the state changes, the content of the widget is updated as well. Here is a simple example of a StatefulWidget.
class Counter extends StatefulWidget {
@override
_CounterState createState() => _CounterState();
}
class _CounterState extends State {
int _count = 0;
void _incrementCounter() {
setState(() {
_count++;
});
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('The button has been pressed $_count times.'),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('Click the button!'),
),
],
);
}
}
This example increases the count each time the button is pressed and shows the current count on the screen. An important point here is the setState() method. When this method is called, Flutter recognizes that the state of the widget has changed and updates the UI.
3. Flutter Layout System
Flutter provides various layout widgets to easily compose complex UIs. Basic layout widgets include Column, Row, Stack, and Container.
3.1 Column and Row
The Column widget arranges its child widgets vertically, while the Row widget arranges its child widgets horizontally. Below is an example code using Column and Row.
class LayoutExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
Row(
children: [
Icon(Icons.star),
Text('Star Icon'),
],
),
Row(
children: [
Icon(Icons.favorite),
Text('Heart Icon'),
],
),
],
);
}
}
3.2 Container and Padding
The Container widget is a very flexible widget that can be configured with various properties. The Padding widget can be used to add space around a child widget.
class PaddedContainer extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Container(
color: Colors.blue,
height: 100,
width: 100,
child: Center(
child: Text(
'Container',
style: TextStyle(color: Colors.white),
),
),
),
);
}
}
4. Interaction and Event Handling
Flutter provides various ways to handle interaction with the user. It can recognize various gestures such as button clicks and swipes. The example below describes how to handle touch events using GestureDetector.
class GestureExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
print('Tapped!');
},
child: Container(
color: Colors.green,
height: 100,
width: 100,
child: Center(
child: Text('Tap me!'),
),
),
);
}
}
GestureDetector can handle various events (tap, double tap, etc.), and in the above example, it is processing only the tap event. When an event occurs, the specified method is invoked.
5. Flutter Customization
Flutter provides a way to easily customize widgets. You can apply a consistent style across the app using ThemeData.
class ThemedApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
textTheme: TextTheme(
bodyText2: TextStyle(color: Colors.white, fontSize: 18),
),
),
home: Scaffold(
appBar: AppBar(
title: Text('Theme Example'),
),
body: Center(
child: Text('This text is themed.'),
),
),
);
}
}
The code above specifies a theme within the MaterialApp that sets the color and size of text across the application. This helps reduce code duplication and maintain a consistent style for the application.
6. Practical Project: Creating a Simple To-Do List App
In this section, we will create a simple to-do list app based on what we have learned so far. Through this, you will experience the basic functionality of Flutter.
6.1 Project Setup
First, create a new Flutter project. Enter the following command to create the Flutter project.
flutter create todo_list
After moving to the project directory, open the lib/main.dart
file, delete the default template, and add the code below.
import 'package:flutter/material.dart';
void main() {
runApp(TodoListApp());
}
class TodoListApp extends StatefulWidget {
@override
_TodoListAppState createState() => _TodoListAppState();
}
class _TodoListAppState extends State {
List _todos = [];
final TextEditingController _controller = TextEditingController();
void _addTodo() {
setState(() {
_todos.add(_controller.text);
_controller.clear();
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('To-Do List'),
),
body: Column(
children: [
TextField(
controller: _controller,
decoration: InputDecoration(labelText: 'Enter task'),
),
ElevatedButton(
onPressed: _addTodo,
child: Text('Add'),
),
Expanded(
child: ListView.builder(
itemCount: _todos.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_todos[index]),
);
},
),
),
],
),
),
);
}
}
The code above structures the basic parts of the to-do list app, allowing you to add tasks using a text field and a button, displaying the list of tasks.
6.2 Adding Functionality and Testing
After writing the code, run the application to be able to add to-do items. Through this process, you can experience just how effective Flutter is in creating fast and efficient UIs.
7. Conclusion and Next Course Preview
In this course, we understood the basic code of Flutter and practiced with widgets, layouts, event handling, and more. Flutter is a very flexible and powerful framework that allows for the easy creation of various apps. In the next course, we will cover state management patterns and asynchronous programming in Flutter.
Thank you.