flutter实现自动吸附sliverAppbar,相信我你也可以变成光!

483 阅读1分钟

开源地址 github.com/7-bit-zhang…

pub地址 pub.dev/packages/sl…

实现效果图

_d45f3059896664c3ae0a44fdbc6924b0.gif_b8edde4965eead805269b6c0b59aa136.gif_c5f6da790c2fd1f3eb402edbe7c51ac8.gif

实现思路

自定义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)),
        ])),
  )