Flutter TextField 宽度应与包含文本的宽度匹配
Flutter TextField width should match width of contained text
在 flutter 中,TextField 没有固有宽度;它只知道如何将自己的大小调整到其父容器的整个宽度。如何将宽度设置为包含文本的宽度。
我尝试将 TextField 放入容器中
如此处所述
new Container(
width: 100.0,
child: new TextField()
)
我希望 TextField 的宽度与其包含的文本的宽度相匹配。 TextField 应随着文本的键入而变宽,并随着文本的删除而变窄。
我能够通过使用 TextPainter
来计算所需的文本宽度来实现预期的结果。然后我将该宽度用作包含 TextField
.
的 Container
的宽度
记得在您的 TextFields onChanged
方法中调用 setState()
。这会告诉小部件重新绘制自身,从而导致 TextField 调整到其内容的新宽度。
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>{
TextEditingController txt = TextEditingController();
// We will use this text style for the TextPainter used to calculate the width
// and for the TextField so that we calculate the correct size for the text
// we are actually displaying
TextStyle textStyle = TextStyle(color: Colors.grey[600]);
initState() {
super.initState();
// Set the text in the TextField to our initialValue
txt.text = widget.initialValue;
}
@override
Widget build(BuildContext context) {
// Use TextPainter to calculate the width of our text
TextSpan ts = new TextSpan(style: textStyle, text: txt.text);
TextPainter tp = new TextPainter(text: ts, textDirection: TextDirection.ltr);
tp.layout();
var textWidth = tp.width; // We will use this width for the container wrapping our TextField
// Enforce a minimum width
if ( textWidth < widget.minWidth ) {
textWidth = widget.minWidth;
}
return Container(
width: textWidth,
child: TextField(
style: textStyle,
controller: txt,
onChanged: (text) {
// Tells the framework to redraw the widget
// The widget will redraw with a new width
setState(() {});
},
),
);
}
}
我稍微修改了 SteveM 的回答以修复小部件未正确扩展时的错误。我们在计算小部件的宽度时应该尊重这两个小东西:
TextField
合并给定 textStyle
参数和当前主题的 TextStyle
。这也必须在自定义小部件中完成:
final ThemeData themeData = Theme.of(context);
final TextStyle style = themeData.textTheme.subtitle1.merge(textStyle);
TextField
的 cursorWidth
必须考虑到小部件的宽度计算中。由于无法从 TextField
class 获取默认光标宽度,我检查了它的代码并向 FitsTextField
class 添加了一个新常量。不要忘记将它传递给 TextField
的构造函数:
final textWidth = max(widget.minWidth, tp.width + _CURSOR_WIDTH);
// When building a TextField:
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> {
// 2.0 is the default from TextField class
static const _CURSOR_WIDTH = 2.0;
TextEditingController txt = TextEditingController();
// We will use this text style for the TextPainter used to calculate the width
// and for the TextField so that we calculate the correct size for the text
// we are actually displaying
TextStyle textStyle = TextStyle(
color: Colors.grey[600],
fontSize: 16,
);
initState() {
super.initState();
// Set the text in the TextField to our initialValue
txt.text = widget.initialValue;
}
@override
Widget build(BuildContext context) {
// TextField merges given textStyle with text style from current theme
// Do the same to get final TextStyle
final ThemeData themeData = Theme.of(context);
final TextStyle style = themeData.textTheme.subtitle1.merge(textStyle);
// Use TextPainter to calculate the width of our text
TextSpan ts = new TextSpan(style: style, text: txt.text);
TextPainter tp = new TextPainter(
text: ts,
textDirection: TextDirection.ltr,
);
tp.layout();
// Enforce a minimum width
final textWidth = max(widget.minWidth, tp.width + _CURSOR_WIDTH);
return Container(
width: textWidth,
child: TextField(
cursorWidth: _CURSOR_WIDTH,
style: style,
controller: txt,
onChanged: (text) {
// Redraw the widget
setState(() {});
},
),
);
}
}
Flutter IntrinsicWidth 可以为您进行计算。只需将 TextField
或 TextFormField
包裹在其中,如下所示:
IntrinsicWidth(child: TextField())
在 flutter 中,TextField 没有固有宽度;它只知道如何将自己的大小调整到其父容器的整个宽度。如何将宽度设置为包含文本的宽度。
我尝试将 TextField 放入容器中
如此处所述
new Container(
width: 100.0,
child: new TextField()
)
我希望 TextField 的宽度与其包含的文本的宽度相匹配。 TextField 应随着文本的键入而变宽,并随着文本的删除而变窄。
我能够通过使用 TextPainter
来计算所需的文本宽度来实现预期的结果。然后我将该宽度用作包含 TextField
.
Container
的宽度
记得在您的 TextFields onChanged
方法中调用 setState()
。这会告诉小部件重新绘制自身,从而导致 TextField 调整到其内容的新宽度。
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>{
TextEditingController txt = TextEditingController();
// We will use this text style for the TextPainter used to calculate the width
// and for the TextField so that we calculate the correct size for the text
// we are actually displaying
TextStyle textStyle = TextStyle(color: Colors.grey[600]);
initState() {
super.initState();
// Set the text in the TextField to our initialValue
txt.text = widget.initialValue;
}
@override
Widget build(BuildContext context) {
// Use TextPainter to calculate the width of our text
TextSpan ts = new TextSpan(style: textStyle, text: txt.text);
TextPainter tp = new TextPainter(text: ts, textDirection: TextDirection.ltr);
tp.layout();
var textWidth = tp.width; // We will use this width for the container wrapping our TextField
// Enforce a minimum width
if ( textWidth < widget.minWidth ) {
textWidth = widget.minWidth;
}
return Container(
width: textWidth,
child: TextField(
style: textStyle,
controller: txt,
onChanged: (text) {
// Tells the framework to redraw the widget
// The widget will redraw with a new width
setState(() {});
},
),
);
}
}
我稍微修改了 SteveM 的回答以修复小部件未正确扩展时的错误。我们在计算小部件的宽度时应该尊重这两个小东西:
TextField
合并给定textStyle
参数和当前主题的TextStyle
。这也必须在自定义小部件中完成:
final ThemeData themeData = Theme.of(context);
final TextStyle style = themeData.textTheme.subtitle1.merge(textStyle);
TextField
的cursorWidth
必须考虑到小部件的宽度计算中。由于无法从TextField
class 获取默认光标宽度,我检查了它的代码并向FitsTextField
class 添加了一个新常量。不要忘记将它传递给TextField
的构造函数:
final textWidth = max(widget.minWidth, tp.width + _CURSOR_WIDTH);
// When building a TextField:
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> {
// 2.0 is the default from TextField class
static const _CURSOR_WIDTH = 2.0;
TextEditingController txt = TextEditingController();
// We will use this text style for the TextPainter used to calculate the width
// and for the TextField so that we calculate the correct size for the text
// we are actually displaying
TextStyle textStyle = TextStyle(
color: Colors.grey[600],
fontSize: 16,
);
initState() {
super.initState();
// Set the text in the TextField to our initialValue
txt.text = widget.initialValue;
}
@override
Widget build(BuildContext context) {
// TextField merges given textStyle with text style from current theme
// Do the same to get final TextStyle
final ThemeData themeData = Theme.of(context);
final TextStyle style = themeData.textTheme.subtitle1.merge(textStyle);
// Use TextPainter to calculate the width of our text
TextSpan ts = new TextSpan(style: style, text: txt.text);
TextPainter tp = new TextPainter(
text: ts,
textDirection: TextDirection.ltr,
);
tp.layout();
// Enforce a minimum width
final textWidth = max(widget.minWidth, tp.width + _CURSOR_WIDTH);
return Container(
width: textWidth,
child: TextField(
cursorWidth: _CURSOR_WIDTH,
style: style,
controller: txt,
onChanged: (text) {
// Redraw the widget
setState(() {});
},
),
);
}
}
Flutter IntrinsicWidth 可以为您进行计算。只需将 TextField
或 TextFormField
包裹在其中,如下所示:
IntrinsicWidth(child: TextField())