为什么会有Sliver家族,主要是结合CustomScrollView,统一滑动方式,CustomScrollView中slivers只能是Sliver家族,其他widget会报错
SliverAppBar 是一个可伸缩的头部,可以实现上拉收起,下拉展开效果
属性:
expandedHeight: 最大扩展高度
flexibleSpace: 扩展内容区域
floating: 为true则在滚动时优先滚动,有下拉动作先appbar后flexibleSpace,反之亦然
snap: 为true时没有变化,正在查证
pinned:为true则appbar不消失,在下拉时会多划出一段距离SliverAppBar才开始滚动
SliverPersistentHeader有点类似SliverAppBar,同样可以收起和展开,可以放置到slivers任何一个位置,如下例:
属性:
floating: 为 true 时,与SliverAppBar用法一致
pinned:与SliverAppBar用法一致,且与floating不能同时为true
delegate: 构建一个SliverPersistentHeader需要传入一个delegate,这个delegate是SliverPersistentHeaderDelegate类型的,而SliverPersistentHeaderDelegate是一个abstract类,我们不能直接new一个SliverPersistentHeaderDelegate出来,因此,我们需要自定义一个delegate来实现SliverPersistentHeaderDelegate类
由于SliverPersistentHeader为abstract抽象类
maxExtent表示header完全展开时的高度,minExtent表示header在收起时的最小高度
import 'package:flutter/material.dart';
import 'dart:math';
class SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
SliverAppBarDelegate({
@required this.minHeight,
@required this.maxHeight,
@required this.child,
});
final double minHeight;
final double maxHeight;
final Widget child;
@override
double get minExtent => minHeight;
@override
double get maxExtent => max(maxHeight, minHeight);
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return new SizedBox.expand(child: child);
}
@override
bool shouldRebuild(SliverAppBarDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}
import 'package:flutter/material.dart';
import 'SliverAppBarDelegate.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// home: CustomScrollViewDemo(),
home: Scaffold(
body: CustomScrollViewDemo(),
),
);
}
}
class CustomScrollViewDemo extends StatefulWidget {
CustomScrollViewDemo({Key key}) : super(key: key);
@override
_CustomScrollViewDemoState createState() {
return _CustomScrollViewDemoState();
}
}
class _CustomScrollViewDemoState extends State {
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return CustomScrollView(
slivers: [
SliverPersistentHeader(
floating: false,//floating 与pinned 不能同时为true
pinned: true,
delegate: SliverAppBarDelegate(
minHeight: 50.0,
maxHeight: 200.0,
child: Container(
color: Colors.lightBlue,
child: Center(
child: Text('SliverAppBarDelegate'),
),
)
),
),
SliverGrid.count(crossAxisCount: 2, children: List.generate(4, (index) {
return Container(
color: Colors.primaries[index % Colors.primaries.length],
alignment: Alignment.center,
child: Text(
'$index', style: TextStyle(color: Colors.white, fontSize: 20),),
);
}).toList(),),
SliverList(
delegate: SliverChildBuilderDelegate((content, index) {
return Container(
height: 85,
alignment: Alignment.center,
color: Colors.primaries[index % Colors.primaries.length],
child: Text(
'$index', style: TextStyle(color: Colors.white, fontSize: 20),),
);
}, childCount: 25),
)
],
);
}
}
SliverFixedExtentList与SliverList类似,唯一区别是SliverFixedExtentList可以设置固定高度。
这个控件很有用,可以实现Header,而不是伸缩的Header,可以随着CustomScrollView滑动
SliverToBoxAdapter(
child: Container(
width: double.infinity,
height: 200,
color: Colors.red,
),
),
SliverPadding可以设置padding,子widget为sliver
SliverPadding(
padding: EdgeInsets.all(10.0),
sliver: SliverList(
delegate: SliverChildListDelegate([
ListTile(title: Text('01'),),
ListTile(title: Text('02'),),
ListTile(title: Text('03'),),
]),
),
)
完整代码
import 'package:flutter/material.dart';
import 'SliverAppBarDelegate.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// home: CustomScrollViewDemo(),
home: Scaffold(
body: CustomScrollViewDemo(),
),
);
}
}
class CustomScrollViewDemo extends StatefulWidget {
CustomScrollViewDemo({Key key}) : super(key: key);
@override
_CustomScrollViewDemoState createState() {
return _CustomScrollViewDemoState();
}
}
class _CustomScrollViewDemoState extends State {
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Container(
width: double.infinity,
height: 200,
color: Colors.red,
),
),
SliverPersistentHeader(
floating: false,//floating 与pinned 不能同时为true
pinned: true,
delegate: SliverAppBarDelegate(
minHeight: 50.0,
maxHeight: 200.0,
child: Container(
color: Colors.lightBlue,
child: Center(
child: Text('SliverAppBarDelegate'),
),
)
),
),
SliverGrid.count(crossAxisCount: 2, children: List.generate(4, (index) {
return Container(
color: Colors.primaries[index % Colors.primaries.length],
alignment: Alignment.center,
child: Text(
'$index', style: TextStyle(color: Colors.white, fontSize: 20),),
);
}).toList(),),
SliverList(
delegate: SliverChildBuilderDelegate((content, index) {
return Container(
height: 85,
alignment: Alignment.center,
color: Colors.primaries[index % Colors.primaries.length],
child: Text(
'$index', style: TextStyle(color: Colors.white, fontSize: 20),),
);
}, childCount: 25),
),
SliverPadding(
padding: EdgeInsets.all(10.0),
sliver: SliverList(
delegate: SliverChildListDelegate([
ListTile(title: Text('01'),),
ListTile(title: Text('02'),),
ListTile(title: Text('03'),),
]),
),
)
],
);
}
}