我稍微修改了SteveM的答案以修复当小部件未正确扩展时的错误。在计算小部件宽度时,我们应该考虑这两个小事情:
TextField
会合并给定的textStyle
参数和当前主题的TextStyle
。在自定义小部件中也必须这样做:
final ThemeData themeData = Theme.of(context);
final TextStyle style = themeData.textTheme.subtitle1.merge(textStyle);
TextField
的cursorWidth
必须计入小部件的宽度计算中。由于无法从TextField
类中获取默认光标宽度,因此我检查了其代码并在FitsTextField
类中添加了一个新常量。不要忘记将其传递给TextField
的构造函数:
final textWidth = max(widget.minWidth, tp.width + _CURSOR_WIDTH);
child: TextField(
cursorWidth: _CURSOR_WIDTH,
完整代码:
import 'dart:math';
import 'package:flutter/material.dart';
class FitTextField extends StatefulWidget {
final String initialValue;
final double minWidth;
const FitTextField({
Key key,
this.initialValue,
this.minWidth: 30,
}) : super(key: key);
@override
State<StatefulWidget> createState() => new FitTextFieldState();
}
class FitTextFieldState extends State<FitTextField> {
static const _CURSOR_WIDTH = 2.0;
TextEditingController txt = TextEditingController();
TextStyle textStyle = TextStyle(
color: Colors.grey[600],
fontSize: 16,
);
initState() {
super.initState();
txt.text = widget.initialValue;
}
@override
Widget build(BuildContext context) {
final ThemeData themeData = Theme.of(context);
final TextStyle style = themeData.textTheme.subtitle1.merge(textStyle);
TextSpan ts = new TextSpan(style: style, text: txt.text);
TextPainter tp = new TextPainter(
text: ts,
textDirection: TextDirection.ltr,
);
tp.layout();
final textWidth = max(widget.minWidth, tp.width + _CURSOR_WIDTH);
return Container(
width: textWidth,
child: TextField(
cursorWidth: _CURSOR_WIDTH,
style: style,
controller: txt,
onChanged: (text) {
setState(() {});
},
),
);
}
}