import 'package:flutter/material.dart'; import 'package:patbond_flutter/core/theme/app_theme.dart'; /// 表单输入框封装(设计规范 §2.2 / §4.1)。 /// /// 密码模式([obscurable] 为 true)内置可见性切换按钮,点击目标 ≥44×44。 /// 提交中禁用时整体 60% 不透明度。 class AppTextField extends StatefulWidget { const AppTextField({ required this.label, super.key, this.controller, this.prefixIcon, this.errorText, this.helperText, this.enabled = true, this.obscurable = false, this.keyboardType, this.textInputAction, this.autofillHints, this.onChanged, this.onSubmitted, }); final String label; final TextEditingController? controller; final IconData? prefixIcon; final String? errorText; final String? helperText; final bool enabled; /// 是否为密码模式:默认遮蔽输入,并显示可见性切换按钮。 final bool obscurable; final TextInputType? keyboardType; final TextInputAction? textInputAction; final Iterable? autofillHints; final ValueChanged? onChanged; final ValueChanged? onSubmitted; @override State createState() => _AppTextFieldState(); } class _AppTextFieldState extends State { bool obscured = true; @override Widget build(BuildContext context) { return Opacity( opacity: widget.enabled ? 1 : 0.6, child: TextFormField( controller: widget.controller, enabled: widget.enabled, obscureText: widget.obscurable && obscured, keyboardType: widget.keyboardType, textInputAction: widget.textInputAction, autofillHints: widget.autofillHints, onChanged: widget.onChanged, onFieldSubmitted: widget.onSubmitted, decoration: InputDecoration( labelText: widget.label, errorText: widget.errorText, helperText: widget.helperText, prefixIcon: widget.prefixIcon == null ? null : Icon(widget.prefixIcon, color: AppColors.muted), suffixIcon: widget.obscurable ? IconButton( tooltip: obscured ? '显示密码' : '隐藏密码', constraints: const BoxConstraints( minWidth: 44, minHeight: 44, ), onPressed: widget.enabled ? () => setState(() => obscured = !obscured) : null, icon: Icon( obscured ? Icons.visibility_off : Icons.visibility, color: AppColors.muted, ), ) : null, ), ), ); } }