Flutter CustomScrollView支持自定义内部item的滚动控件,还支持头部带滑动缩放的SliverAppBar。需要注意如果CustomScrollView的item嵌套了和他滚动方向相同的控件这不能正常滑动,因为CustomScrollView内部只会维护一个Scrollable而会子控件会优先消费就会出现只有子控件能滚动的问题。如果有这种需求的场景建议使用NestedScrollView,可以自定义Sliver
///
/// CustomScrollView 滚动
class CustomScrollViewApp extends StatelessWidget {
const CustomScrollViewApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => _CustomScrollViewPage();
}
class _CustomScrollViewPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => _CustomScrollViewState();
}
class _CustomScrollViewState extends State<_CustomScrollViewPage> {
var controller = ScrollController();
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) => MaterialApp(
home: Scaffold(
bottomNavigationBar: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
child: const Text('当前滑动'),
onPressed: () {
print('滑动offset=${controller.offset}');
print('滑动position=${controller.positions.length}');
},
),
const SizedBox(
width: 20,
),
ElevatedButton(
child: const Text('滑动到最上'),
onPressed: () {
//设置带动画滑动到指定位置
controller.animateTo(0,
duration: const Duration(milliseconds: 500), //动画持续时长
curve: Curves.easeInCubic); //以哪种动画的方式滑动
},
),
],
),
body: CustomScrollView(
controller: controller,
slivers: <Widget>[
//顶部的标题内容,添加[expandedHeight]属性后支持列表滑动缩放
SliverAppBar(
//缩放到最小时是否需要悬停到顶部
pinned: true,
//缩放的最大高度,必须要设置了才会有缩放的效果
expandedHeight: 250.0,
flexibleSpace: FlexibleSpaceBar(
//标题是否居中
centerTitle: true,
//标题padding
titlePadding: const EdgeInsets.all(10),
//背景缩放模式 CollapseMode.pin//背景跟着一起往上滚,CollapseMode.none//背景不动
collapseMode: CollapseMode.parallax,
background: Image.network(
'https://tse4-mm.cn.bing.net/th/id/OIP-C.E-4fLhTRC4aG-RvqTAO_dwHaE8?w=251&h=180&c=7&r=0&o=5&dpr=2&pid=1.7',
fit: BoxFit.cover,
),
title: const Text('万物生长'),
),
),
//卡片样式的item,意思就是一行可以排列多个
SliverGrid(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
//单个item最大宽度,一行不排列不够就换到下一行
maxCrossAxisExtent: 200.0,
//横轴的间距
mainAxisSpacing: 10.0,
//数轴的间距
crossAxisSpacing: 10.0,
//item宽高比列
childAspectRatio: 4,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
alignment: Alignment.center,
color: Colors.teal[100 * (index % 9)],
child: Text(
'Grid Item $index',
style: const TextStyle(fontSize: 15),
),
);
},
//item条数
childCount: 20,
),
),
//自定义item
SliverToBoxAdapter(
child: SizedBox(
height: 300,
child: PageView(
children: [
Stack(
alignment: Alignment.bottomCenter,
children: [
Image.network(
'https://tse1-mm.cn.bing.net/th/id/OIP-C.d0NDc_VMqt8RrQXWzu7zvQHaE7?w=295&h=197&c=7&r=0&o=5&dpr=2&pid=1.7',
fit: BoxFit.cover,
),
const Text(
'这是第一个',
style: TextStyle(fontSize: 30, color: Colors.white),
),
],
),
Image.network(
'https://tse2-mm.cn.bing.net/th/id/OIP-C.zsnUfFGwV6T3G9ENQpu2BQHaL3?w=122&h=197&c=7&r=0&o=5&dpr=2&pid=1.7',
fit: BoxFit.cover,
),
Image.network(
'https://tse4-mm.cn.bing.net/th/id/OIP-C.BEBN8oSQVet6K2qUFkIMYgHaET?w=294&h=180&c=7&r=0&o=5&dpr=2&pid=1.7',
fit: BoxFit.cover,
),
Image.network(
'https://tse2-mm.cn.bing.net/th/id/OIP-C.QnTEUd-GHD5B2cTgalo4-QHaEK?w=333&h=187&c=7&r=0&o=5&dpr=2&pid=1.7',
fit: BoxFit.cover,
),
],
),
)),
//包裹可以设置间距
SliverPadding(
padding: const EdgeInsets.all(20),
sliver: //固定单条item
SliverFixedExtentList(
//item高度
itemExtent: 50.0,
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
alignment: Alignment.center,
color: Colors.lightBlue[100 * (index % 9)],
child: Text('List Item $index'),
);
//item条数
}, childCount: 20),
),
),
//单条一行
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
height: 40,
alignment: Alignment.center,
color: Colors.green[100 * (index % 9)],
child: Text('Sliver List Item $index'),
);
//item条数
}, childCount: 20)),
],
),
));
}
版权声明:本文为qq_30005223原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。