TextEditingController中的text是如何被监听的

  1. TextEditingController可以在任何widget中使用
  2. 监听器什么时候触发
  3. TextEditingController的text的变化
    1. 自动获取(输入组件)
    2. 手动设置(非输入组件)

TextEditingController可以在任何widget中使用

Flutter 中的 TextEditingController 可以在任何 Widget 里使用,前提是你自己正确地创建和销毁它。

TextEditingController 是一个独立的控制器对象,用来管理 EditableText/ TextField / TextFormField 的输入内容。

  • TextField 是一个独立的输入框,不会参与 Form 的统一管理。
  • **TextFormField**是FormField<String> 的一个封装,专门用于文本输入,参与 Form 的统一管理,支持 validator / onSaved / reset()
  • EditableText其实是 TextField 的底层实现类TextField 内部就是包了一层 EditableText)。

它不是依赖某个特定 Widget 的内置东西,而是你自己创建的一个 Dart 类实例。所以理论上StatelessWidgetStatefulWidgetGetxControllerProvider,甚至 main() 里都可以创建和使用它。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(home: CounterPage());
  }
}

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

  @override
  State<CounterPage> createState() => _CounterPageState();
}

class _CounterPageState extends State<CounterPage> {
  // 创建 TextEditingController,但不用在任何 TextField 里
  final TextEditingController _controller = TextEditingController(text: "0");

  @override
  void initState() {
    super.initState();

    // 监听内容变化
    _controller.addListener(() {
      debugPrint("文本内容改变为: ${_controller.text}");
    });
  }

  @override
  void dispose() {
    _controller.dispose(); // 记得释放资源
    super.dispose();
  }

  void _increment() {
    // 手动修改 controller 中的文本
    final current = int.tryParse(_controller.text) ?? 0;
    _controller.text = (current + 1).toString();
    setState(() {}); // 触发重建显示新值
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Controller 计数器')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              '当前值:${_controller.text}', // 从 controller 读取内容显示
              style: const TextStyle(fontSize: 24),
            ),
            const SizedBox(height: 20),
            ElevatedButton(onPressed: _increment, child: const Text('增加')),
          ],
        ),
      ),
    );
  }
}
I/flutter (17703): 文本内容改变为: 1
I/flutter (17703): 文本内容改变为: 2
I/flutter (17703): 文本内容改变为: 3
I/flutter (17703): 文本内容改变为: 4

监听器什么时候触发

  • 只有当 controller.text 发生变化时,这个监听才会被触发。

  • 换句话说:

    _controller.addListener(() {
      print(_controller.text);
    });
    

    表示_controller 内部的值(即 text)发生变化时,就执行这个回调函数

TextEditingController的text的变化

TextEditingController 本身只是一个文本状态容器,它并不会自己去“生成”文字,文字必须来自两种途径:①主动赋值(代码里设置);②用户在输入控件中输入(例如 EditableText/TextField / TextFormField 绑定了这个 controller)

自动获取(输入组件)

只要把 TextEditingController 传给输入类组件的 controller 属性:

  • 输入类组件包括:EditableText / TextField / TextFormField

  • 用户在界面中输入 → 会自动更新 controller.text

  • 每次 text 被更新时都会 notifyListeners() → 触发你用 addListener() 注册的回调

import 'package:flutter/material.dart';

void main() {
  runApp(const MaterialApp(home: MyEditableDemo()));
}

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

  @override
  State<MyEditableDemo> createState() => _MyEditableDemoState();
}

class _MyEditableDemoState extends State<MyEditableDemo> {
  final _controller = TextEditingController();

  @override
  void initState() {
    super.initState();
    // 监听内容变化
    _controller.addListener(() {
      print('当前输入内容:${_controller.text}');
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("EditableText Demo")),
      body: Center(
        child: Container(
          // 用 Container 包裹,方便设置边框和内边距
          padding: const EdgeInsets.all(8),
          width: 250,
          // 设置边框
          decoration: BoxDecoration(
            // 灰色边框,圆角
            border: Border.all(color: Colors.grey),
            borderRadius: BorderRadius.circular(8),
          ),
          child: EditableText(
            // controller 管理输入内容
            controller: _controller,
            focusNode: FocusNode(),
            // 设置文本样式
            style: const TextStyle(color: Colors.black, fontSize: 20),
            // 设置光标颜色
            cursorColor: Colors.blue,
            // 设置背景光标颜色
            backgroundCursorColor: Colors.grey,
          ),
        ),
      ),
    );
  }
}
// 日志
I/flutter (18118): 当前输入内容:f
I/flutter (18118): 当前输入内容:ff
I/flutter (18118): 当前输入内容:fff
I/flutter (18118): 当前输入内容:ffff
I/flutter (18118): 当前输入内容:fffff
I/flutter (18118): 当前输入内容:ffffff
I/flutter (18118): 当前输入内容:fffffff

手动设置(非输入组件)

当我们绑定的是非输入类组件时(如 ElevatedButton、Text 等)时,它们本身不会改变 controller.text,所以:

  • 用户点击按钮或显示文本时,不会触发 addListener()
  • 如果想要触发监听器,需要你在事件里手动给 controller.text 赋值
  void _increment() {
    // 手动修改 controller 中的文本
    final current = int.tryParse(_controller.text) ?? 0;
    _controller.text = (current + 1).toString();
    setState(() {}); // 触发重建显示新值
  }

// 用户需要配合onPressed函数,给TextEditingController的text赋值
ElevatedButton(onPressed: _increment, child: const Text('增加')),

// _controller.text  变化之后,才会触发监听器
_controller.addListener(() {
  debugPrint("文本内容改变为: ${_controller.text}");
});

也就是说,这类组件 必须「手动更新 controller」,监听器才会被调用。

×

喜欢就点赞,疼爱就打赏