我有一个带有一些 TextFormField 的表单,我想扩展最后一个 TextFormField 以占据屏幕的其余部分。最后一个 TextFormField 可以有多行文本。
我没能做到这一点,并尝试了
SizedBox.expand()
和Expanded
小部件,但没有运气。
以下是当前代码:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"What is this new classroom?"
),
SizedBox(height: 8.0,),
Expanded(
child: Form(
key: _formKey,
child: ListView(
padding: EdgeInsets.all(8.0),
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Classroom Name",
hintText: "What's name of the new classroom?",
),
)
),
SizedBox(height: 8.0,),
Container(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Description",
hintText: "Description of the new classroom",
),
//maxLines: 5,
),
),
]
),
),
),
],
),
),
);
}
}
我稍微编辑了你的代码。但是没用。请参考以下代码。我会尝试解释我的理解在代码下面。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("What is this new classroom?"),
SizedBox(
height: 8.0,
),
Expanded(
child: Form(
key: _formKey,
child: Column(children: <Widget>[
Container(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Classroom Name",
hintText: "What's name of the new classroom?",
),
)),
SizedBox(
height: 8.0,
),
Expanded(
child: Container(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: TextFormField(
maxLines: null,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Description",
hintText: "Description of the new classroom",
),
),
),
),
]),
)),
],
),
),
);
}
}
我用你的代码检查了视图。
TextField
里面的 TextFormField
没有占据屏幕的其余部分。所以我编辑了TextField
来拥有屏幕的其余部分。上面的代码就是这样做的。查看检查视图
但是有
InputDecorator
(它是我们的TextField的孩子)绘制边界线。在我们的例子中,它根据内容绘制边界线。
可能的解决方法是:
maxLines = null
这将增加 TextField
作为内容组。但初始视图将是一行。maxLines
(如 10 或 20),这看起来像是占据了屏幕。但它不是动态的(不会根据屏幕尺寸/屏幕方向改变)我找到了解决方案,也许它可以帮助某人。您可以创建 Container 或另一个具有与 TextField 相同边框的小部件,并使其扩展以填充整个屏幕,并在其上方使用 Stack 小部件将 TextField 与 maxLines: null 和无边框。
[编辑] 它也可以在没有 Stack 小部件的情况下工作。这是我的代码
Expanded(
child: Material(
borderRadius: BorderRadius.circular(10),
color: Colors.white,
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
hintText: "Description",
),
keyboardType: TextInputType.multiline,
maxLines: null,
),
),
),
expands: true,
解决您的问题:) 这是扩展文本字段的代码:
TextField(
maxLines: null,
expands: true,
textAlignVertical: TextAlignVertical.top,
keyboardType: TextInputType.multiline,
)
您还可以在使用
contentPadding
addPostFrameCallback
渲染小部件后设置initState()
。
但是您必须根据上述所有小部件的位置和高度手动计算新高度。
例子:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final _tffKey1 =
GlobalKey();
final _tffKey2 = GlobalKey();
final _scaffoldKey = GlobalKey();
final _textKey = GlobalKey();
double _height = 0;
//Set callback that will be called after widgets are rendered.
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
final RenderBox scaffoldKeyBox = _scaffoldKey.currentContext.findRenderObject();
final RenderBox tffBox = _tffKey1.currentContext.findRenderObject();
final RenderBox textBox = _textKey.currentContext.findRenderObject();
final tffPos = tffBox.localToGlobal(Offset.zero);
final textPos = textBox.localToGlobal(Offset.zero);
//Calculate widget's height.
_height = (scaffoldKeyBox.size.height -
(tffBox.size.height + tffPos.dy) -
(textBox.size.height + textPos.dy));
setState(() {});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"What is this new classroom?",
key: _textKey,
),
SizedBox(
height: 8.0,
),
Expanded(
child: Form(
key: _formKey,
child:
ListView(padding: EdgeInsets.all(8.0), children: <Widget>[
Container(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: TextFormField(
key: _tffKey1,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Classroom Name",
hintText: "What's name of the new classroom?",
),
)),
Container(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: TextFormField(
key: _tffKey2,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(left: 8, top: _height), // Set new height here
border: OutlineInputBorder(),
labelText: "Description",
hintText: "Description of the new classroom",
),
),
),
]),
),
),
],
),
),
);
}
}
我知道有点晚了,但答案已发布here。 你只需要以下
TextField(
keyboardType: TextInputType.multiline,
maxLines: whatever,
)
TextFormField 包含 expands 属性。
Expanded(
child: TextFormField(
//...
maxLines: null,
expands: true,
)),
当您将
expands
属性设置为true时,您必须将maxLines
设置为null
。然后,为了让它工作,将 TextFormField
包裹在 Expanded
中。
很简单
TextFormField(
expands: true, // add this line
minLines: null, // add this line
maxLines: null, // add this line
decoration: InputDecoration(
// if you want to change text form field background color
// add this two lines
fillColor: Theme.of(context).colorScheme.background,
filled: true,
),
)