5

I want to implement the following Ui which contains a multiline TextField with underline below every single line. any idea on how I can implement this?

enter image description here

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, ) ), ), 

3 Answers 3

4
+25

You can use a Stack to stack the TextField onto lines. You need to set the expands attribute of the TextField to true in order to make it expand to the full three-line width right from the start.
I implemented a similar TextField to the one you are trying to create:

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, ), ), ), ], ), 

Result:
enter image description here

Sign up to request clarification or add additional context in comments.

Comments

1
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, ), ), ], ), 

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
1

It is just a simple example of how to generate an underline when text change for a general case. The output behavior on the screen still needs to be tuned if the underline position is not on the place you want.

Check more on heigh property

enter image description here

If you want to allocate a Fixed Lines Textfield, you can try the below widget:

style is required because it uses the fontSize & height to calculate the line number

controller use to monitor the text changed

textPainter in the initState simulates the text behavior of the text and calculates the lines of text that will be shown.

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), ], ), ), ), ), ], ); }, ); } } 

2 Comments

I would love some more explanation on this and maybe a full example of the UnderLineTextField widget
The original answer is posted a long time ago. I updated it and simplify the widget.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.