Flutter Course: Structuring the Basic Code of main.dart File 8.2

Flutter is an open-source UI software development kit (SDK) developed by Google, which allows for rapid building of mobile, web, and desktop applications. One of the appeals of Flutter is its ability to build applications for multiple platforms from a single codebase. In this course, we will examine the basic code structure of the main.dart file, which is central to Flutter applications.

1. Role of the main.dart File

The main.dart file is the entry point of a Flutter application. It is the first file executed when the application runs, and within this file, the main structure and UI of the application are defined.

Main Roles:

  • Application setup and initialization
  • Configuration of the top-level widget
  • Declaration of the root widget

1.1 Basic Structure

The basic main.dart file starts with the following structure:

        
        import 'package:flutter/material.dart';

        void main() {
            runApp(MyApp());
        }

        class MyApp extends StatelessWidget {
            @override
            Widget build(BuildContext context) {
                return MaterialApp(
                    title: 'Flutter Course',
                    home: Scaffold(
                        appBar: AppBar(
                            title: Text('Main Page'),
                        ),
                        body: Center(
                            child: Text('Hello, Flutter!'),
                        ),
                    ),
                );
            }
        }
        
        

2. Code Components

Let’s analyze the example code above and look at the roles of each part.

2.1 Importing Necessary Packages

We import the packages necessary to use Flutter’s features. The flutter/material.dart package provides Material Design UI components, allowing for easy routing and state management.

2.2 main() Function

The main() function, which is the entry point of the Flutter application, executes the root widget through the runApp() function. Here, we instantiate and run the MyApp class.

2.3 StatelessWidget

The MyApp class inherits from StatelessWidget. This means it does not have state and is suitable for cases where the data used to draw the UI does not change.

2.4 build() Method

The build() method is responsible for creating the widget’s UI and takes BuildContext as a parameter. Within the build() method, widgets like MaterialApp and Scaffold are defined. The Scaffold widget provides a basic app layout.

3. Improving the Example Application

While you can create a simple application using the basic code, it can be improved by adding more features. Below is an example that adds a button to the basic application, which changes the text when clicked.

        
        import 'package:flutter/material.dart';

        void main() {
            runApp(MyApp());
        }

        class MyApp extends StatefulWidget {
            @override
            _MyAppState createState() => _MyAppState();
        }

        class _MyAppState extends State {
            String message = 'Hello, Flutter!';

            void _changeMessage() {
                setState(() {
                    message = 'Button has been clicked!';
                });
            }

            @override
            Widget build(BuildContext context) {
                return MaterialApp(
                    title: 'Flutter Course',
                    home: Scaffold(
                        appBar: AppBar(
                            title: Text('Main Page'),
                        ),
                        body: Center(
                            child: Column(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: [
                                    Text(message),
                                    SizedBox(height: 20),
                                    ElevatedButton(
                                        onPressed: _changeMessage,
                                        child: Text('Change Message'),
                                    ),
                                ],
                            ),
                        ),
                    ),
                );
            }
        }
        
        

3.1 Adding StatefulWidget

In the example above, we used StatefulWidget instead of StatelessWidget since the state can change. StatefulWidget has internal state and is used when the UI may change based on that state.

3.2 setState() Method

When the button is clicked, we call the _changeMessage() method to update the state and use setState() to redraw the UI. This allows us to create a dynamically responsive UI for the application.

4. Widget Structure of Flutter

The UI in Flutter consists of widgets. Every UI element is represented as a widget, and widgets can be combined to form complex UIs. Widgets can be broadly divided into two categories:

  • StatelessWidget: A widget that does not change its state and has a static UI
  • StatefulWidget: A widget that has an internal state and can change its UI based on that state

5. Flutter Project Structure

A Flutter project is composed of several directories and files. The basic file structure generated is as follows:

  • lib/ – Contains commonly used Dart files
  • pubspec.yaml – Dependency and resource management file
  • android/ – Android-related settings and code
  • ios/ – iOS-related settings and code

6. Conclusion

