首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有动态容器高度的TabBarView

具有动态容器高度的TabBarView
EN

Stack Overflow用户
提问于 2019-02-12 04:13:34
回答 6查看 35.6K关注 0票数 37

这是我的布局结构

这是主屏幕

代码语言:javascript
复制
ListView(
  children: <Widget>[
    _buildCarousel(),
    _buildHomeTabBar(),
  ],
)

这是HomeTabBar屏幕

代码语言:javascript
复制
SingleChildScrollView(
  child:
    DefaultTabController(
      length: myTabs.length,
      initialIndex: 0,
      child: Column(
        children: [
          TabBar(
            isScrollable: true,
            tabs: myTabs,
          ),
          Container(
            height: 600,
              child: 
              TabBarView(
                children: [
                  ChildScreen(),
                  ChildScreen2(),
                  ChildScreen3(),
                ],
              )
          )
        ],
      ))
);

我想摆脱Container的高度。我们该怎么做?

ChildScreen从REST获取数据,实际上它是一个GridView.Builder,因此Container的高度应该是动态的。

对不起,我错过了ChildScreen的布局,实际上是这样的

代码语言:javascript
复制
SingleChildScrollView(
  // shrinkWrap: true,
child: Column(
    children: <Widget>[
        StreamBuilder(
          stream: categoryBloc.categoryList,
          builder: (context, AsyncSnapshot<List<Category>> snapshot){
              if (snapshot.hasData && snapshot!=null) {
                if(snapshot.data.length > 0){
                  return buildCategoryList(snapshot);
                }
                else if(snapshot.data.length==0){
                    return Text('No Data');
                }
              }
              else if (snapshot.hasError) {
                return ErrorScreen(errMessage: snapshot.error.toString());
              }     
              return Center(child: CircularProgressIndicator());

          },
        ),       
    ]
  )
);

所以StreamBuilder的内部是GridView.Builder。我想要移除Container高度的主要内容。在不同的设备上看起来很难看..。

因此,如果我删除高度,它将不会显示在屏幕上并抛出错误。

I/ (package:flutter/src/rendering/sliver_list.dart:200:17) ( 493):#2 RenderObject.layout (package:flutter/src/rendering/sliver_list.dart:233:19) I/颤振( 493):#3 RenderSliverList.performLayout.advance RenderSliverList.performLayout I/颤振( 493):#4 RenderSliverList.performLayout(package:flutter/src/rendering/sliver_list.dart:233:19)I/颤振( 493):#5(package:flutter/src/rendering/object.dart:1634:7) I/颤振( 493):#6 RenderSliverPadding.performLayout (package:flutter/src/rendering/sliver_padding.dart:182:11) I/颤振( 493):#7 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7) I/颤振( 493):#8 RenderViewportBase.layoutChildSequence (软件包:flutter/src/ RenderObject.layout /viewport.dart):405:13) I/颤振( 493):#9 (package:flutter/src/rendering/viewport.dart:1316:12) I/颤振( 493):#10 RenderViewport.performLayout (package:flutter/src/rendering/viewport.dart:1234:20) I/颤振( 493):#11 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7) I/颤振( 493):#12_RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:104:13) I/颤振( 493):#13 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7)

EN

回答 6

Stack Overflow用户

发布于 2019-08-06 19:46:55

我的项目中也有类似的任务。问题的根源在于您试图将TabBarView (尽可能大的可滚动小部件)放到没有高度的列小部件中。

解决方案之一是在本例中去掉包装TabBarView的可滚动小部件ListView + Column。并使用NestedScrollView代替它们。您需要将_buildCarousel()TabBar放在headerSliverBuilder部分中,TabBarView放在NestedScrollView的主体中。

我不知道你的设计是什么样子,但NestedScrollView默认打开高达100%的屏幕视图。因此,如果您想要使所有内容都在一个屏幕上,只需在需要时通过更改ScrollController行为来阻止滚动就更容易了。

在本例中,我在第三个选项卡上阻止滚动,但您可以检查网格视图的最后一个项的可见性。只需将键添加到最后一个项目,并检查其在屏幕上的位置。

