关于Flutter中CustomScrollView+SliverAppBar+SliverList
需求背景:
图1为正常状态下,滑动状态下为图二。 对于iOS或者android项目开发老哥来说这种实现已经是很熟练了。但是用flutter来说。一开始还是一脸懵逼。后来查了查资料。总结下,当前的需求可通过 CustomScrollView+SliverAppBar+SliverList实现。
CustomScrollView
首先看下CustomScrollView官方提供的代码:
Key? key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController? controller,
bool? primary,
ScrollPhysics? physics,
ScrollBehavior? scrollBehavior,
bool shrinkWrap = false,
Key? center,
double anchor = 0.0,
double? cacheExtent,
this.slivers = const <Widget>[],
int? semanticChildCount,
DragStartBehavior dragStartBehavior = DragStartBehavior.start,
ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
String? restorationId,
Clip clipBehavior = Clip.hardEdge,
参数中,设置的一些参数,从文字的意思或者猜测,基本上都能了解个差不多。 这里面有个 slivers一个Widget的数组。应该就是CustomScrollView的字试图部分
slivers
让我们在看下## slivers下面可以放哪些Widget呢?
1、SliverAppBar
this.leading,
this.automaticallyImplyLeading = true,
this.title,
this.actions,
this.flexibleSpace,
this.bottom,
this.elevation,
this.shadowColor,
this.forceElevated = false,
this.backgroundColor,
this.foregroundColor,
this.textTheme,
this.primary = true,
this.centerTitle,
this.excludeHeaderSemantics = false,
this.titleSpacing,
this.collapsedHeight,
this.expandedHeight,
this.floating = false,
this.pinned = false,
this.snap = false,
this.stretch = false,
this.stretchTriggerOffset = 100.0,
this.onStretchTrigger,
this.shape,
this.toolbarHeight = kToolbarHeight,
this.leadingWidth,
this.backwardsCompatibility,
this.toolbarTextStyle,
this.titleTextStyle,
this.systemOverlayStyle,
对应的属性相应较多一点。按照当前需求:
Widget build(BuildContext context) {
super.build(context);
ScreenUtil.init(
BoxConstraints(
maxWidth: MediaQuery.of(context).size.width,
maxHeight: MediaQuery.of(context).size.height),
designSize: Size(375, 667),
);
return Scaffold(
body: Stack(
children: [
CustomScrollView(
controller: _scrollController,
slivers: [
SliverAppBar(
title: Opacity(opacity: opacity, child: Text('快车道货运')),
expandedHeight: 100.0,
floating: true,
pinned: true,
actions: [
Opacity(
opacity: opacity,
child:
IconButton(onPressed: () {}, icon: Icon(Icons.add))),
Opacity(
opacity: opacity,
child: IconButton(
onPressed: () {}, icon: Icon(Icons.search)))
],
backgroundColor: AppColors.nav,
flexibleSpace: FlexibleSpaceBar(
centerTitle: false,
background: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [AppColors.nav, AppColors.nav1])),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Container(
alignment: Alignment.center,
child: Text('自定义按钮'),
)),
Expanded(
child: Container(
alignment: Alignment.center,
child: Text('自定义按钮'),
))
],
),
)),
),
SliverList(
delegate:
SliverChildBuilderDelegate(_homeCell, childCount: 50)),
],
),
],
),
);
}
opacity为通过监_scrollController听滑动控制距离 是否显示按钮 当前需求 滑动之后显示的靠左显示的标题 右边两个icon。SliverAppBar提供的方法完全可以实现了。
如滑动收缩后的导航栏实现不了,因为导航栏滑动固定的,可以做一个自定义的widget固定在上面。通过滑动的幅度,显示还是隐藏
floatingActionButton: 自定义widget,
floatingActionButtonLocation: FloatingActionButtonLocation.centerTop,//位置
实现效果如下:
根据需求 SliverAppBar 与 SliverList 中间有和头部试图。 要SliverList上面增加个header 根据文档里 发现了提供了 SliverPersistentHeader
SliverPersistentHeader(
delegate: _homeSliverPersistentHeaderDelegate(),
pinned: true,//是否固定
floating: false,
),
//SliverPersistentHeaderDelegate 自定义 效果和SliverAppBar差不多
class _homeSliverPersistentHeaderDelegate
extends SliverPersistentHeaderDelegate {
final double _minExtent = 100;//滑动最小高度
final double _maxExtent = 100;//最大高度
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return Container(
child: 自定义试图,
);
}
实现效果图:
当前问题: 滑动之后的appBar的颜色渐变怎么实现?