这只是一个简单的示例,演示了如何在一般情况下在文本更改时生成下划线。如果下划线位置不在您想要的位置,则仍需要调整屏幕上的输出行为。
查看更多关于高度属性的信息
如果您想分配一个固定行数的文本框,可以尝试下面的小部件:
由于需要使用fontSize和height来计算行数,因此需要
style
。
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() {
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),
],
),
),
),
),
],
);
},
);
}
}