希望能帮上忙。

代码语言:javascript
复制
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  final bodyGlobalKey = GlobalKey();
  final List<Widget> myTabs = [
    Tab(text: 'auto short'),
    Tab(text: 'auto long'),
    Tab(text: 'fixed'),
  ];
  TabController _tabController;
  ScrollController _scrollController;
  bool fixedScroll;

  Widget _buildCarousel() {
    return Stack(
      children: <Widget>[
        Placeholder(fallbackHeight: 100),
        Positioned.fill(child: Align(alignment: Alignment.center, child: Text('Slider'))),
      ],
    );
  }

  @override
  void initState() {
    _scrollController = ScrollController();
    _scrollController.addListener(_scrollListener);
    _tabController = TabController(length: 3, vsync: this);
    _tabController.addListener(_smoothScrollToTop);

    super.initState();
  }

  @override
  void dispose() {
    _tabController.dispose();
    _scrollController.dispose();
    super.dispose();
  }

  _scrollListener() {
    if (fixedScroll) {
      _scrollController.jumpTo(0);
    }
  }

  _smoothScrollToTop() {
    _scrollController.animateTo(
      0,
      duration: Duration(microseconds: 300),
      curve: Curves.ease,
    );

    setState(() {
      fixedScroll = _tabController.index == 2;
    });
  }

  _buildTabContext(int lineCount) => Container(
        child: ListView.builder(
          physics: const ClampingScrollPhysics(),
          itemCount: lineCount,
          itemBuilder: (BuildContext context, int index) {
            return Text('some content');
          },
        ),
      );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: NestedScrollView(
        controller: _scrollController,
        headerSliverBuilder: (context, value) {
          return [
            SliverToBoxAdapter(child: _buildCarousel()),
            SliverToBoxAdapter(
              child: TabBar(
                controller: _tabController,
                labelColor: Colors.redAccent,
                isScrollable: true,
                tabs: myTabs,
              ),
            ),
          ];
        },
        body: Container(
          child: TabBarView(
            controller: _tabController,
            children: [_buildTabContext(2), _buildTabContext(200), _buildTabContext(2)],
          ),
        ),
      ),
    );
  }
}

另一种获取所需内容的方法是创建自定义TabView小部件。

票数 80
EN

Stack Overflow用户

发布于 2021-01-08 19:54:46

如果您也使用展开时出错,则不要使用TabBarView创建自定义TabBarView

  1. 从onTap获取索引,是TabBar的属性。
  2. 然后在要选择的索引的onTap函数中使用if else,并使用索引初始化全局变量。
  3. 然后使用building构建TabBarView。同样地,在Builder中,您将使用if来获得所选的索引。然后返回你的小部件在如果其他。

在这种情况下,您可以获得小部件的最大或最小高度。您不需要指定容器高度。

_selectedTabBar是一个全局变量。

代码语言:javascript
复制
 Column(children: [
               TabBar(
                       onTap: (index) {
                          print(index);                                  
                          setState(() {
                                _selectedTabbar = index;
                          });
                        },
                        tabs: [
                          Tab(
                            text: 'Tab1',
                          ),
                          Tab(
                            text: 'Tab2',
                          ),
                          Tab(
                            text: 'Tab3',
                          ),
                        ],
                      ),
                    
                      Builder(builder: (_) {
                        if (_selectedTabbar == 0) {
                          return Container();//1st custom tabBarView
                        } else if (_selectedTabbar == 1) {
                          return Container();//2nd tabView
                        } else {
                          return Container(); //3rd tabView
                        }
                      }),
]
)
票数 21
EN

Stack Overflow用户

发布于 2021-05-23 20:43:28

工作解决方案:您需要在两个地方进行扩展

  1. 高于DefaultTabController。
  2. 容器的容器。
代码语言:javascript
复制
Expanded(
    child: Container(
        decoration: BoxDecoration(
          border: Border(
              top: BorderSide(
                  color: Colors.grey, width: 0.5))),
        child: TabBarView(
          children: <Widget>[
              Container(),
              Container(),
              Container(),
        ])),),

一个是不够的。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54642710

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档