import 'package:flutter/material.dart'; import 'package:location/utils/common_expand.dart'; class NewsRepostTextView extends StatefulWidget { final String? initialValue; // 初始值 final String hintText; // 提示文本 final TextEditingController controller; final ValueChanged? onChanged; // 文本变化回调 final VoidCallback? onSubmitted; // 提交回调 final int minLength; // 最小字数 final int maxLength; // 最大字数 const NewsRepostTextView({ Key? key, this.initialValue, required this.controller, this.hintText = '请输入举报原因,确保您提交的信息真实、客观,且符合中华人民共和国相关法律法规。我们将由专门的审核团队对您提供的内容进行核查并第一时间处理。', this.onChanged, this.onSubmitted, this.minLength = 3, this.maxLength = 500, }) : super(key: key); @override _NewsRepostTextViewState createState() => _NewsRepostTextViewState(); } class _NewsRepostTextViewState extends State { late TextEditingController _controller; late FocusNode _focusNode; bool _isValid = true; // 当前输入是否有效 int _currentLength = 0; // 当前字数 @override void initState() { super.initState(); _controller = widget.controller;//TextEditingController(text: widget.initialValue); _focusNode = FocusNode(); _currentLength = widget.initialValue?.length ?? 0; _validateText(); // 监听文本变化 _controller.addListener(() { setState(() { _currentLength = _controller.text.length; _validateText(); widget.onChanged?.call(_controller.text); }); }); } @override void dispose() { _controller.dispose(); _focusNode.dispose(); super.dispose(); } // 验证文本长度 void _validateText() { final text = _controller.text; _isValid = text.length >= widget.minLength && text.length <= widget.maxLength; } // 获取当前文本状态的提示信息 String get _lengthStatusText { if (_currentLength < widget.minLength) { return '至少输入${widget.minLength}个字'; } else if (_currentLength >= widget.maxLength) { return '已超出最大字数限制'; } else { return '${_currentLength}/${widget.maxLength}'; } } // 获取当前文本状态的颜色 Color get _lengthStatusColor { if (_currentLength < widget.minLength || _currentLength > widget.maxLength) { return Colors.red; } else { return Colors.grey; } } @override Widget build(BuildContext context) { return GestureDetector( onTap: () { // 点击时收起键盘 FocusScopeNode currentFocus = FocusScope.of(context); if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) { FocusManager.instance.primaryFocus?.unfocus(); } }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ TextField( controller: _controller, focusNode: _focusNode, maxLines: null, // 允许多行输入 minLines: 4, // 最小显示行数 maxLength: widget.maxLength, // 最大字数限制(UI层限制) keyboardType: TextInputType.multiline, decoration: InputDecoration( hintText: widget.hintText, hintStyle: TextStyle( color: Colors.grey ), border: OutlineInputBorder( borderSide: BorderSide( color: "#12C2C2C2".color, width: 1.0, ), ), enabledBorder: OutlineInputBorder( borderSide: BorderSide( color: "#12C2C2C2".color, width: 1.0, ), ), focusedBorder: OutlineInputBorder( borderSide: BorderSide( color: _isValid ? "#12C2C2C2".color : Colors.red, width: 2.0, ), borderRadius: BorderRadius.all(Radius.circular(10)) ), counterText: '', // 隐藏默认计数器 ), onSubmitted: (_) => widget.onSubmitted?.call(), ), SizedBox(height: 8.0), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( _lengthStatusText, style: TextStyle(color: _lengthStatusColor), ), if (!_isValid) Text( '字数不符合要求', style: TextStyle(color: Colors.red), ), ], ), ], ), ); } }