import 'package:flutter/material.dart'; import 'package:together_mobile/common/constants.dart'; class SignTextField extends StatefulWidget { const SignTextField({ super.key, this.color = kPrimaryColor, this.obscureText = false, required this.type, required this.labelText, required this.controller, required this.isError, }); final Color color; final bool obscureText; final String type; final String labelText; final TextEditingController controller; final void Function(String, bool) isError; @override State createState() => _SignTextFieldState(); } class _SignTextFieldState extends State { int _length = 0; String? _errorText; @override Widget build(BuildContext context) { return TextField( onChanged: (String newValue) { setState(() { _length = newValue.characters.length; }); setErrorText(); widget.isError( widget.type, (_errorText == null && widget.controller.text.isEmpty) || _errorText != null); }, controller: widget.controller, obscureText: widget.obscureText, cursorColor: widget.color, textAlignVertical: TextAlignVertical.bottom, keyboardType: initTextInputType(), decoration: InputDecoration( errorText: _errorText, labelText: widget.labelText, counterText: '$_length 字符', floatingLabelStyle: TextStyle(color: widget.color), focusedBorder: UnderlineInputBorder( borderSide: BorderSide(color: widget.color), ), ), ); } TextInputType initTextInputType() { switch (widget.type) { case 'email': return TextInputType.emailAddress; case 'code': return TextInputType.number; case _: return TextInputType.visiblePassword; } } void setErrorText() { if (widget.controller.text.isEmpty) { setState(() { _errorText = null; }); } switch (widget.type) { case 'username': if (widget.controller.text.contains(RegExp(r'\W+'))) { setState(() { _errorText = '用户名只允许字母, 数字和下划线'; }); } else if (_length < 5 || _length > 20) { setState(() { _errorText = '用户名需为8-20个字符'; }); } else { setState(() { _errorText = null; }); } break; case 'password' || 'password1' || 'password2': if (widget.controller.text.contains(RegExp(r'\s'))) { setState(() { _errorText = '密码不能包含空格'; }); } else if (_length < 8 || _length > 30) { setState(() { _errorText = '密码需为8-30个字符'; }); } else { setState(() { _errorText = null; }); } break; case 'email': var exp = RegExp( r'^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$'); if (!exp.hasMatch(widget.controller.text)) { setState(() { _errorText = '邮箱格式错误'; }); } else { setState(() { _errorText = null; }); } case 'code': if (!RegExp(r'\d{6}').hasMatch(widget.controller.text)) { setState(() { _errorText = '6为数字'; }); } else if (widget.controller.text.characters.length != 6) { _errorText = '6位数字'; } else { setState(() { _errorText = null; }); } } } } TextField textField({ Color color = kPrimaryColor, bool obscureText = false, required String labelText, required TextEditingController controller, }) { return TextField( controller: controller, obscureText: obscureText, cursorColor: kSecondaryColor, textAlignVertical: TextAlignVertical.bottom, decoration: InputDecoration( helperText: '5-10位', errorText: 'xxx', labelText: labelText, floatingLabelStyle: const TextStyle(color: kSecondaryColor), focusedBorder: UnderlineInputBorder(borderSide: BorderSide(color: color))), ); } ElevatedButton elevatedButton( {required VoidCallback onPressed, required String text, Color? color = kPrimaryColor}) { return ElevatedButton( onPressed: onPressed, style: ElevatedButton.styleFrom( backgroundColor: color, elevation: 0, fixedSize: const Size(150, 20), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12))), child: Text( text, style: const TextStyle(fontSize: 20.0, letterSpacing: 10), ), ); }