Files
2026-09-04 15:22:20 +08:00

3.7 KiB
Raw Permalink Blame History

【Demo】TextField 输入框(登录表单)

源文件:lib/pages/demo/input_demo.dart | 分类:基础布局 一句话:输入框 + 密码"小眼睛"切换 —— 表单最基础的零件。


一、这个 Demo 解决什么问题

做一个最简单的登录表单:手机号输入框 + 密码输入框(可切换明文/密文)。 核心是搞懂 TextEditingController 的用法——Flutter 里输入框不叫"双向绑定", 而是"控制器持有值,代码里随时读写"。


二、怎么运行 / 演示内容

runApp(const MaterialApp(home: InputDemoPage()));
  • 手机号框:弹数字键盘(keyboardType: TextInputType.phone);
  • 密码框:右侧眼睛图标切换密文/明文;
  • 点"登录":控制台打印两个输入框的内容。

三、核心知识点(新手向)

1. 对照 Vue 的 v-model

Vue Flutter
v-model="phone" TextEditingController + controller.text
框架自动同步 手动 controller.text 读写

Flutter 没有隐式的双向绑定:controller.text 改了就同步到输入框, 输入框内容变了 controller.text 也会读到 —— 但没有"响应式": 想根据输入内容实时刷新 UI(如"输入满 11 位才能点登录"),要自己 addListener 或 setState。

2. TextEditingController 生命周期(红线)

final TextEditingController _userCtrl = TextEditingController();

@override
void dispose() {
  _userCtrl.dispose(); // 必须在 dispose 释放,防内存泄漏
  super.dispose();
}

凡是用 Controller 命名的东西(Text/Scroll/Animation/Tab),基本都要 dispose。

3. 密码眼睛切换

bool _showPwd = false;

TextField(
  controller: _pwdCtrl,
  obscureText: !_showPwd, // 密文/明文由状态决定
  decoration: InputDecoration(
    labelText: "密码",
    prefixIcon: const Icon(Icons.lock),
    border: const OutlineInputBorder(),
    suffixIcon: IconButton(
      icon: Icon(_showPwd ? Icons.visibility : Icons.visibility_off),
      onPressed: () => setState(() => _showPwd = !_showPwd),
    ),
  ),
)

4. InputDecoration 常用参数

  • labelText:浮动标签(聚焦时缩小浮到边框上);
  • hintText:灰色占位提示;
  • prefixIcon:左侧图标;suffixIcon:右侧(按钮/图标);
  • border: OutlineInputBorder():带边框的圆角样式(默认是下划线)。

四、关键代码剖析

// 读取输入内容(点登录时)
String user = _userCtrl.text;
String pwd = _pwdCtrl.text;
if (kDebugMode) {
  print("账号:$user,密码:$pwd"); // kDebugMode:只在 debug 包打印
}

要点:

  • kDebugMode(来自 package:flutter/foundation.dart)保证打印不会出现在 release 包;
  • 真实项目里读取后要走校验(见 form_demo.md)和登录接口(见 dio_demo.md)。

五、踩坑记录

  1. Scaffold 没有 padding 参数! 外间距要写在 body 的 Padding 上(新手必踩)。
  2. controller 忘了 dispose → 内存泄漏(Flutter 分析器会提示)。
  3. suffixIcon 用 IconButton 而不要用普通 Icon 包 GestureDetector —— IconButton 自带点击区域和涟漪反馈。
  4. 想"输入即校验"别自己写监听,直接上 Form(见 form_demo)。

六、扩展思考

  • 进阶校验:TextFormField + validator(form_demo.md)—— 本项目表单校验全家桶;
  • 真实登录页还要:防重复提交、加载动画、错误提示、密码安全存储(本项目用 flutter_secure_storage,见架构文档存储层);
  • 输入法控制:textInputAction: TextInputAction.next 让回车键变成"下一项",最后一项变"完成"。