[英]Flutter: Using Expandable Textfield with BottomNavigationBar
I need some help with this layout :)我需要一些有关此布局的帮助:)
The Layout contains a BottomNavigationBar
.布局包含一个BottomNavigationBar
。 The body consists of a Container
at the top (which serves as some kind of header) and a Textfield
below the Container
.主体由顶部的Container
(用作某种标题)和Container
下方的Textfield
。 The Textfield
should expand to fill the remaining space. Textfield
应扩展以填充剩余空间。 As soon as the user enters enough lines so that the text doesn't fit on the screen, the whole body ( Textfield
and Container
) should become scrollable
.一旦用户输入了足够多的行以致文本无法显示在屏幕上,整个正文( Textfield
和Container
)应该变为scrollable
。
So it's basically a note app with a Header
(the Container
part) and multiple Tabs
for Note taking.所以它基本上是一个带有Header
( Container
部分)和多个用于记笔记的Tabs
的笔记应用程序。
This is the solution so far:这是迄今为止的解决方案:
Scaffold buildBody(BuildContext context) {
return Scaffold(
appBar: AppBar(...),
body: _buildScaffoldBody(),
bottomNavigationBar: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
AnimatedCrossFade(
firstChild: Material(
color: Theme.of(context).primaryColor,
child: TabBar(
controller: _tabController,
tabs: _tabNames,
onTap: (int) {
...
},
),
),
secondChild: Container(),
crossFadeState: _screen == 0
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
duration: const Duration(milliseconds: 300),
),
],
),
);
}
Widget _buildScaffoldBody() {
return LayoutBuilder(
builder: (context, constraint) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: constraint.maxHeight),
child: IntrinsicHeight(
child: Column(
children: <Widget>[
Container(
height: 100,
alignment: Alignment.center,
color: Colors.green,
child: Text("Header"),
),
Expanded( //This is probably the cause
child: TabBarView( //of the exception
controller: _tabController,
children: <Widget>[
TextField(
expands: true,
maxLines: null,
decoration: InputDecoration(
fillColor: Colors.blue[200], filled: true),
),
TextField(
expands: true,
maxLines: null,
decoration: InputDecoration(
fillColor: Colors.blue[200], filled: true),
),
TextField(
expands: true,
maxLines: null,
decoration: InputDecoration(
fillColor: Colors.blue[200], filled: true),
),
]
)
)
],
),
),
),
);
},
);
But it's throwing an exception.I tried replacing Expanded
with a Container
and hardcoding height
and width
.但它抛出了一个异常。我尝试用Container
替换Expanded
并硬编码height
和width
。 If I do so the exception is not thrown, but the Textfield
is no longer expandable
and it doesn't scroll together with the Header
.如果我这样做,则不会抛出异常,但Textfield
不再expandable
,并且不会与Header
一起滚动。 It only scrolls within the Container
wrapping the Textfield
.它仅在包装Textfield
的Container
内滚动。
The following assertion was thrown during performLayout():
I/flutter ( 8080): RenderViewport does not support returning intrinsic dimensions.
I/flutter ( 8080): Calculating the intrinsic dimensions would require instantiating every child of the viewport, which
I/flutter ( 8080): defeats the point of viewports being lazy.
I/flutter ( 8080): If you are merely trying to shrink-wrap the viewport in the main axis direction, consider a
I/flutter ( 8080): RenderShrinkWrappingViewport render object (ShrinkWrappingViewport widget), which achieves that
I/flutter ( 8080): effect without implementing the intrinsic dimension API.
I/flutter ( 8080):
I/flutter ( 8080): The relevant error-causing widget was:
I/flutter ( 8080): IntrinsicHeight
You just have some stuff misplaced.你只是放错了一些东西。 Try as much as you can to break apart your code into re-usable widgets.尽可能多地尝试将代码分解为可重复使用的小部件。 It helps to keep everything more organized.它有助于让一切更有条理。
Also, as a general rule, when you're trying to implement something commonly needed, chances are there will be a widget built for it already.此外,作为一般规则,当您尝试实现一些通常需要的东西时,很可能已经为它构建了一个小部件。 In this case, you don't need to mess with the AnimatedCrossFade
etc... It's all built into the TabBarView
.在这种情况下,您不需要弄乱AnimatedCrossFade
等......它都内置在TabBarView
。
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
home: TabBarScaffold(),
);
}
}
class TabBarScaffold extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
color: Colors.yellow,
home: DefaultTabController(
length: 3,
child: new Scaffold(
body: MyPages(),
bottomNavigationBar: MyTabs(),
),
),
);
}
}
class MyTabs extends StatelessWidget {
@override
Widget build(BuildContext context) {
return TabBar(
tabs: [
Tab(
child: Text("Tab 1"),
),
Tab(
child: Text("Tab 2"),
),
Tab(
child: Text("Tab 3"),
),
],
labelColor: Colors.blue,
unselectedLabelColor: Colors.black,
indicatorSize: TabBarIndicatorSize.label,
indicatorPadding: EdgeInsets.all(5.0),
indicatorColor: Colors.red,
);
}
}
class MyPages extends StatelessWidget {
@override
Widget build(BuildContext context) {
return TabBarView(
children: [
MyPageBody(
textBackgroundColor: Colors.blue[200],
),
MyPageBody(
textBackgroundColor: Colors.green[200],
),
MyPageBody(
textBackgroundColor: Colors.red[200],
),
],
);
}
}
class MyPageBody extends StatelessWidget {
final Color textBackgroundColor;
MyPageBody({this.textBackgroundColor});
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraint) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: constraint.maxHeight),
child: IntrinsicHeight(
child: Column(
children: <Widget>[
Container(
height: 100,
alignment: Alignment.center,
color: Colors.green,
child: Text("Header"),
),
Expanded(
child: TextField(
expands: true,
maxLines: null,
decoration: InputDecoration(
fillColor: textBackgroundColor, filled: true),
),
),
],
),
),
),
);
},
);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.