【问题标题】:TabBarView in TabBar to take up the remaining spaceTabBar 中的 TabBarView 占用剩余空间
【发布时间】:2019-10-08 17:37:38
【问题描述】:

我一直在我的颤振应用程序中使用TabBar(),除非我发现它在屏幕尺寸变化时我的TabBarView() 搞砸了,否则它可以工作。 在关注this 问题后,我发现我的问题的解决方案是Expanded() for TabBarView()。我已经尽力而为,但我得到的只是渲染数据的很多错误。

       ⡿flutter: ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
flutter: The following assertion was thrown during performLayout():
flutter: RenderFlex children have non-zero flex but incoming height constraints are unbounded.
       ⣟flutter: When a column is in a parent that does not provide a finite height constraint, for example if it is
flutter: in a vertical scrollable, it will try to shrink-wrap its children along the vertical axis. Setting a
flutter: flex on a child (e.g. using Expanded) indicates that the child is to expand to fill the remaining
flutter: space in the vertical direction.
flutter: These two directives are mutually exclusive. If a parent is to shrink-wrap its child, the child
flutter: cannot simultaneously expand to fit its parent.
flutter: Consider setting mainAxisSize to MainAxisSize.min and using FlexFit.loose fits for the flexible
flutter: children (using Flexible rather than Expanded). This will allow the flexible children to size
flutter: themselves to less than the infinite remaining space they would otherwise be forced to take, and
flutter: then will cause the RenderFlex to shrink-wrap the children rather than expanding to fit the maximum
flutter: constraints provided by the parent.
flutter: If this message did not help you determine the problem, consider using debugDumpRenderTree():
flutter:   https://flutter.dev/debugging/#rendering-layer
flutter:   http://docs.flutter.io/flutter/rendering/debugDumpRenderTree.html
flutter: The affected RenderFlex is:
flutter:   RenderFlex#bc077 relayoutBoundary=up2 NEEDS-LAYOUT NEEDS-PAINT(creator: Column ← TabWidget ← Column ← MediaQuery ← LayoutId-[<_ScaffoldSlot.body>] ← CustomMultiChildLayout ← AnimatedBuilder ← DefaultTextStyle ← AnimatedDefaultTextStyle ← _InkFeatures-[GlobalKey#4f100 ink renderer] ← NotificationListener<LayoutChangedNotification> ← PhysicalModel ← ⋯, parentData: offset=Offset(0.0, 0.0); flex=null; fit=null (can use size), constraints: BoxConstraints(w=375.0, 0.0<=h<=Infinity), size: MISSING, direction: vertical, mainAxisAlignment: start, mainAxisSize: min, crossAxisAlignment: start, textDirection: ltr, verticalDirection: down)
flutter: The creator information is set to:
flutter:   Column ← TabWidget ← Column ← MediaQuery ← LayoutId-[<_ScaffoldSlot.body>] ←
flutter:   CustomMultiChildLayout ← AnimatedBuilder ← DefaultTextStyle ← AnimatedDefaultTextStyle ←
flutter:   _InkFeatures-[GlobalKey#4f100 ink renderer] ← NotificationListener<LayoutChangedNotification> ←
flutter:   PhysicalModel ← ⋯
flutter: The nearest ancestor providing an unbounded width constraint is: RenderFlex#0807f relayoutBoundary=up1 NEEDS-LAYOUT NEEDS-PAINT:
flutter:   creator: Column ← MediaQuery ← LayoutId-[<_ScaffoldSlot.body>] ← CustomMultiChildLayout ←
flutter:     AnimatedBuilder ← DefaultTextStyle ← AnimatedDefaultTextStyle ← _InkFeatures-[GlobalKey#4f100 ink
flutter:     renderer] ← NotificationListener<LayoutChangedNotification> ← PhysicalModel ←
flutter:     AnimatedPhysicalModel ← Material ← ⋯
flutter:   parentData: offset=Offset(0.0, 0.0); id=_ScaffoldSlot.body (can use size)
flutter:   constraints: BoxConstraints(0.0<=w<=375.0, 0.0<=h<=591.0)
flutter:   size: MISSING
flutter:   direction: vertical
flutter:   mainAxisAlignment: start
flutter:   mainAxisSize: min
flutter:   crossAxisAlignment: stretch
flutter:   verticalDirection: down
flutter: See also: https://flutter.dev/layout/
flutter: If none of the above helps enough to fix this problem, please don't hesitate to file a bug:
flutter:   https://github.com/flutter/flutter/issues/new?template=BUG.md
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0      RenderFlex.performLayout.<anonymous closure> (package:flutter/src/rendering/flex.dart:691:11)
flutter: #1      RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:717:10)
flutter: #2      RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #3      RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:743:15)
flutter: #4      RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #5      MultiChildLayoutDelegate.layoutChild (package:flutter/src/rendering/custom_layout.dart:142:11)
flutter: #6      _ScaffoldLayout.performLayout (package:flutter/src/material/scaffold.dart:443:7)
flutter: #7      MultiChildLayoutDelegate._callPerformLayout (package:flutter/src/rendering/custom_layout.dart:212:7)
flutter: #8      RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:356:14)
flutter: #9      RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #10     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #11     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #12     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #13     _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1214:11)
flutter: #14     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #15     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #16     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #17     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #18     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #19     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #20     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #21     RenderStack.performLayout (package:flutter/src/rendering/stack.dart:510:15)
flutter: #22     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #23     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #24     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #25     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #26     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #27     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #28     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #29     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #30     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #31     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #32     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #33     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #34     RenderOffstage.performLayout (package:flutter/src/rendering/proxy_box.dart:3067:13)
flutter: #35     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #36     RenderStack.performLayout (package:flutter/src/rendering/stack.dart:510:15)
flutter: #37     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #38     __RenderTheatre&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #39     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #40     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #41     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #42     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #43     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #44     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #45     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #46     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #47     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #48     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
flutter: #49     RenderObject.layout (package:flutter/src/rendering/object.dart:1620:7)
flutter: #50     RenderView.performLayout (package:flutter/src/rendering/view.dart:151:13)
flutter: #51     RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1497:7)
flutter: #52     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:766:18)
flutter: #53     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:346:19)
flutter: #54     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:701:13)
flutter: #55     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:285:5)
flutter: #56     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1012:15)
flutter: #57     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:952:9)
flutter: #58     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:773:7)
flutter: #60     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:382:19)
flutter: #61     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:416:5)
flutter: #62     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:171:12)
flutter: (elided one frame from package dart:async-patch)
flutter:
flutter: The following RenderObject was being processed when the exception was fired: RenderFlex#bc077 relayoutBoundary=up2 NEEDS-LAYOUT NEEDS-PAINT:
flutter:   creator: Column ← TabWidget ← Column ← MediaQuery ← LayoutId-[<_ScaffoldSlot.body>] ←
flutter:     CustomMultiChildLayout ← AnimatedBuilder ← DefaultTextStyle ← AnimatedDefaultTextStyle ←
flutter:     _InkFeatures-[GlobalKey#4f100 ink renderer] ← NotificationListener<LayoutChangedNotification> ←
flutter:     PhysicalModel ← ⋯
       ⣯flutter:   parentData: offset=Offset(0.0, 0.0); flex=null; fit=null (can use size)
flutter:   constraints: BoxConstraints(w=375.0, 0.0<=h<=Infinity)
flutter:   size: MISSING
flutter:   direction: vertical
flutter:   mainAxisAlignment: start
flutter:   mainAxisSize: min
flutter:   crossAxisAlignment: start
flutter:   textDirection: ltr
flutter:   verticalDirection: down
flutter: This This RenderObject had the following descendants (showing up to depth 5):
flutter:     child 1: RenderPadding#ec776 relayoutBoundary=up3 NEEDS-PAINT
flutter:       child: RenderDecoratedBox#82c7d relayoutBoundary=up4 NEEDS-PAINT
flutter:         child: RenderPadding#47def relayoutBoundary=up5 NEEDS-PAINT
flutter:           child: RenderCustomPaint#d3174 relayoutBoundary=up6 NEEDS-PAINT
flutter:             child: _TabLabelBarRenderer#1dbbb relayoutBoundary=up7 NEEDS-PAINT
flutter:     child 2: _RenderScrollSemantics#ab273 NEEDS-LAYOUT NEEDS-PAINT
flutter:       child: RenderPointerListener#85f41 NEEDS-LAYOUT NEEDS-PAINT
flutter:         child: RenderSemanticsGestureHandler#dfb17 NEEDS-LAYOUT NEEDS-PAINT
flutter:           child: RenderPointerListener#36472 NEEDS-LAYOUT NEEDS-PAINT
flutter:             child: RenderSemanticsAnnotations#0d0f0 NEEDS-LAYOUT NEEDS-PAINT
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════
flutter: Another exception was thrown: RenderBox was not laid out: RenderFlex#bc077 relayoutBoundary=up2 NEEDS-PAINT
flutter: Another exception was thrown: RenderBox was not laid out: RenderFlex#0807f relayoutBoundary=up1 NEEDS-PAINT
flutter: Another exception was thrown: NoSuchMethodError: The method '>' was called on null.

现在让您了解我一直在做的事情是,我有一个小部件类,我在其中定义了我的TabBar,并且我在不同的地方使用它。

这是我的 TabBar 类小部件:

@override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Container(
          margin: EdgeInsets.only(left: 16.0, right: 16.0),
          decoration: BoxDecoration(
            color: Colors.white.withOpacity(0.0),
            border: Border(bottom: BorderSide(color: Colors.grey, width: 0.5))),
          child: TabBar(
            unselectedLabelColor: Colors.grey,
            unselectedLabelStyle: TextStyle().copyWith(fontSize: 16.0, fontWeight: FontWeight.normal),
            labelColor: Color.fromRGBO(253, 92, 99, 1),
            labelStyle: TextStyle().copyWith(fontSize: 16.0, fontWeight: FontWeight.bold),
            indicatorColor: Color.fromRGBO(253, 92, 99, 1),
            indicatorWeight: widget.indicatorWeight,
            controller: _controller,
            tabs: [
              new Tab(
                child: Padding(
                  padding: EdgeInsets.only(top: 18.0),
                  child: Text(widget.childOneHeader, style: TextStyle(fontSize: 15.0)),
                )
              ),
              new Tab(
                child: Padding(
                  padding: EdgeInsets.only(top: 18.0),
                  child: Text(widget.childTwoHeader, style: TextStyle(fontSize: 15.0)),
                )
              ),
              new Tab(
                child: Padding(
                  padding: EdgeInsets.only(top: 18.0),
                  child: Text(widget.childThreeHeader, style: TextStyle(fontSize: 15.0)),
                )
              )
            ]
          )
        ),
        Expanded(
          //height: widget.layoutHeight,
          child: new TabBarView(
            controller: _controller,
            children: <Widget>[
              widget.childOne,
              widget.childTwo,
              widget.childThree
            ],
          )
        )
      ]
    );