In this course, we examined the basic structure and components of the main.dart file in Flutter. The application runs through the main.dart file, and we can create the UI through a combination of widgets. We also learned how to build dynamic applications utilizing StatelessWidget and StatefulWidget. This foundational course will be a great help when structuring more complex UIs in the future.

Continue learning for more information and in-depth courses on Flutter! In the next session, we will explore more widgets and advanced features of Flutter.

Flutter Course, 7.8 Using CircleAvatar Widget

Hello! Today, we will learn about the CircleAvatar widget, which is one of the user interface (UI) components in Flutter. In this tutorial, we will detail the basic concepts of the CircleAvatar widget, various usage examples, and how to customize it. Learn how to enhance the user experience of your app using the CircleAvatar widget.

1. What is CircleAvatar?

CircleAvatar is a widget that is commonly used to display profile pictures or user avatars, having a circular shape. This widget can show various contents such as images, icons, and text in a circular format. The CircleAvatar widget is a very useful element for implementing various designs in user interfaces.

1.1 Basic Usage of CircleAvatar

To use the CircleAvatar widget, you can follow this basic format:

CircleAvatar(
  radius: 30.0,
  backgroundImage: NetworkImage("https://example.com/image.png"),
)

In the code above, radius sets the radius of the avatar, and backgroundImage specifies the image to be displayed inside the circle. This allows for a simple creation of a circular avatar.

2. Description of CircleAvatar Properties

The CircleAvatar widget provides various properties that enable customized designs. The main properties are as follows:

  • backgroundColor: Sets the background color of the avatar. You can specify the color to display when the image is not loaded.
  • backgroundImage: Sets the image to be displayed on the avatar. You can use either NetworkImage or AssetImage.
  • radius: Sets the radius of the avatar. The default value is 20.
  • child: This is a widget that can be added inside the avatar. It is typically used to add text or icons.

2.1 Example of CircleAvatar Properties

CircleAvatar(
  radius: 50,
  backgroundColor: Colors.blue,
  child: Text("A", style: TextStyle(color: Colors.white, fontSize: 24),),
)

The above example creates a circular avatar with a blue background color and displays the text ‘A’ in white. This example illustrates how to create a CircleAvatar widget that includes text.

3. Various Usage Examples of CircleAvatar

The CircleAvatar widget can be used for various purposes beyond representing a profile picture. Below are some usage examples.

3.1 User Profile Image

CircleAvatar is often used to display user profile images in social media apps. Here is an example of loading a profile image:

CircleAvatar(
  radius: 40,
  backgroundImage: NetworkImage("https://example.com/user_profile.jpg"),
)

3.2 Color-Based Avatar

It is also nice to create avatars that can be identified by color based on specific users or categories. For example, it can be implemented in the following format:

CircleAvatar(
  radius: 30,
  backgroundColor: Colors.red,
  child: Text("U", style: TextStyle(color: Colors.white)),
)

3.3 Alternative Image

If loading an image from the network is not possible, it is also possible to provide an alternative image. In this case, the backgroundColor property can be utilized to set the background color of the avatar. This can be implemented in the following manner:

CircleAvatar(
  radius: 30,
  backgroundColor: Colors.grey,
  child: Icon(Icons.person, color: Colors.white),
)

4. Customizing CircleAvatar

To make CircleAvatar more unique, you can combine its properties appropriately to apply your own style. Below are some tips for customizing CircleAvatar:

4.1 Adding a Border

If you want to add a border to CircleAvatar, you can wrap the CircleAvatar with a Container widget. Here is an example of a CircleAvatar with a border:

Container(
  decoration: BoxDecoration(
    shape: BoxShape.circle,
    border: Border.all(
      width: 2.0,
      color: Colors.blue,
    ),
  ),
  child: CircleAvatar(
    radius: 40,
    backgroundImage: NetworkImage("https://example.com/image.jpg"),
  ),
)

4.2 Changing Size

You can use different radius values to have avatars of various sizes. By adjusting the radius, you can dynamically change the size of the avatar.

