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

Flutter TextField设置maxLines为2后,实现回车行替换及滚动效果

实现自定义滚动的双行TextField(回车自动上移内容)

要实现固定显示两行文本、按下回车键时自动将第二行内容上移到第一行并丢弃原第一行,同时支持滚动的效果,需要手动控制文本内容和滚动行为,默认TextField无法直接满足该需求。以下是完整实现方案:

完整代码

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 20),
            child: CustomTwoLineTextField(),
          ),
        ),
      ),
    );
  }
}

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

  @override
  State<CustomTwoLineTextField> createState() => _CustomTwoLineTextFieldState();
}

class _CustomTwoLineTextFieldState extends State<CustomTwoLineTextField> {
  final TextEditingController _textController = TextEditingController();
  final ScrollController _scrollController = ScrollController();

  @override
  void dispose() {
    _textController.dispose();
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: _textController,
      scrollController: _scrollController,
      maxLines: null,
      decoration: const InputDecoration(
        border: OutlineInputBorder(),
        hintText: '输入内容,按回车换行上移',
      ),
      style: const TextStyle(fontSize: 16, height: 1.5),
      onKeyEvent: (node, event) {
        if (event.logicalKey == LogicalKeyboardKey.enter && event is KeyDownEvent) {
          _handleEnterKey();
          return KeyEventResult.handled;
        }
        return KeyEventResult.ignored;
      },
    );
  }

  void _handleEnterKey() {
    final currentText = _textController.text;
    final lines = currentText.split('\n');

    String newText;
    if (lines.length >= 2) {
      newText = '${lines[1]}\n';
    } else {
      newText = '\n';
    }

    _textController.text = newText;
    _textController.selection = TextSelection.fromPosition(
      TextPosition(offset: newText.length),
    );

    WidgetsBinding.instance.addPostFrameCallback((_) {
      _scrollController.jumpTo(_scrollController.position.maxScrollExtent);
    });
  }
}

关键实现说明

  • 控制器管理:使用TextEditingController控制文本内容,ScrollController控制滚动位置,确保组件销毁时正确释放资源。
  • 多行输入与固定显示:设置maxLines: null允许无限多行输入,通过字体大小和行高(style中的height参数)控制输入框默认显示两行,超出内容自动触发滚动。
  • 回车事件处理:通过onKeyEvent捕获回车键按下动作,阻止默认换行行为,手动实现文本行上移逻辑:
    • 拆分当前文本为行列表,若已有两行及以上,将第二行内容作为新的第一行,保留换行符让光标停在第二行
    • 若只有一行或空文本,直接添加换行符定位光标到第二行
  • 自动滚动:更新文本后通过addPostFrameCallback触发滚动,确保输入区域始终可见。

你可以根据需求调整字体大小、行高或在外层包裹SizedBox来精确控制输入框的高度,匹配UI设计。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 01:17:36