You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter实现YouTube式TextFormField后缀组件位置方案问询

实现YouTube风格评论框后缀图标效果

针对你遇到的问题,这里提供两种可行的解决方案:

方案一:Stack+TextField手动控制图标位置

直接用Stack将TextField和图标组件叠加,通过初始偏移量控制图标位置,同时监听文本输入的行数变化,动态调整图标的垂直偏移,避免maxLines导致的图标居中问题。

class CommentTextField extends StatefulWidget {
  const CommentTextField({super.key});

  @override
  State<CommentTextField> createState() => _CommentTextFieldState();
}

class _CommentTextFieldState extends State<CommentTextField> {
  final TextEditingController _controller = TextEditingController();
  double _iconTopOffset = 12; // 初始偏移量,对应输入框内边距

  @override
  void initState() {
    super.initState();
    _controller.addListener(_updateIconPosition);
  }

  void _updateIconPosition() {
    final text = _controller.text;
    final lineCount = text.split('\n').length;
    // 根据行数计算偏移,可根据实际字体大小调整每行高度
    setState(() {
      _iconTopOffset = lineCount > 1 ? 12 + (lineCount - 1) * 20 : 12;
      // 限制最大偏移,对应maxLines=3的上限
      if (_iconTopOffset > 12 + 2 * 20) {
        _iconTopOffset = 12 + 2 * 20;
      }
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        TextField(
          controller: _controller,
          maxLines: 3,
          decoration: const InputDecoration(
            hintText: "添加评论...",
            contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
            border: OutlineInputBorder(
              borderRadius: BorderRadius.all(Radius.circular(24)),
            ),
          ),
        ),
        Positioned(
          right: 16,
          top: _iconTopOffset,
          child: IconButton(
            icon: const Icon(Icons.send),
            onPressed: () {},
          ),
        ),
      ],
    );
  }
}

方案二:自定义InputDecoration的suffix,结合IntrinsicHeight

用IntrinsicHeight约束输入框的实际高度,避免maxLines强制拉长组件,同时通过Align让图标始终对齐顶部,配合文本行数动态调整高度因子。

class CommentTextField extends StatefulWidget {
  const CommentTextField({super.key});

  @override
  State<CommentTextField> createState() => _CommentTextFieldState();
}

class _CommentTextFieldState extends State<CommentTextField> {
  final TextEditingController _controller = TextEditingController();
  int _lineCount = 1;

  @override
  void initState() {
    super.initState();
    _controller.addListener(_updateLineCount);
  }

  void _updateLineCount() {
    final text = _controller.text;
    setState(() {
      _lineCount = text.split('\n').length;
      if (_lineCount > 3) _lineCount = 3;
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return IntrinsicHeight(
      child: TextField(
        controller: _controller,
        maxLines: 3,
        decoration: InputDecoration(
          hintText: "添加评论...",
          contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
          border: const OutlineInputBorder(
            borderRadius: BorderRadius.all(Radius.circular(24)),
          ),
          suffix: Align(
            alignment: Alignment.topRight,
            heightFactor: _lineCount > 1 ? _lineCount : 1,
            child: IconButton(
              padding: EdgeInsets.zero,
              icon: const Icon(Icons.send),
              onPressed: () {},
            ),
          ),
        ),
      ),
    );
  }
}

方案一灵活性更高,能精准控制图标位置;方案二更贴合TextField原生装饰体系,代码更简洁,可根据实际需求选择适配。

内容的提问来源于stack exchange,提问作者dontknowhy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 13:25:15