具有动态容器高度的TabBarView [英] TabBarView with dynamic Container height

查看:94
本文介绍了具有动态容器高度的TabBarView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的布局结构

这是主屏幕

ListView(
  children: <Widget>[
    _buildCarousel(),
    _buildHomeTabBar(),
  ],
)

这是HomeTabBar屏幕

And this is the HomeTabBar screen

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高度.我们该怎么做?

I want to get rid off that Container height. How do we do this?

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

The ChildScreen is getting the data from REST it is actually a GridView.Builder so the height of Container should be dynamic.

抱歉,我实际上错过了ChildScreen的布局

Sorry I missed layout for ChildScreen actually like this

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高度.在不同的设备上看起来很丑...

So inside StreamBuilder is GridView.Builder. The main thing I want to remove Container height. It looks ugly on different devices...

因此,如果我移除高度,它将不会显示在屏幕上并引发错误

So if I remove the height it will not show on screen and throw error

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

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

推荐答案

我在我的项目中有类似的任务.问题的根源在于,您试图将TabBarView(试图扩大的可滚动小部件)放置在没有高度的列小部件中.

I had similar task at my project. The root of the problem is that you are trying to put TabBarView (scrollable widget that trying to be as big as possible), in a column widget, that have no height.

解决方案之一是摆脱在此示例ListView + Column中包裹您的TabBarView的可滚动窗口小部件.并使用NestedScrollView代替它们.您需要将_buildCarousel()TabBar放在headerSliverBuilder部分中,并且将TabBarView放在NestedScrollView的正文中.

One of solutions is get rid of scrollable widgets that wraps your TabBarView in this example ListView + Column. And use NestedScrollView instead of them. You need to put _buildCarousel() and TabBar in the headerSliverBuilder part, and TabBarView inside the body of NestedScrollView.

我不知道您的设计外观如何,但默认情况下NestedScrollView最多打开100%的屏幕视图高度.因此,如果您想使所有内容都在一个屏幕上,则可以通过在需要时更改ScrollController行为来阻止滚动,这很容易.

I don't know how is your design looks, but NestedScrollView by default opens up to 100% height of screen view. So if you want to make an effect that everything is on one screen, it easer to just block scrolling, by change ScrollController behavior when it’s needed.

在此示例中,我禁止在第三个选项卡上滚动,但是您可以检查网格视图最后一项的可见性.只需将密钥添加到最后一项,然后检查其在屏幕上的位置即可.

In this example I’m blocking scrolling on third tab, but you can check visibility of the last item of the grid view. Just add the key to the last item, and check its position on the screen.

希望有帮助.

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小部件.

Another way to get what you want could be creating custom TabView widget.

这篇关于具有动态容器高度的TabBarView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