【问题标题】:Flutter: Using Expandable Textfield with BottomNavigationBarFlutter:使用带有 BottomNavigationBar 的可扩展文本字段
【发布时间】:2020-05-16 12:44:59
【问题描述】:

我需要一些关于这个布局的帮助:)

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

所以它基本上是一个带有HeaderContainer 部分)和多个Tabs 用于记笔记的笔记应用程序。

这是目前的解决方案:

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

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

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】:

    你只是有些东西放错了地方。尽可能多地尝试将代码分解为可重用的小部件。它有助于使一切更有条理。

    此外,作为一般规则,当您尝试实现通常需要的东西时,很可能已经为它构建了一个小部件。在这种情况下,您不需要弄乱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),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            );
          },
        );
      }
    }
    

    【讨论】:

    • 1.) 我使用 AnimatedCrossfade 等是有原因的。标准的 NavigationBar 对我不起作用,因为我需要一个动态且可滚动的 BottomNavigatiomBar。我找不到从哪里得到它的 stackoverflow 帖子......但是 BottomNavigation 在方面工作正常。
    • 2.) 包含 Header 的 Container 不应该是 TabBarBody 的一部分,因为它在浏览选项卡时应该保持固定。所以它需要在 TabBarBody 之外。但仍然感谢您的帮助:)
    • 或者换句话说,如果你开始滚动,容器(页眉)和选项卡应该表现为一个页面 -> 容器和选项卡一起滚动。如果您向右或向左滑动,Container 和 Tab/TabBarBody 的行为应该是分开的 -> 当 Tab/TabBarBody 向右或向左移动时,Container 保持固定。
    猜你喜欢
    • 2018-08-13
    • 1970-01-01
    • 2013-05-11
    • 1970-01-01
    • 1970-01-01
    • 2020-10-11
    • 2016-08-31
    • 1970-01-01
    • 2020-08-13
    相关资源
    最近更新 更多