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

查看:23
本文介绍了具有动态容器高度的 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(包: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 放在 headerSliv​​erBuilder 部分,并将 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天全站免登陆