4.3 Combining Text and Icons

It is also possible to combine text and icons inside CircleAvatar. This can be implemented in the following manner:

CircleAvatar(
  radius: 40,
  backgroundColor: Colors.green,
  child: Row(
    mainAxisSize: MainAxisSize.min,
    children: [
      Icon(Icons.person, color: Colors.white),
      SizedBox(width: 5),
      Text("User", style: TextStyle(color: Colors.white)),
    ],
  ),
)

5. Using CircleAvatar with ListView

It is possible to dynamically display multiple avatars by combining the CircleAvatar widget with ListView. Here is an example of using ListView to display multiple avatars:

ListView.builder(
  itemCount: 10,
  itemBuilder: (context, index) {
    return ListTile(
      leading: CircleAvatar(
        radius: 30,
        backgroundImage: NetworkImage("https://example.com/user_$index.jpg"),
      ),
      title: Text("User $index"),
    );
  },
)

6. Considerations When Using CircleAvatar

When using CircleAvatar, consider the following points:

  • When selecting images, it is important to choose the appropriate size and format to reduce load time.
  • When using network images, logic to handle loading errors is also necessary.
  • Colors and sizes should be adjusted to harmonize with the UI design.

7. Conclusion

In this post, we learned about various ways of using and customizing the CircleAvatar widget in Flutter. CircleAvatar is a simple yet powerful UI element. By utilizing it, you can provide a strong user experience in various apps. Try implementing CircleAvatar yourself and make your app more attractive with your own style!

Thank you!

Flutter Course: Understanding the Structure of an App

Flutter is a powerful UI toolkit developed by Google that allows for the easy creation of applications not only for iOS and Android but also for web and desktop. In this course, we will understand the overall structure of a Flutter app and how each component interacts with one another. Before we start, let’s briefly review the basic concepts of Flutter.

Basic Components of Flutter

A Flutter application consists of several basic components:

  • Widgets: Everything in Flutter is represented as a widget. All elements of the user interface are a collection of widgets.
  • Root Widget: Every app starts with a single root widget. This root widget is located at the top of the widget tree that makes up the entire UI of the app.
  • Singleton: A Flutter application typically has a single main method, in which runApp() is called to execute the root widget.
  • Widget Tree: The UI of the app is organized in the form of a widget tree, allowing each widget to contain other widgets. This makes it easy to create complex UIs.

Flutter App Architecture

To understand the architecture of a Flutter app, we first need to look at its basic structure. Flutter primarily consists of the following three main components:

  • Framework: Includes high-level APIs that provide the main functionality of Flutter. It can implement various features such as user interface, animations, and networking.
  • Engine: Provides the development environment for Flutter and performs low-level functions such as UI rendering, text processing, and image processing.
  • Widgets & Packages: Developers can easily add the necessary functionality by using the basic widgets provided by Flutter or by using packages that provide additional features.

1. Role of the Framework

The Flutter framework offers high-level APIs to help developers create applications easily. It supports various functions, including UI components and state management, to maintain app consistency. Additionally, it contains all the necessary features to provide a consistent UI experience across different platforms.

2. Role of the Engine

The Flutter engine is written in C++ and primarily performs the functions of rendering the UI and handling events. It offers high performance and horizontal scalability, supporting various types of applications.

3. Widgets and Packages

Flutter provides various widgets that make it easy to construct the UI. These widgets can be infinitely nested, and each widget can have its own independent state. By using packages, developers can easily utilize various tools and libraries created by the community. Simply find and install the necessary packages from pub.dev.

Understanding State Management

State management is very important in Flutter apps. The UI of the app varies according to its state, which directly affects the user experience. There are several methods for state management, and some representative methods include:

  • setState: The simplest method for state management, used to update the UI in a StatefulWidget.
  • InheritedWidget: A method for sharing data in the widget hierarchy, allowing data to propagate from deep parent widgets to child widgets.
  • Provider: One of the most commonly used state management patterns, providing a simple API and reactive design.
  • Bloc Pattern: A pattern that helps to manage complex application logic neatly, emphasizing the separation of state management and business logic.