widget. 的数据来自它的构造函数。

现在我一直在我的页面中使用它,其中 ListView() 用于我的 TabBarView() children,所以我只从他们那里传递它。

类使用 TabBar 代码:

body: Column(
   mainAxisSize: MainAxisSize.min,
   crossAxisAlignment: CrossAxisAlignment.stretch,
   children: <Widget>[
     Text('Heading'),
     Container(),
     TabWidget(
            indicatorWeight: 1.0,
            childOneHeader: 'Title 1',
            childTwoHeader: 'Title 2',
            childThreeHeader: 'Title 3',
            childOne: ListView(
              shrinkWrap: true,
              scrollDirection: Axis.vertical,
              children: this.isDataNull ? 
                [Container(
                  child: errorWidget,
                )] 
                : this.getOffersWidgets()
            ),
            childTwo: ListView(
              shrinkWrap: true,
              scrollDirection: Axis.vertical,
              children: this.isDataNull ? 
              [Container(
                child: errorWidget,
              )] 
              : this.getBarWidgets()
            ),
            childThree: ListView(
              shrinkWrap: true,
              scrollDirection: Axis.vertical,
              children: this.isDataNull ? 
              [Container(
                child: errorWidget,
              )]
              : this.getEventWidget()
            )
          )
   ]
);

