开源地址 github.com/7-bit-zhang…
pub地址 pub.dev/packages/sl…
实现效果图
、
、
实现思路
自定义sliver可以使用继承SliverPersistentHeaderDelegate进行自定义 在继承SliverPersistentHeaderDelegate后build中会有offset我们需要的坐标,通过坐标判断控制动画
继承: SliverPersistentHeaderDelegate
@override
double get minExtent => collapsedHeight + paddingTop;
@override
double get maxExtent => expandedHeight;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return true;
}
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
shrinkOffset滚动坐标
}
接下来我们可以根据最大展开大小和折叠大小进行逻辑控制
/// 更新状态栏 控制动画执行
void _updateStatusBarBrightness(shrinkOffset) {
if (shrinkOffset <= maxExtent / 2) {
animationController.reverse();
controller?.animateTo(0,
duration: durationAnimation, curve: curve ?? Curves.easeInOut);
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarBrightness: expandedBrightness,
statusBarIconBrightness: expandedBrightness,
));
} else if (shrinkOffset > maxExtent / 2 &&
shrinkOffset <= maxExtent - (minExtent)) {
controller?.animateTo(maxExtent - (minExtent),
duration: durationAnimation, curve: curve ?? Curves.easeInOut);
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarBrightness: collapsedBrightness,
statusBarIconBrightness: collapsedBrightness,
));
}
}
增加一个计算过渡动画的函数展开和关闭都可以使用
/// 计算透明度
double _makeStickyHeaderTitleAlpha(shrinkOffset) {
final double alpha =
(shrinkOffset / (maxExtent - minExtent) * 1).clamp(0, 1).toDouble();
return alpha;
}
最后拼接为一个简单的列子
SafeArea(
bottom: false,
child: SizedBox(
height: collapsedHeight,
child: Stack(children: [
Opacity(
opacity: 1 - _makeStickyHeaderTitleAlpha(shrinkOffset),
child: expandedWidget),
Opacity(
opacity: _makeStickyHeaderTitleAlpha(shrinkOffset),
child:
collapsedWidget ?? _defaultCollapsedWidget(shrinkOffset)),
])),
)