✍️ Flutter 用户输入组件实战教程

📖 前言

用户输入是移动应用中的核心交互功能。Flutter 提供了强大的文本输入组件,支持多种输入类型、验证、格式化等功能。

image-20260121160607253


🎯 用户输入组件概览

Flutter 提供了以下用户输入组件:

组件名 功能说明 适用场景
TextField 单行文本输入 用户名、密码、搜索框
TextFormField 带验证的文本输入 表单输入、数据验证
FormField 通用表单字段 自定义表单字段
Form 表单容器 表单管理、统一验证

📝 TextField 组件

TextField 组件是 Flutter 中最常用的文本输入组件。

基础用法

// 最简单的输入框
TextField()

// 带提示文本
TextField(
  decoration: InputDecoration(
    hintText: '请输入用户名',
  ),
)

// 带标签
TextField(
  decoration: InputDecoration(
    labelText: '用户名',
  ),
)

// 带图标和装饰
TextField(
  decoration: InputDecoration(
    labelText: '用户名',
    hintText: '请输入用户名',
    prefixIcon: Icon(Icons.person),
    suffixIcon: Icon(Icons.clear),
    border: OutlineInputBorder(
      borderRadius: BorderRadius.circular(8),
    ),
  ),
)

image-20260121161101025

输入类型

// 文本输入(默认)
TextField(
  keyboardType: TextInputType.text,
)

// 数字输入
TextField(
  keyboardType: TextInputType.number,
)

// 电话号码输入
TextField(
  keyboardType: TextInputType.phone,
)

// 邮箱输入
TextField(
  keyboardType: TextInputType.emailAddress,
)

// 密码输入
TextField(
  obscureText: true,
  decoration: InputDecoration(
    labelText: '密码',
  ),
)

image-20260121161240853

输入控制

final TextEditingController _controller = TextEditingController();

TextField(
  controller: _controller,
  onChanged: (value) {
    print('输入内容:$value');
  },
  onSubmitted: (value) {
    print('提交内容:$value');
  },
)

image-20260121161340598


📋 TextFormField 组件

TextFormFieldTextField 的扩展,增加了表单验证功能。

基础用法

TextFormField(
  decoration: InputDecoration(
    labelText: '用户名',
  ),
  validator: (value) {
    if (value == null || value.isEmpty) {
      return '请输入用户名';
    }
    if (value.length < 3) {
      return '用户名至少3个字符';
    }
    return null;
  },
)

image-20260121161425938

表单验证

final _formKey = GlobalKey<FormState>();

Form(
  key: _formKey,
  child: Column(
    children: [
      TextFormField(
        decoration: InputDecoration(labelText: '用户名'),
        validator: (value) {
          if (value == null || value.isEmpty) {
            return '请输入用户名';
          }
          return null;
        },
      ),
      TextFormField(
        decoration: InputDecoration(labelText: '邮箱'),
        validator: (value) {
          if (value == null || value.isEmpty) {
            return '请输入邮箱';
          }
          if (!value.contains('@')) {
            return '请输入有效的邮箱地址';
          }
          return null;
        },
      ),
      ElevatedButton(
        onPressed: () {
          if (_formKey.currentState!.validate()) {
            // 表单验证通过
          }
        },
        child: Text('提交'),
      ),
    ],
  ),
)

image-20260121161454733


🎨 输入框装饰

边框样式

// 轮廓边框
TextField(
  decoration: InputDecoration(
    border: OutlineInputBorder(),
    labelText: '用户名',
  ),
)

// 下划线边框
TextField(
  decoration: InputDecoration(
    border: UnderlineInputBorder(),
    labelText: '用户名',
  ),
)

// 无边框
TextField(
  decoration: InputDecoration(
    border: InputBorder.none,
    labelText: '用户名',
  ),
)

image-20260121161635434

填充和边距

TextField(
  decoration: InputDecoration(
    labelText: '用户名',
    filled: true,
    fillColor: Colors.grey[100],
    contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
  ),
)

image-20260121161720704


💡 实际应用场景

场景1:登录表单

Form(
  key: _formKey,
  child: Column(
    children: [
      TextFormField(
        decoration: InputDecoration(
          labelText: '用户名',
          prefixIcon: Icon(Icons.person),
        ),
        validator: (value) {
          if (value == null || value.isEmpty) {
            return '请输入用户名';
          }
          return null;
        },
      ),
      SizedBox(height: 16),
      TextFormField(
        obscureText: true,
        decoration: InputDecoration(
          labelText: '密码',
          prefixIcon: Icon(Icons.lock),
        ),
        validator: (value) {
          if (value == null || value.isEmpty) {
            return '请输入密码';
          }
          return null;
        },
      ),
      SizedBox(height: 24),
      ElevatedButton(
        onPressed: () {
          if (_formKey.currentState!.validate()) {
            // 执行登录
          }
        },
        child: Text('登录'),
      ),
    ],
  ),
)

image-20260121161753013

场景2:搜索框

TextField(
  decoration: InputDecoration(
    hintText: '搜索',
    prefixIcon: Icon(Icons.search),
    suffixIcon: Icon(Icons.clear),
    border: OutlineInputBorder(
      borderRadius: BorderRadius.circular(24),
    ),
  ),
  onChanged: (value) {
    // 执行搜索
  },
)

image-20260121161817215

场景3:多行输入

TextField(
  maxLines: 5,
  decoration: InputDecoration(
    labelText: '备注',
    border: OutlineInputBorder(),
  ),
)

