Skip to content

[Flutter] 使用 StatefulWidget 動態改變頁面與元件的樣式

在剛學習著使用 Flutter 開發 App 的時期,一定會在撰寫界面的時候疑惑:不知道現在究竟該使用 StatefulWidget?還是應該要使用 StatelessWidget?

其實使用場合非常簡單就能分辨:

  • StatelessWidget: 頁面創立好之後就不會更動。
  • StatefulWidget: 頁面上的元件與使用者會有互動、元件樣式可能會改變。

今天我就簡單地紀錄每次使用 IDE 打開專案,都能看到『點擊按鈕,使畫面中央數字增加』—— 這個簡單 DEMO 的程式碼是如何運作。當然,既然我們改變了畫面中央的數字,那麼這想必得使用能使元件『改變』的『StatefulWidget』才行。(這個 DEMO 我有在《Flutter 學習心得筆記 (0) 下載 Intellij IDEA》當中測試過。)

就是這個。

若是對 Flutter 學習有興趣,可以參閱他們的官方 Tutorial: https://flutter.dev/docs/reference/tutorials


StatefulWidget

事先聲明,我有刪除一些不必要的程式碼,比如 AppBar 以及名稱傳遞之類的程式,力求最小化的範例程式。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}



這邊我們定義了程式的進入點(main()),這裡我們使用 StatelessWidget,應該這邊以後並不會再改變了。

以下我們接著定義 MyHomePage()。

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



這裡我們就要使用 StatefulWidget 了。我們使用 “createState()” 這個函式來實例化我們接下來要撰寫的頁面,在這之後,若是我們需要重繪頁面,就使用 “setState()” 函式來重繪頁面。

接下來終於要來製作我們 App 最主要的界面了:一個『顯示點擊按鈕次數的文字』、一個『按鈕』。

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      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),
      ),
    );
  }



Output:

這張圖片的 alt 屬性值為空,它的檔案名稱為 01-6.png
這是點擊了 9 次之後的模樣。

別忘了,一開始我們應該使用 _counter 變數來儲存我們點擊次數,有下底線 “_” 的變數都是私有變數。然後我們定義一個 function _incrementCounter() 來增加 _counter,並將其放到下面點擊按鈕觸發的『事件』裡。

這樣一來,我們『點擊按鈕,使畫面中央數字變化』的簡單 DEMO 就完成了!


也可以更改元件顏色

接下來我們來更改除了點擊數字以外的元件屬性吧?

跟上方的 DEMO 一樣依樣畫葫蘆,我們將改變的物件更改為『Color』,並賦予畫面當中的文字。

這樣一來,就變成我們點擊按鈕就會改變文字顏色了:

import 'dart:math';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

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

class _MyHomePageState extends State<MyHomePage> {
  Color _color = Color.fromARGB(255, 0, 0, 200);

  void _colorChange() {
    setState(() {
      _color = Color.fromARGB(255, Random().nextInt(256), Random().nextInt(256), Random().nextInt(256));
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
              style: TextStyle(color: _color),
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _colorChange,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}



Output:

可以看到,每次點擊按鈕之後,中央文字都會改變。


以上就是關於 Flutter 當中 StatefulWidget 的簡單紀錄。之所以會寫這個是因為我今天想要將從前寫過的 App 從 Android Studio (Java) 移植到 Flutter 上 (我要拋棄 Java 啦!)

然後,我熊熊忘記 StatefulWidget 該怎麼寫……對啦,就是 createState() 那一段。

Tags:

Leave a Reply