Fluttter CustomScrollView 滑动冲突
1.CustomScrollView简介
CustomScrollView是使用Sliver组件创建自定义滚动效果的滚动组件。使用场景:
1.ListView和GridView相互嵌套场景,ListView嵌套GridView时,需要给GridView指定高度,但我们希望高度随内容而变化(不指定),ListView和GridView使用同一个滚动效果。
2.一个页面顶部是AppBar,然后是GridView,最后是ListView,这3个区域以整体来滚动,AppBar具有吸顶效果。
CustomScrollView就像一个粘合剂,将多个组件粘合在一起,具统一的滚动效果。
Sliver家族
Sliver系列组件有很多,比如SliverList、SliverGrid、SliverFixedExtentList、SliverPadding、SliverAppBar等。
2.属性
scrollDirection | 方向,默认Axis.vertical(垂直滚动) |
---|---|
reverse | 数据方向,默认false(正序) |
controller | 控制器 |
primary | |
physics | |
shrinkWrap | 默认false |
anchor | 默认0.0 |
cacheExtent | |
slivers | const [] |
semanticChildCount | |
dragStartBehavior | 默认DragStartBehavior.start |
注意:
scrollDirection滚动方向,分为垂直和水平方向。
reverse参数表示反转滚动方向,并不是垂直转为水平,而是垂直方向滚动时,默认向下滚动,reverse设置false,滚动方向改为向上,同理水平滚动改为水平向左。
primary设置为true时,不能设置controller,因为primarytrue时,controller使用PrimaryScrollController,这种机制带来的好处是父组件可以控制子树中可滚动组件的滚动行为,例如,Scaffold正是使用这种机制在iOS中实现了点击导航栏回到顶部的功能。
controller为滚动控制器,可以监听滚到的位置,设置滚动的位置等,用法如下:
3.使用场景 作为联合剂,GridView+ListView连锁滑动
在实际业务场景中经常见到这样的布局,顶部是网格布局(GridView),然后是列表布局(ListView),滚动的时候做为一个整体,此场景是无法使用GridView+ListView来实现的,而是需要使用CustomScrollView+SliverGrid+SliverList来实现,实现代码如下:
import 'package:flutter/material.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<CustomScrollViewDemo> {
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return CustomScrollView(
slivers: <Widget>[
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),
)
],
);
}
}
4. 顶部是AppBar场景 实现Android AppBarLayout+CollapsingToolbarLayout的效果
·实际项目中页面顶部是AppBar,然后是GridView,最后是ListView,这3个区域以整体来滚动,AppBar具有吸顶效果,此效果也是我们经常遇到的,用法如下:
import 'package:flutter/material.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<CustomScrollViewDemo> {
var _scrollController = ScrollController();
@override
void initState() {
super.initState();
_scrollController.addListener(() {
print('我的${_scrollController.position}');
});
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return CustomScrollView(
controller:_scrollController,
slivers: <Widget>[
SliverAppBar(
pinned: true,
expandedHeight: 200,
floating: true,
flexibleSpace: FlexibleSpaceBar(
title: Text('简约生活'),
background: Image.network(
'https://www.itying.com/images/flutter/1.png',
fit: BoxFit.cover,
),
),
),
SliverGrid.count(
crossAxisCount: 3,
children: List.generate(6, (index) {
return Container(
color: Colors.primaries[index % Colors.primaries.length],
alignment: Alignment.center,
child: Text(
'$index',
style: TextStyle(color: Colors.white, fontSize: 20),
),
);
}, growable: true)
.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),
)
],
);
}
}