image-20260121161846960

场景4:实时搜索

class SearchField extends StatefulWidget {
  
  _SearchFieldState createState() => _SearchFieldState();
}

class _SearchFieldState extends State<SearchField> {
  final TextEditingController _controller = TextEditingController();
  String _searchText = '';

  
  void initState() {
    super.initState();
    _controller.addListener(() {
      setState(() {
        _searchText = _controller.text;
      });
      // 执行搜索
    });
  }

  
  Widget build(BuildContext context) {
    return TextField(
      controller: _controller,
      decoration: InputDecoration(
        hintText: '搜索',
        prefixIcon: Icon(Icons.search),
        suffixIcon: _searchText.isNotEmpty
            ? IconButton(
                icon: Icon(Icons.clear),
                onPressed: () {
                  _controller.clear();
                },
              )
            : null,
      ),
    );
  }
}

image-20260121161918750

场景5:输入验证和格式化

TextFormField(
  decoration: InputDecoration(labelText: '手机号'),
  keyboardType: TextInputType.phone,
  inputFormatters: [
    FilteringTextInputFormatter.digitsOnly,
    LengthLimitingTextInputFormatter(11),
  ],
  validator: (value) {
    if (value == null || value.isEmpty) {
      return '请输入手机号';
    }
    if (value.length != 11) {
      return '手机号格式不正确';
    }
    return null;
  },
)

image-20260121161958314


🔧 TextField 高级属性

输入限制

TextField(
  inputFormatters: [
    FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),  // 只允许数字
    LengthLimitingTextInputFormatter(10),  // 最大长度
  ],
)

image-20260121162032400

焦点控制

final FocusNode _focusNode = FocusNode();

TextField(
  focusNode: _focusNode,
  onSubmitted: (value) {
    _focusNode.unfocus();  // 失去焦点
  },
)

// 程序化控制焦点
_focusNode.requestFocus();  // 获取焦点
_focusNode.unfocus();       // 失去焦点

image-20260121162058442

文本选择

final TextEditingController _controller = TextEditingController();

// 选择所有文本
_controller.selection = TextSelection(
  baseOffset: 0,
  extentOffset: _controller.text.length,
);

// 选择部分文本
_controller.selection = TextSelection(
  baseOffset: 0,
  extentOffset: 5,
);

image-20260121162127957

输入监听

TextField(
  controller: _controller,
  onChanged: (value) {
    print('输入内容:$value');
  },
  onSubmitted: (value) {
    print('提交内容:$value');
  },
  onEditingComplete: () {
    print('编辑完成');
  },
)

image-20260121162152287


⚠️ 常见问题与解决方案

问题1:输入框无法获取焦点

解决方案

  • 检查是否有其他组件覆盖
  • 使用 FocusNode 手动控制焦点
  • 确保输入框在可见区域

问题2:键盘遮挡输入框

解决方案

Scaffold(
  resizeToAvoidBottomInset: true,  // 自动调整布局
  body: SingleChildScrollView(
    child: TextField(...),
  ),
)

问题3:输入验证不生效

解决方案

  • 确保使用 TextFormField 而不是 TextField
  • TextFormField 放在 Form 组件内
  • 调用 FormState.validate() 方法

问题4:输入框样式不统一

解决方案

  • 使用 InputDecorationTheme 统一设置样式
  • 创建统一的输入框组件
  • 使用主题系统管理样式

💼 最佳实践

1. 统一的输入框组件

class AppTextField extends StatelessWidget {
  final String label;
  final TextEditingController? controller;
  final String? Function(String?)? validator;
  
  const AppTextField({
    required this.label,
    this.controller,
    this.validator,
  });
  
  
  Widget build(BuildContext context) {
    return TextFormField(
      controller: controller,
      decoration: InputDecoration(
        labelText: label,
        border: OutlineInputBorder(),
      ),
      validator: validator,
    );
  }
}

2. 输入框状态管理

class InputState {
  final String value;
  final String? error;
  final bool isFocused;
  
  InputState({
    required this.value,
    this.error,
    this.isFocused = false,
  });
}

📚 总结

通过本教程,我们学习了:

  1. TextField 组件的基础用法和输入类型
  2. TextFormField 组件的表单验证功能
  3. ✅ 输入框装饰和样式定制
  4. ✅ 实际应用场景和最佳实践

用户输入组件是 Flutter 应用中的核心交互组件,掌握好这些组件的用法,能够让你的应用表单更加完善和用户友好!


🔗 相关资源

Happy Coding! 🎨✨
equired this.value,
this.error,
this.isFocused = false,
});
}


---

## 📚 总结

通过本教程,我们学习了:

1. ✅ `TextField` 组件的基础用法和输入类型
2. ✅ `TextFormField` 组件的表单验证功能
3. ✅ 输入框装饰和样式定制
4. ✅ 实际应用场景和最佳实践

用户输入组件是 Flutter 应用中的核心交互组件,掌握好这些组件的用法,能够让你的应用表单更加完善和用户友好!

---

## 🔗 相关资源

- [Flutter TextField 官方文档](https://api.flutter.dev/flutter/material/TextField-class.html)
- [TextFormField 官方文档](https://api.flutter.dev/flutter/material/TextFormField-class.html)
- [Form 官方文档](https://api.flutter.dev/flutter/widgets/Form-class.html)
- [欢迎加入开源鸿蒙跨平台社区](https://openharmonycrossplatform.csdn.net/)

Happy Coding! 🎨✨
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