【问题标题】:How can I have a TabView with variable height content within a Scrollable View with Flutter?如何在带有 Flutter 的可滚动视图中拥有具有可变高度内容的 TabView?
【发布时间】:2017-06-16 01:28:38
【问题描述】:

我有一个 TabBarTabBarView 嵌套在 Block 中。这是因为 TabBarView 内部的内容是动态的,内容的高度直到运行时才知道。

我无法将 Block 嵌套在 TabBarView 内,因为 TabBar 前面的内容应与 TabBarView 内容一起滚动。

图表:

代码:

new DefaultTabController(
  length: 3,
  child: new Block(
    children: [
      new Container(
        height: 200.0,
        decoration: new BoxDecoration(
          backgroundColor: Colors.blue[500],
        ),
      ),
      new TabBar(
        tabs: <Widget>[
          new Tab(text: '1'),
          new Tab(text: '2'),
          new Tab(text: '3'),
        ],
      ),
      new TabBarView(
        children: [
          new Text('one'),
          new Text('two'),
          new Text('three'),
        ],
      ),
    ],
  )
);

但是,TabBarView 的 Viewport 不受约束,需要一个具有有限高度约束的祖先小部件。不幸的是,一个 Block 并没有给出一个有界的高度,因为它的可滚动特性。

我在运行布局时收到此错误:

══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY    ╞═════════════════════════════════════════════════════════
I/flutter (28715): The following assertion was thrown during   performLayout():
I/flutter (28715): RenderList object was given an infinite size during layout.
I/flutter (28715): This probably means that it is a render object that tries to be as big as possible, but it was put
I/flutter (28715): inside another render object that allows its children to pick their own size.
I/flutter (28715): The nearest ancestor providing an unbounded height constraint is: ...

关于如何最好地解决这个问题的任何想法?

【问题讨论】:

标签: dart flutter


【解决方案1】:

我不知道什么是块(链接不再起作用)。但正如我从问题中看到的,您需要将 TableView 放在一些可滚动的组件中。

最简单的解决方案是使用标签控制器 + 容器代替 TabView Widget。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  final List<Widget> myTabs = [
    Tab(text: 'one'),
    Tab(text: 'two'),
    Tab(text: 'three'),
  ];

  TabController _tabController;
  int _tabIndex = 0;

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

  @override
  void initState() {
    _tabController = TabController(length: 3, vsync: this);
    _tabController.addListener(_handleTabSelection);
    super.initState();
  }

  _handleTabSelection() {
    if (_tabController.indexIsChanging) {
      setState(() {
        _tabIndex = _tabController.index;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView(
        children: <Widget>[
          Container(
            height: 120,
            child: Center(
              child: Text('something on top'),
            ),
          ),

          TabBar(
            controller: _tabController,
            labelColor: Colors.redAccent,
            isScrollable: true,
            tabs: myTabs,
          ),
          Center(
            child: [
              Text('second tab'),
              Column(
                children: List.generate(20, (index) => Text('line: $index')).toList(),
              ),
              Text('third tab')
            ][_tabIndex],
          ),
          Container(child: Text('another component')),
        ],
      ),
    );
  }
}

【讨论】:

  • 好像少了幻灯片动画吧?你也可以水平滚动吗?
【解决方案2】:

当前作为https://github.com/flutter/flutter/projects/3 的一部分登陆的重构滚动“sliver”代码将使这变得非常容易。

SliverList https://docs.flutter.io/flutter/widgets/SliverList-class.html 旨在实现这种组合,并应在大约两周内准备好进行一般使用。

【讨论】:

  • 你能举个例子,使用 SilverList 来构造这样的视图。我试过这个gist,但它仍然需要一个固定高度的容器来包装TabBarView。任何帮助,将不胜感激。谢谢
猜你喜欢
  • 2018-07-28
  • 2019-03-24
  • 2011-02-14
  • 2019-09-17
  • 1970-01-01
  • 2011-02-14
  • 1970-01-01
  • 2021-05-22
  • 2021-04-30
相关资源
最近更新 更多