Example of App Structure

Now, let’s apply what we’ve discussed above through a simple Flutter app example. The code below creates a simple root widget.

import 'package:flutter/material.dart';

    void main() {
      runApp(MyApp());
    }

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter App Structure Example',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(),
        );
      }
    }

    class MyHomePage extends StatefulWidget {
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }

    class _MyHomePageState extends State {
      int _counter = 0;

      void _incrementCounter() {
        setState(() {
          _counter++;
        });
      }

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Flutter App Structure Example'),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  'Number of times the button has been pressed:',
                ),
                Text(
                  '$_counter',
                  style: Theme.of(context).textTheme.headline4,
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ),
        );
      }
    }

In the above example, we created a simple counter app. Each time the user clicks the button, the count increases, which is the most basic example of state management. The setState() method is called to update the UI.

Conclusion

In this course, we learned about the structure of Flutter apps, the importance of basic components, and state management. Understanding how the Flutter framework, composed of high-level APIs, makes app development easier and how each element interacts with one another is crucial. Utilizing various state management patterns can efficiently manage even complex applications.

We hope you create your own apps using Flutter’s various features and enhance your development skills by adding more functionalities. In the next session, we will explore various packages and plugins available in Flutter.

Thank you for reading!

Flutter Course: Using the Row Widget

In programming, the elements that compose the layout are as important as the business logic of the user interface (UI). In this post, we will delve into the use of the Row widget in the Flutter framework. The Row widget allows you to arrange elements horizontally, enabling a flexible design through various properties. This tutorial will detail how to use the Row widget and its advantages.

Basic Concepts of the Row Widget

The Row widget is one of the main layout widgets in Flutter, aligning multiple child widgets side by side horizontally. The Row widget can be used with Flexible and Expanded widgets to create more complex layouts. By default, the Row will automatically adjust its size based on the number of child widgets.

Structure of the Row Widget


Row(
  children: [
    Icon(Icons.star),
    Text('Star'),
    Icon(Icons.star),
  ],
)

The example above shows the basic structure of the Row widget. The Row contains various widgets, in this case, Icon and Text. You can easily extend it by adding the widgets needed for your interface design.

Main Properties of the Row Widget

The Row widget has several properties that you can use to adjust the UI. Among them, the most important properties are:

  • mainAxisAlignment: Aligns the child widgets along the main axis direction of the Row.
  • crossAxisAlignment: Aligns the child widgets along the cross axis direction of the Row.
  • mainAxisSize: Determines the width of the Row, adjusting the size along the main axis.
  • textDirection: Sets the text direction. It can be set from left to right or right to left.
  • verticalDirection: Determines the vertical alignment of the child widgets.

mainAxisAlignment Property

Let’s learn how to use the mainAxisAlignment property to align child widgets in the Row along the main axis direction. The following example shows various alignment options.


Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: [
    Icon(Icons.star),
    Icon(Icons.star),
    Icon(Icons.star),
  ],
)

In the above example, MainAxisAlignment.spaceBetween adds equal spacing between all icons, positioning the icons at both ends of the Row.

crossAxisAlignment Property

The crossAxisAlignment property determines how the child elements within the Row will be aligned vertically. Let’s take a look at the following example.


Row(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Icon(Icons.star),
    Text('Star', style: TextStyle(fontSize: 20)),
    Icon(Icons.star),
  ],
)

In this example, CrossAxisAlignment.start aligns the icon and text at the top, making all elements align to one side.

Use Cases for the Row Widget

The Row widget can be utilized in various ways. Here are some descriptions of different use cases.

1. Button Group

You can create a group of buttons by placing different buttons horizontally using Row. For example, create a button group like the one below.


Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    ElevatedButton(onPressed: () {}, child: Text('Button 1')),
    ElevatedButton(onPressed: () {}, child: Text('Button 2')),
    ElevatedButton(onPressed: () {}, child: Text('Button 3')),
  ],
)

