如何在带有 Flutter 的可滚动视图中拥有具有可变高度内容的 TabView?
Posted
技术标签:
【中文标题】如何在带有 Flutter 的可滚动视图中拥有具有可变高度内容的 TabView?【英文标题】:How can I have a TabView with variable height content within a Scrollable View with Flutter? 【发布时间】:2017-06-16 01:28:38 【问题描述】:我有一个 TabBar 和 TabBarView 嵌套在 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: ...
关于如何最好地解决这个问题的任何想法?
【问题讨论】:
@SethLadd 不鼓励在标题中重复标签 ;-) 显然目前正在努力重构滚动行为以帮助实现这一点,您可以在此处关注:github.com/flutter/flutter/projects/3 marcinszalek.pl/flutter/flutter-tabbar-example-weighttracker-5 【参考方案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
。任何帮助,将不胜感激。谢谢以上是关于如何在带有 Flutter 的可滚动视图中拥有具有可变高度内容的 TabView?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Swift IOS 中创建具有多个堆栈视图的可滚动堆栈视图
带有空 UIScrollView 的可滚动内容大小歧义(XCode 6)
如何在 Qt C++ 应用程序中显示具有大量小部件的可滚动列表作为项目?