Flutter -如何实现多行带下划线的TextField

svujldwt  于 2023-05-23  发布在  Flutter
关注(0)|答案(3)|浏览(239)

我想实现以下UI,其中包含一个多行TextField,每一行下面都有下划线。有什么办法可以实现吗

Expanded(
child: Padding(
    padding: const EdgeInsets.symmetric(horizontal: 5.0),
    child: TextField(
        controller: problemItem.titleController,
        decoration: const InputDecoration(
                                border: InputBorder.none),
        keyboardType: TextInputType.multiline,
        minLines: 3,
        maxLines: 100,
        )
    ),
),
bqf10yzr

bqf10yzr1#

您可以使用StackTextField堆叠到行上。您需要将TextFieldexpands属性设置为true,以便使其从一开始就扩展到完整的三行宽度。
我实现了一个类似于您正在尝试创建的TextField

Stack(
  children: [
    for (int i = 0; i < 3; i++)
      Container(
        width: double.infinity,
        margin: EdgeInsets.only(
          top: 4 + (i + 1) * 28,
          left: 15,
          right: 15,
        ),
        height: 1,
        color: Colors.black,
      ),
    const SizedBox(
      height: 97,
      child: Padding(
        padding: EdgeInsets.symmetric(horizontal: 15),
        child: TextField(
          decoration: InputDecoration(border: InputBorder.none),
          cursorHeight: 22,
          style: TextStyle(
            fontSize: 20.0,
          ),
          keyboardType: TextInputType.multiline,
          expands: true,
          maxLines: null,
        ),
      ),
    ),
  ],
),

结果:

mzmfm0qo

mzmfm0qo2#

这只是一个简单的例子,说明了当文本为一般情况更改时如何生成下划线。如果下划线位置不在您想要的位置,屏幕上的输出行为仍然需要调整。

查看heigh属性的更多信息

如果要分配固定行文本域,可以尝试以下小部件:
style是必需的,因为它使用fontSize & height来计算行号
controller用于监视文本更改
initState中的textPainter模拟文本的文本行为,并计算将要显示的文本行数。

class UnderlineTextField extends StatefulWidget {
  const UnderlineTextField({
    required this.style,
    this.controller,
    this.maxLines = 3,
    Key? key,
  }) : super(key: key);

  final TextEditingController? controller;
  final int? maxLines;
  final TextStyle style;

  @override
  State<UnderlineTextField> createState() => _UnderlineTextFieldState();
}

class _UnderlineTextFieldState extends State<UnderlineTextField> {
  double maxWidth = 0;
  int numberOfLines = 1;

  @override
  void initState() {
    /// Calculate numberOfLines
    widget.controller?.addListener(() {
      final text = widget.controller?.text ?? '';
      final textPainter = TextPainter(
        text: TextSpan(text: text, style: widget.style),
        maxLines: widget.maxLines,
        textDirection: TextDirection.ltr,
      );

      textPainter.layout(maxWidth: maxWidth);
      setState(() {
        numberOfLines = textPainter.computeLineMetrics().length;
      });
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final fontSize = widget.style.fontSize ?? 12;
    final textHeight = fontSize * (widget.style.height ?? 1);

    return LayoutBuilder(
      builder: (_, constrinat) {
        maxWidth = constrinat.maxWidth;
        return Stack(
          children: [
            TextField(
              style: widget.style,
              controller: widget.controller,
              decoration: const InputDecoration(
                isDense: true,
                border: InputBorder.none,
              ),
              maxLines: widget.maxLines,
            ),
            Positioned.fill(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: List.generate(
                  numberOfLines,
                  (index) => Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      SizedBox(height: textHeight - 1),
                      const Divider(height: 1, thickness: 1),
                    ],
                  ),
                ),
              ),
            ),
          ],
        );
      },
    );
  }
}
yvgpqqbh

yvgpqqbh3#

Stack(
          children: [
            for (int i = 0; i < 4; i++)
              Container(
                margin: EdgeInsets.only(
                  top: 4 + (i + 1) * 28,
                  left: 15,
                  right: 15,
                ),
                height: 2,
                color: Colors.black,
              ),
            const Padding(
              padding: EdgeInsets.symmetric(horizontal: 15),
              child: TextField(
                decoration: InputDecoration(border: InputBorder.none),
                style: TextStyle(
                  fontSize: 20.0,
                ),
                keyboardType: TextInputType.multiline,
                expands: true,
                maxLines: null,
              ),
            ),
          ],
        ),

相关问题