| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- 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<String>? 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<NewsRepostTextView> {
- 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),
- ),
- ],
- ),
- ],
- ),
- );
- }
- }
|