2. Image and Text Combination

The Row is also useful for placing images and text together. You can use it as shown below for a beautiful UI.


Row(
  children: [
    Image.network('https://example.com/image.png', width: 50, height: 50),
    SizedBox(width: 10),
    Text('Image Description'),
  ],
)

3. Card Layout

The Row is also useful in card layouts. Below is a simple example of a card layout.


Row(
  children: [
    Card(
      child: Column(
        children: [
          Image.network('https://example.com/image1.png'),
          Text('Card 1'),
        ],
      ),
    ),
    SizedBox(width: 10),
    Card(
      child: Column(
        children: [
          Image.network('https://example.com/image2.png'),
          Text('Card 2'),
        ],
      ),
    ),
  ],
)

Combining Row Widget with Expanded Widget

Using the Row widget together with the Expanded widget is a great way to optimize space utilization. The Expanded widget allows the size of child widgets to stretch based on the available space.


Row(
  children: [
    Expanded(
      child: Container(color: Colors.red, height: 50),
    ),
    SizedBox(width: 10),
    Expanded(
      child: Container(color: Colors.green, height: 50),
    ),
  ],
)

In the above example, two Expanded widgets are placed together in the Row. Each Container widget will maximize its size to fit the allocated space. Note that if there are multiple Expanded widgets in the Row, each Expanded distributes its space in the same ratio.

Combining Row Widget with Column Widget

Combining the Row widget with the Column widget allows for easier construction of more complex layouts. Below is an example of using a Row widget within a Column.


Column(
  children: [
    Text('Top Text'),
    Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Icon(Icons.star),
        SizedBox(width: 10),
        Icon(Icons.star),
      ],
    ),
    Text('Bottom Text'),
  ],
)

Adjusting Size of the Row Widget

Adjusting the size of the Row widget is very important in UI design. Especially, when there’s no need to adjust the width, you can utilize the mainAxisSize property.

For example, to limit the size of the row to the size occupied by its child widgets, you can set it as follows.


Row(
  mainAxisSize: MainAxisSize.min,
  children: [
    Icon(Icons.star),
    Text('Star'),
    Icon(Icons.star),
  ],
)

Possibilities of the Row Widget

The Row widget can be used effectively, and with various configurations and combinations, a more diverse UI can be created. Experimenting with the Row widget directly is also a good learning method, so continue to modify the examples in your own way.

Conclusion

The Row widget is an essential tool for creating powerful and responsive UIs using Flutter. This tutorial covered a wide range of topics from the basic concepts to applications of the Row widget. It’s advisable to gain deeper experience by practically utilizing the Row widget in projects. Based on this foundation, you should be able to implement more complex layouts.

Stay tuned for more updates on Flutter tutorials!

Flutter Course: 7.6 crossAxisAlignment Property and Align Widget

In this course, we will delve deeply into the crossAxisAlignment property and the Align widget, which play a crucial role in Flutter’s layout composition. To fully leverage the strengths of Flutter on Android and iOS platforms when building user interfaces (UIs), it is essential to clearly understand layout directionality and alignment issues.

1. Understanding Layout in Flutter

Flutter is a widget-based framework where everything consists of widgets. Layouts are constructed by combining multiple widgets, and the alignment and arrangement of these widgets are very important. In Flutter’s layout system, axes are defined to determine the alignment of layout components. The concepts of main axis and cross axis are significant: the main axis is the direction in which widgets are primarily arranged, while the cross axis is the direction perpendicular to that.

2. The crossAxisAlignment Property

The crossAxisAlignment property is used in Flex widgets like Row or Column to specify the alignment of components along the cross axis. There are several values, and each value changes how the components are aligned.

2.1. Key Values of crossAxisAlignment

  • CrossAxisAlignment.start: Aligns at the starting point of the cross axis.
  • CrossAxisAlignment.end: Aligns at the ending point of the cross axis.
  • CrossAxisAlignment.center: Aligns at the center of the cross axis.
  • CrossAxisAlignment.stretch: Stretches to fill the cross axis direction according to the main axis length.
  • CrossAxisAlignment.baseline: Aligns based on the baseline of the main axis.

