Flutter Sliver滚动组件
SliverList & SliverGrid
需要同时滚动ListView和GridView时可以使用SliverList和SliverGrid。
CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return Container(
height: 50,
color: Colors.primaries[index % Colors.primaries.length],
);
},
childCount: 5,
),
),
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 5,
mainAxisSpacing: 5,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
color: Colors.primaries[index % Colors.primaries.length],
);
},
childCount: 20,
),
),
],
)
SliverAppBar
pinned:是否固定在屏幕顶部。
expandedHeight:展开区域的高度。
flexibleSpace:展开取消显示内容。
CustomScrollView(
slivers: [
SliverAppBar(
pinned: true,
expandedHeight: 200,
flexibleSpace: FlexibleSpaceBar(
title: const Text("SliverAppBar"),
background: Image.asset("images/avatar.jpg", fit: BoxFit.cover),
),
),
SliverFixedExtentList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
alignment: Alignment.center,
color: Colors.primaries[index % Colors.primaries.length],
child: Text("$index"),
);
},
),
itemExtent: 50.0,
),
],
)
SliverPersistentHeader
SliverPersistentHeader组件可以控制滚动的最大高度和最小高度,类似SliverAppBar效果。
build:显示内容。
maxExtent & minExtent:滚动的高度范围。
shouldRebuild:是否需要更新。
CustomScrollView(
slivers: [
SliverPersistentHeader(
pinned: true,
delegate: MySliverPersistentHeaderDelegate(),
),
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 5,
mainAxisSpacing: 5,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
color: Colors.primaries[index % Colors.primaries.length],
);
},
),
),
],
)
class MySliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return Container(
color: Colors.blue,
alignment: Alignment.center,
child: Text(
"hello world",
style: TextStyle(color: Colors.white),
),
);
}
@override
double get maxExtent => 200;
@override
double get minExtent => 50;
@override
bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
return false;
}
}
SliverToBoxAdapter
CustomScrollView只能包含Sliver组件,如果需要使用普通组件可以使用SliverToBoxAdapter。
CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Container(
height: 200,
color: Colors.black26,
alignment: Alignment.center,
child: Text("hello world"),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
height: 60,
color: Colors.primaries[index % Colors.primaries.length],
);
},
childCount: 50,
),
),
],
)
CustomScrollView & NestedScrollView
CustomScrollView组件可以将多个组件组合在一起,具有统一的滚动效果,但是CustomScrollView只能嵌套Sliver系列的组件,如SliverList、SliverGrid、SliverPadding、SliverAppBar等。
NestedScrollView可以协调两个滚动组件滑动。NestedScrollView在逻辑上将可滚动组件分为header和body两部分,heade部分只能接收Sliver类型的组件,而body部分可以接收任意类型的组件。
NestedScrollView+SliverAppBar+SliverFixedExtentList+ListView
NestedScrollView(
//Sliver组件
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [
SliverAppBar(
title: const Text("嵌套ListView"),
pinned: true, //固定AppBar
forceElevated: true,
),
SliverFixedExtentList(
itemExtent: 50,
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return ListTile(title: Text("$index"));
},
childCount: 5,
),
),
];
},
//滚动组件
body: ListView.builder(
padding: const EdgeInsets.all(8),
physics: const ClampingScrollPhysics(), //需要
itemCount: 30,
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 50,
child: Center(child: Text("item $index")),
);
},
),
)
NestedScrollView+SliverAppBar+CustomScrollView
NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [
SliverAppBar(
floating: true,
snap: true,
expandedHeight: 200,
forceElevated: innerBoxIsScrolled,
flexibleSpace: FlexibleSpaceBar(
background: Image.asset(
"images/logo.png",
fit: BoxFit.cover,
),
),
),
];
},
body: CustomScrollView(
slivers: [buildSliverList(50)],
),
)
优化联动效果
SliverAppBar+CustomScrollView组合,当反向滑动时,SliverAppBar就会整体回到屏幕顶部,出现遮挡问题,为了解决该问题,可以用在header里用SliverOverlapAbsorber组件包裹SliverAppBar,body里Sliver列表最前面添加一个SliverOverlapInjector。
NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
sliver: SliverAppBar(
floating: true,
snap: true,
expandedHeight: 200,
forceElevated: innerBoxIsScrolled,
flexibleSpace: FlexibleSpaceBar(
background: Image.asset(
"images/logo.png",
fit: BoxFit.cover,
),
),
),
),
];
},
body: Builder(
builder: (BuildContext context) {
return CustomScrollView(
slivers: [
SliverOverlapInjector(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
),
buildSliverList(50),
],
);
},
),
)
NestedScrollView+TabBarView
class MyPageView extends StatefulWidget {
late List<String> tabs;
MyPageView({Key? key, required this.tabs}) : super(key: key);
@override
State<StatefulWidget> createState() {
return _MyPageViewState();
}
}
class _MyPageViewState extends State<MyPageView>
with SingleTickerProviderStateMixin {
late TabController _controller;
@override
void initState() {
super.initState();
_controller = TabController(length: widget.tabs.length, vsync: this);
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) {
return NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
sliver: SliverAppBar(
title: const Text("hi Flutter"),
floating: true,
snap: true,
forceElevated: innerBoxIsScrolled,
bottom: TabBar(
controller: _controller,
tabs: widget.tabs.map((e) => Tab(text: e)).toList(),
),
),
),
];
},
body: TabBarView(
controller: _controller,
children: widget.tabs.map((e) {
return Builder(builder: (BuildContext context) {
return CustomScrollView(
key: PageStorageKey(e),
slivers: [
SliverOverlapInjector(
handle:
NestedScrollView.sliverOverlapAbsorberHandleFor(context),
),
SliverPadding(
padding: const EdgeInsets.all(9),
sliver: buildSliverList(50),
),
],
);
});
}).toList(),
),
);
}
}
到此这篇关于Flutter Sliver滚动组件的文章就介绍到这了,更多相关Flutter 滚动组件内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!