點燈坊

失くすものさえない今が強くなるチャンスよ

TextFormField 實現進階輸入框

Sam Xiao's Avatar 2024-10-19

TextFormField 可實現進階輸入框,搭配 TextEditingController 可支援 Two Way Binding。

Version

Flutter 3.24

TextFormField

textformfield01

  • Android 與 iOS 都成功使用 TextFormField 顯示
import 'package:flutter/material.dart';

class Home extends StatefulWidget {
  const Home({super.key});

  
  State<Home> createState() {
    return _Home();
  }
}

class _Home extends State<Home> {
  final _textEditingController = TextEditingController();
  var _greeting = '';

  
  void initState() {
    super.initState();
    _textEditingController.text = 'Hello World';

    _textEditingController.addListener(() {
      setState(() {
        _greeting = _textEditingController.text;
      });
    });
  }

  
  void dispose() {
    _textEditingController.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    var appBar = AppBar(title: const Text('TextFormField'));

    var textFormField = TextFormField(
      controller: _textEditingController,
    );

    var text = Text(_greeting);

    var body = Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          textFormField,
          text,
        ],
      ),
    );

    return Scaffold(
      appBar: appBar,
      body: body,
    );
  }
}

Line 13

final _textEditingController = TextEditingController();
  • TextEditingController:定義 TextFormField 的 controller,用來對 TextFormField 做 data binding

Line 14

var _greeting = '';
  • _greeting:定義 TextFormField 所綁定的變數,因為會被改變,所以使用 var 宣告

Line 16


void initState() {
  super.initState();
  _textEditingController.text = 'Hello World';
}
  • initState() 定義 TextFormField 的初始值

Line 21

_textEditingController.addListener(() {
  setState(() {
    _greeting = _textEditingController.text;
  });
});
  • TextFormField 被改變時,透過 TextEditController 去寫入 state
  • addEventListener() 相當於 onChange() event

Line 28


void dispose() {
  _textEditingController.dispose();
  super.dispose();
}
  • TextEditingController 需在最後的 dispose() 加以釋放

Line 38

var textFormField = TextFormField(
  controller: _textEditingController,
);
  • controller:將 TextEditingController 綁定到 TextFormField

Line 42

var text = Text(_greeting);
  • 直接將 state 綁定到 Text,當 state 改變,Text 會自動更新

Conclusion

  • 若想主動讀取 TextFormField 的值,透過 TextEditingController.text 即可讀取
  • 但若想實現 two way binding,則必須透過 state,因為 state 的改變才會觸發 Text 的改變,但 TextEditingController 又不能主動更改 state,必須另外透過 TextEditingControlleraddEventListener() 去更新 state
  • addEventListener() 可視為 onChange() event