Flutter:将可扩展文本字段与BottomNavigationBar一起使用

问题描述 投票:0回答:1

我需要有关此布局的帮助:)

布局包含BottomNavigationBar。主体由顶部的Container(用作某种标头)和Textfield的下面的Container组成。 Textfield应该展开以填充剩余的空间。一旦用户输入了足够多的行以使文本无法显示在屏幕上,整个正文(TextfieldContainer)应变为scrollable

因此,它基本上是一个笔记应用程序,具有HeaderContainer部分)和多个Tabs用于记录笔记。

enter image description here

到目前为止,这是解决方案:

  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),
                          ),
                        ]
                      )
                    )
                ],
              ),
            ),
          ),
        );
      },
    );

但是它引发了异常。我尝试将Expanded替换为Container,并对heightwidth进行硬编码。如果这样做,则不会引发异常,但是Textfield不再是expandable,并且不会与Header一起滚动。它仅在包裹ContainerTextfield中滚动。

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
android flutter flutter-layout
1个回答
0
投票

您只是放错了一些东西。尽力将代码分解成可重用的小部件。它有助于保持一切井井有条。

此外,通常,当您尝试实现一些常用的东西时,很可能已经为它构建了一个小部件。在这种情况下,您无需弄乱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),
                    ),
                  ),
                ],
              ),
            ),
          ),
        );
      },
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.