--- 编辑 1 --
好的,所以我快速为你整理了一些东西。我关注了这篇文章(由 Flutter 的主要开发者之一 Emily Fortuna 撰写)以更好地理解 Slivers。
介质:Slivers, Demystified
但后来发现这个 Youtube 视频基本上使用了你的代码,所以我选择了这个,而不是试图找出关于 Slivers 的每一个小细节。
Youtube:在 Dart 的 Flutter 框架中使用 Tab 和 Scroll 控制器以及 NestedScrollView
事实证明,您的代码走在了正确的轨道上。您可以SliverAppBar
在其中使用NestedScrollView
(我上次尝试时不是这种情况),但我做了一些更改。我将在我的代码之后解释:
import 'package:flutter/material.dart';
import 'dart:math';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin /*<-- This is for the controllers*/ {
TabController _tabController; // To control switching tabs
ScrollController _scrollViewController; // To control scrolling
List<String> items = [];
List<Color> colors = [Colors.red, Colors.green, Colors.yellow, Colors.purple, Colors.blue, Colors.amber, Colors.cyan, Colors.pink];
Random random = new Random();
Color getRandomColor() {
return colors.elementAt(random.nextInt(colors.length));
}
@override
void initState() {
super.initState();
_tabController =TabController(vsync: this, length: 2);
_scrollViewController =ScrollController();
}
@override
void dispose() {
super.dispose();
_tabController.dispose();
_scrollViewController.dispose();
}
@override
Widget build(BuildContext context) {
// Init the items
for (var i = 0; i < 100; i++) {
items.add('Item $i');
}
return SafeArea(
child: NestedScrollView(
controller: _scrollViewController,
headerSliverBuilder: (BuildContext context, bool boxIsScrolled) {
return <Widget>[
SliverAppBar(
title: Text("WhatsApp using Flutter"),
floating: true,
pinned: false,
snap: true,
bottom: TabBar(
tabs: <Widget>[
Tab(
child: Text("Colors"),
),
Tab(
child: Text("Chats"),
),
],
controller: _tabController,
),
),
];
},
body: TabBarView(
controller: _tabController,
children: <Widget>[
ListView.builder(
itemBuilder: (BuildContext context, int index) {
Color color = getRandomColor();
return Container(
height: 150.0,
color: color,
child: Text(
"Row $index",
style: TextStyle(
color: Colors.white,
),
),
);
},
//physics: NeverScrollableScrollPhysics(), //This may come in handy if you have issues with scrolling in the future
),
ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Material(
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.blueGrey,
),
title: Text(
items.elementAt(index)
),
),
);
},
//physics: NeverScrollableScrollPhysics(),
),
],
),
),
);
}
}
好吧,等等解释。
用一个StatefulWidget
Flutter 中的大多数小部件都是有状态的,但这取决于具体情况。我认为在这种情况下更好,因为您使用的ListView
可能会随着用户添加或删除对话/聊天而改变。
SafeArea
因为这个小部件很棒。
在 Flutter Docs 上阅读它:SafeArea
控制器
我认为一开始这是个大问题,但也许是别的问题。但是,如果您在 Flutter 中处理自定义行为,您通常应该制作自己的控制器。所以我做了_tabController
and the _scrollViewController
(我不认为我得到了它们的所有功能,即跟踪标签之间的滚动位置,但它们适用于基础知识)。您用于TabBar
和 的选项卡控制器TabView
应该是相同的。
之前的Material
小部件ListTile
您可能迟早会发现这一点,但该ListTile
小部件是一个 Material 小部件,因此根据我最初尝试渲染它时得到的输出,它需要一个“Material 祖先小部件”。所以我为你省去了一点麻烦。我认为这是因为我没有使用Scaffold
. (当您使用没有 Material 祖先小部件的 Material 小部件时,请记住这一点)
希望这可以帮助您入门,如果您需要任何帮助,只需给我发消息或将我添加到您的 Github 存储库,我会看看我能做什么。
- - 原来的 - -
我也在 Reddit 上回答了你,希望你能很快看到这两个中的一个。
SliverAppBar 信息
您希望 SliverAppBar 具有的关键属性是:
floating: Whether the app bar should become visible as soon as the user scrolls towards the app bar.
pinned: Whether the app bar should remain visible at the start of the scroll view. (This is the one you are asking about)
snap: If snap and floating are true then the floating app bar will "snap" into view.
所有这些都来自Flutter SliverAppBar Docs。他们有很多动画示例,具有浮动、固定和捕捉的不同组合。
因此,对于您的以下内容应该有效:
SliverAppBar(
title: Text("Application"),
floating: true, // <--- this is required if you want the appbar to come back into view when you scroll up
pinned: false, // <--- this will make the appbar disappear on scrolling down
snap: true, // <--- this is required if you want the application bar to 'snap' when you scroll up (floating MUST be true as well)
bottom: new TabBar(
tabs: [ ... ], // <-- total of 2 tabs
),
),
带有 SliverAppBar 的 ScrollView
回答NestedScrollView
. 根据文档(与上述相同),aSliverAppBar
是:
一个与CustomScrollView
.
因此你不能使用 aNestedScrollView
你需要使用 a CustomScrollView
。这是Sliver
类的预期用途,但它们可以在NestedScrollView
查看文档中使用。