Flutter系列文章-Flutter基礎

2023-07-17 15:00:30

Flutter是Google推出的一種新的移動應用開發框架,允許開發者使用一套程式碼庫同時開發Android和iOS應用。它的設計理念、框架結構、以及對Widget的使用,都讓開發者能更有效率地建立高質量的應用。

一、Flutter設計理念

Flutter的設計理念是「一切皆為Widget」。這意味著不論是按鈕、字型、顏色、佈局,甚至是你的整個應用程式,都是由一個個Widget組合而成。在Flutter中,Widget可以巢狀、包裹或組合在一起,形成複雜的UI元件,這給了開發者極大的靈活性和創造力。

二、Flutter框架結構

Flutter框架由一系列層次結構構成。自底向上,主要包括:

  • Dart平臺:Flutter使用Dart語言編寫,Dart平臺包括一個能夠為Flutter生成原生ARM程式碼的Dart JIT和AOT編譯器。

  • Flutter引擎:主要用C++編寫,它提供了低階渲染支援。它還負責外掛系統、文字佈局和型別設定、網路和檔案 I/O、執行緒管理等。

  • Foundation庫:提供了和Dart一致的基本型別和實用工具,使得其他更高階別的庫可以共用相同的設計和實現。

  • Widgets:描述應用程式使用者介面和互動的模組。關鍵概念包括Widget、StatelessWidget、StatefulWidget、State等。

三、Flutter中的Widget

Flutter中的Widget即是宣告UI的檢視,也是檢視和介面變化的橋樑。一個Widget可以定義:

一個結構元素(如按鈕或選單)
一個樣式元素(如字型或顏色模式)
甚至是佈局方面的元素(如填充或對齊方式)
在Flutter中,Widget的主要任務是提供一個build()方法,用於描述在UI中所看到的內容。

四、StatelessWidget和StatefulWidget

StatelessWidget是不可變的。它們描述了在給定設定下應該如何構建UI。而StatefulWidget則可以在生命週期內改變狀態。實現一個StatefulWidget至少需要兩個類:1)一個StatefulWidget類;2)一個State類。

五、基礎佈局Widgets

在Flutter中有很多佈局Widget,比如Row,Column和Stack等。Row和Column是基本佈局Widget,它們都接受一列子Widget,並在水平或垂直方向上排列。Stack可以將Widget堆疊在一起,實現各種複雜的佈局。

六、Flutter程式結構

一個基本的Flutter程式通常包括以下部分:

  • main函數:應用的入口點。
  • MyApp類:StatelessWidget,返回一個包含應用主題、路由和主頁的MaterialApp Widget。
  • 主頁類:可為StatelessWidget或StatefulWidget,包含應用主體部分。
  • 其他Widget類:你自定義的Widget,可被主頁類或其他Widget類使用。
    掌握了這些基礎知識,你就能更好地使用Flutter框架進行應用開發,建立出精美並具有良好使用者體驗的應用程式。

七、Flutter的Widget

7.1. 基礎Widgets

在Flutter中,所有的介面元素都是由Widget構建的。每一個Widget都描述了介面上應該看到什麼。你可以把Widget看作是應用介面的一個構建塊。它們包括用於顯示文字、圖片、圖示、輸入框以及行為等的元素。

7.1.1 Text:這個widget用於顯示簡單的樣式文字,它包含一些控制文字顯示樣式的屬性。####

Text(
  'Hello, World!',
  textAlign: TextAlign.center,
  style: TextStyle(fontWeight: FontWeight.bold),
)

7.1.2 Image:用於顯示圖片的widget,支援多種方式的圖片載入,例如網路、資源、檔案系統等。

Image.network('https://example.com/images/sample.jpg')

7.1.3 Icon:Material Design的圖示widget。

Icon(Icons.star, color: Colors.red[500])

7.2. Widget型別:StatelessWidget和StatefulWidget。

7.2.1. StatelessWidget

StatelessWidget是不可變的,它描述了在給定設定下應該如何構建UI。例如,下面的程式碼展示瞭如何建立一個自定義的StatelessWidget,它返回一個紅色的星星圖示:

class MyIcon extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Icon(Icons.star, color: Colors.red[500]);
  }
}

7.2.2. StatefulWidget

StatefulWidget是動態的。它們可以在生命週期內改變狀態,例如響應使用者的互動。一個StatefulWidget至少需要兩個類:StatefulWidget類和State類。以下是一個例子:

class Counter extends StatefulWidget {
  Counter({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _CounterState createState() => _CounterState();
}

class _CounterState extends State<Counter> {
  int _counter = 0;

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

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Text('You have pushed the button $_counter times.'),
        RaisedButton(
          onPressed: _incrementCounter,
          child: Text('Increment'),
        ),
      ],
    );
  }
}

這個例子建立了一個名為Counter的新StatefulWidget。每當使用者按下"Increment"按鈕時,_counter 的值就會增加,並且UI會自動更新。

八、Flutter的基本佈局Widgets

在Flutter中,我們有許多預定義的佈局Widget,例如Row、Column和Stack。

8.1. Row和Column

Row和Column是兩個最常用的佈局Widget。它們都接受一列子Widget,並在水平或垂直方向上排列。以下是一個使用Row的例子,它包含了三個紅色的星星圖示:

Row(
  mainAxisAlignment: MainAxisAlignment.spaceAround,
  children: <Widget>[
    Icon(Icons.star, color: Colors.red[500]),
    Icon(Icons.star, color: Colors.red[500]),
    Icon(Icons.star, color: Colors.red[500]),
  ],
)

8.2. Stack

Stack是一個佈局Widget,它可以將子Widget堆疊在一起。你可以使用Positioned widget來定位Stack中的子Widget。以下是一個簡單的Stack範例:

Stack(
  alignment: const Alignment(0.6, 0.6),
  children: [
    CircleAvatar(
      backgroundImage: AssetImage('images/pic.jpg'),
      radius: 100.0,
    ),
    Container(
      decoration: BoxDecoration(
        color: Colors.black45,
      ),
      child: Text(
        'Hello World',
        style: TextStyle(
          fontSize: 20.0,
          fontWeight: FontWeight.bold,
          color: Colors.white,
        ),
      ),
    ),
  ],
)

九、下面我們建立一個Flutter的範例應用,包括之前提到的一些關鍵概念,包括Widget,StatelessWidget,StatefulWidget,以及Row,Column和Stack佈局。

import 'package:flutter/material.dart';

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

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

class MyHomePage extends StatefulWidget {
  final String title;

  MyHomePage({required this.title, key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

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

  void _decrementCounter() {
    setState(() {
      _counter--;
    });
  }

  @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.headline4,
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: <Widget>[
                FloatingActionButton(
                  onPressed: _incrementCounter,
                  tooltip: 'Increment',
                  child: Icon(Icons.add),
                ),
                FloatingActionButton(
                  onPressed: _decrementCounter,
                  tooltip: 'Decrement',
                  child: Icon(Icons.remove),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

通過這篇文章,你應該對Flutter有了一個基礎的理解,包括Flutter的設計理念、框架結構、Widget系統、以及如何使用不同型別的Widgets來建立介面和佈局。接下來,我們會深入到更高階的主題,包括如何處理使用者互動,如何建立動畫,以及如何存取網路資料等等。