2.2. Example of Using crossAxisAlignment

import 'package:flutter/material.dart';

class CrossAxisAlignmentExample extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(title: Text('Example of crossAxisAlignment')),
            body: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                    Container(height: 50, width: 100, color: Colors.red),
                    Container(height: 100, width: 50, color: Colors.blue),
                    Container(height: 75, width: 200, color: Colors.green),
                ],
            ),
        );
    }
}

void main() => runApp(MaterialApp(home: CrossAxisAlignmentExample()));

In the example above, the crossAxisAlignment property of the Column widget is set to CrossAxisAlignment.center. In this case, the three Container widgets are aligned at the center of the cross axis.

3. The Align Widget

The Align widget is used to specify the position of a widget. It is primarily used as a child of other widgets and provides the functionality to adjust the position of the child in the cross axis direction. The alignment property of the Align widget offers various ways to set the position of the widget.

3.1. alignment Property of the Align Widget

  • Alignment.topLeft: Top-left corner
  • Alignment.topCenter: Top center
  • Alignment.topRight: Top-right corner
  • Alignment.centerLeft: Center-left
  • Alignment.center: Center
  • Alignment.centerRight: Center-right
  • Alignment.bottomLeft: Bottom-left corner
  • Alignment.bottomCenter: Bottom center
  • Alignment.bottomRight: Bottom-right corner

3.2. Example of Using Align

import 'package:flutter/material.dart';

class AlignExample extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(title: Text('Example of Align Widget')),
            body: Container(
                height: 200,
                width: 200,
                color: Colors.grey[300],
                child: Align(
                    alignment: Alignment.bottomRight,
                    child: Container(
                        height: 50,
                        width: 50,
                        color: Colors.red,
                    ),
                ),
            ),
        );
    }
}

void main() => runApp(MaterialApp(home: AlignExample()));

In the example above, the child widget of the Container is aligned to the bottom right through the Align widget. This allows the Align widget to precisely position a widget in a specific location.

4. Combining crossAxisAlignment and Align

By combining the crossAxisAlignment and Align widgets, more flexible layouts can be implemented. For example, you can align each child element in the cross axis within a Row widget and use the Align widget to adjust positioning.

import 'package:flutter/material.dart';

class CombinedExample extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(title: Text('Example of crossAxisAlignment and Align')),
            body: Row(
                crossAxisAlignment: CrossAxisAlignment.end,
                children: [
                    Align(
                        alignment: Alignment.centerLeft,
                        child: Container(height: 50, width: 50, color: Colors.red),
                    ),
                    Align(
                        alignment: Alignment.center,
                        child: Container(height: 75, width: 50, color: Colors.blue),
                    ),
                    Align(
                        alignment: Alignment.centerRight,
                        child: Container(height: 100, width: 50, color: Colors.green),
                    ),
                ],
            ),
        );
    }
}

void main() => runApp(MaterialApp(home: CombinedExample()));

In the above example, the crossAxisAlignment of the Row widget is set to CrossAxisAlignment.end, and each Container is individually aligned through the Align widget. This helps in easily constructing complex layouts.

5. Performance Optimization and Layout Effect Analysis

When using the crossAxisAlignment property and the Align widget, it is also important to optimize performance. You can improve rendering performance by avoiding unnecessary widget tree nesting and removing unused widgets. This can enhance the performance of Flutter applications while also improving the user experience.

6. Summary

In this course, we conducted an in-depth analysis of the crossAxisAlignment property and the Align widget in Flutter. By appropriately combining these two elements when constructing layouts, you can create a very flexible and powerful user interface. When designing layouts, apply the alignment and positioning in the cross axis effectively to greatly improve your app’s UI/UX while being mindful of performance for efficient app development.

As we conclude the course, I hope you will learn and apply more about advanced layout compositions. Wishing you to enjoy the charm of app development with Flutter.