我已经尽力了我的水平,但无法让它发挥作用。我得到的只是一个空白页。请帮我解决一下这个。谢谢:)

解决方案:

因为我找到了出路,所以我想以后看到这个问题的朋友也会从这个问题中受益。

顺便说一下,如果您想看一看,这是答案的链接:Solution to my problem

在使用 tabbarcode 的类中,将 TabWidget 包裹在 Expanded() 中,其余部分相同,您的工作就完成了。

body: Column(
   mainAxisSize: MainAxisSize.min,
   crossAxisAlignment: CrossAxisAlignment.stretch,
   children: <Widget>[
     Text('Heading'),
     Container(),
     Expanded(
      child: TabWidget(//your content goes here)
     )

特别感谢MFARKAN

请注意,永远不要在 ListView() 或任何可滚动小部件中使用 Expanded() 或 Flexible(),因为它们需要有限的高度。在内容中使用它,但不能用于 Expanded()

谢谢各位! :)

【问题讨论】:

  • 尝试删除 Column 中的 mainAxisSize 最重要的是 shrinkwrap: true 导致错误,删除它们并告诉我。
  • 不适合我@Blasanka。 RenderFlex children have non-zero flex but incoming height constraints are unbounded. 以及更多类似的错误
  • 我已经为此打开了问题,我想你在 github/flutter 上检查了这个问题; github.com/flutter/flutter/issues/33072
  • 好的,我会检查@MFARKAN
  • 不客气,伙计,我什么都没说,谢谢你提到

标签: dart flutter uitabbar


【解决方案1】:

重申解决方案以关闭线程。正如在 GitHub 上发布的 issue ticket 中所述,TabBarView 需要渲染一个有限的高度。这可以通过使用已发布的错误日志和此GitHub thread中发布的解决方案中建议的扩展小部件来实现@

这是您可以尝试的最小重现

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,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      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> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Expanded(
        child: TabWidget(),
      ),
    );
  }
}

class TabWidget extends StatefulWidget {
  @override
  _TabWidgetState createState() => _TabWidgetState();
}

class _TabWidgetState extends State<TabWidget>
    with SingleTickerProviderStateMixin {
  TabController _controller;
  @override
  void initState() {
    super.initState();
    _controller = TabController(length: 3, vsync: this);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.symmetric(horizontal: 10.0),
      child: Column(
        children: <Widget>[
          TabBar(
            labelColor: Colors.black,
            indicatorColor: Colors.blue,
            controller: _controller,
            tabs: <Widget>[
              Tab(
                text: 'Tab 1',
              ),
              Tab(
                text: 'Tab 2',
              ),
              Tab(
                text: 'Tab 3',
              ),
            ],
          ),
          Expanded(
            child: TabBarView(
              controller: _controller,
              children: <Widget>[
                Center(
                  child: Text('Tab View 1'),
                ),
                Center(
                  child: Text('Tab View 2'),
                ),
                Center(
                  child: Text('Tab View 3'),
                ),
              ],
            ),
          )
        ],
      ),
    );
  }
}

应用的外观

【讨论】: