FlexibleSpaceBar 解析之background

简介: FlexibleSpaceBar 解析之background
FlexibleSpaceBar

Stack

Height

background

Code
   
   ///_FlexibleSpaceBarState
   ///返回了一个ClipRect
   ClipRect(child: Stack(children: children))
   
   ///background的高度
    children.add(Positioned(
            top: topPadding,
            left: 0.0,
            right: 0.0,
            height: height,
            child: _FlexibleSpaceHeaderOpacity(
              // IOS is relying on this semantics node to correctly traverse
              // through the app bar when it is collapsed.
              alwaysIncludeSemantics: true,
              opacity: opacity,
              child: widget.background,
            ),
          ));


            ///获取高度
       double height = settings.maxExtent;

          // StretchMode.zoomBackground
          if (widget.stretchModes.contains(StretchMode.zoomBackground) &&
            constraints.maxHeight > height) {
            height = constraints.maxHeight;
          }
        ///_SliverAppBarDelegate
      double get maxExtent => math.max(topPadding + (expandedHeight ?? (toolbarHeight ?? kToolbarHeight) + _bottomHeight), minExtent);

background 高度

SliverAppBar的expandedHeight会强制FlexibleSpaceBar的background的高度一致,如果直接获取子组件的高度就会得到expandedHeight的值,

如果想要获取到真实内容的高度,需要套一个Column或者其他Widget,然后通过Key获取高度,代码如下


import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

class FlexibleSpaceBarBackground extends StatefulWidget {
  final Function(double) setHeight;
  final Widget child;

  const FlexibleSpaceBarBackground(
      {super.key, required this.setHeight, required this.child});

  @override
  State<FlexibleSpaceBarBackground> createState() =>
      _FlexibleSpaceBarBackgroundState();
}

class _FlexibleSpaceBarBackgroundState
    extends State<FlexibleSpaceBarBackground> {
  final heightKey = GlobalKey();

  @override
  void initState() {
    super.initState();
    SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
      final heightRO = heightKey.currentContext?.findRenderObject();
      if (heightRO != null && heightRO is RenderBox) {
        widget.setHeight(heightRO.size.height);
        print('heightRO.size.height=${heightRO.size.height}');
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Container(
          key: heightKey,
          child: widget.child,
        ),
        const Spacer()
      ],
    );
  }
}
class HeaderDetail extends StatelessWidget {
  
  const HeaderDetail(
      {super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
      Text('================'),
        const Gap.v(10),
        Text('================'),
        const Gap.v(10),
      ],
    );
  }
}




SliverAppBar(
  ///此属性为折叠后的高度,默认为toolbarHeight
  ///"collapsedHeight"参数必须大于或等于[toolbarHeight]
    collapsedHeight: 0,
    toolbarHeight: 0,
    backgroundColor: Colors.transparent,
    pinned: true,
    expandedHeight: height.value,
    flexibleSpace: FlexibleSpaceBar(
      background: FlexibleSpaceBarBackground(                    
        doResult: setHeight,
        child:HeaderDetail(),
      ),
    ),
    bottom: PreferredSize(
      preferredSize: Size.fromHeight(42),
      child: Container(
        color: Colors.white,
        child: TabBar(
          tabs: items.value,
          controller: tabC,
          unselectedLabelColor: Colors.grey,
          indicator:
          context.extensions.underlineTabIndicator,
        ),
      ),
    ),
  )
  
    ///设置高度
   final setHeight = useCallback((double height_) {
      height.value = height_ + 42;
    }, []);

判断是否折叠 constraints.biggest.height

LayoutBuilder(
   builder: (context,constraints) {
     ///此属性是appbar的高度,如果等于42说明已折叠 因为bottom的高度是42
     constraints.biggest.height.log();
     return FlexibleSpaceBar(
       background: FlexibleSpaceBarBackground(
         setHeight: setHeight,
         child: HeaderProductDetail(),
       ),
     );
   }
 )

相关文章
Flutter Getx 路由 until 方法帮助你跳转指定路由
不少同学都会问我,这样一个场景,当我点击商品列表,进入商品页,点击购买,支付成功后,想返回商品页,或者我的中心的订单列表。怎么做,这中间跨度了 n 个路由。 我不只一次的推荐 GetX 的 until 方法,和 offNamedUntil 方法。 我写了个 demo 今天我们就一起来看下这两个方法如何使用。
2132 0
Flutter Getx 路由 until 方法帮助你跳转指定路由
Flutter 分享功能之Share
Flutter 分享功能之Share
2570 0
Flutter 分享功能之Share
|
Rust 安全 算法
Go标准库的新 math/rand
Go标准库的新 math/rand
|
7月前
|
存储 运维 监控
2025年4月深度评测:10款最值得部署的网络监控软件
真正卓越的运维不仅仅是对当前问题的解决,更在于对未来的预测和防范。 OpManager 的预测报表功能可以为用户提供有关未来存储需求增长方式的直观展示,帮助用户进行基于需求的容量规划,从而避免成本浪费。
335 0
|
安全 Shell 测试技术
Android 11 来袭,一起来看看怎么适配(二)
Android 11 来袭,一起来看看怎么适配
|
监控 Java 大数据
【Java内存管理新突破】JDK 22:细粒度内存管理API,精准控制每一块内存!
【9月更文挑战第9天】虽然目前JDK 22的确切内容尚未公布,但我们可以根据Java语言的发展趋势和社区的需求,预测细粒度内存管理API可能成为未来Java内存管理领域的新突破。这套API将为开发者提供前所未有的内存控制能力,助力Java应用在更多领域发挥更大作用。我们期待JDK 22的发布,期待Java语言在内存管理领域的持续创新和发展。
|
编解码 Dart 网络协议
Flutter如何玩转超低延迟RTSP/RTMP播放,跨平台视频流体验大升级,让你的应用秒变直播神器!
【9月更文挑战第3天】Flutter作为谷歌推出的跨平台移动UI框架,凭借高性能和丰富的生态系统广受好评。本文详细介绍如何在Flutter应用中实现低延迟的跨平台RTSP/RTMP播放,并提供具体示例代码。首先介绍了如何使用`flutter_vlc_player`播放RTSP流,然后讨论了优化视频播放以降低延迟的方法,包括调整播放器配置等。通过选用合适的播放器插件并进行优化,Flutter可在视频流播放领域提供卓越的用户体验。随着生态的发展,Flutter有望成为视频流媒体开发的首选框架。
1479 6
|
前端开发 Python
在vscode中如何配置Django项目
在vscode中如何配置Django项目
362 0
|
iOS开发
如何找到Xcode中下载的Provisioning Profile文件
如何找到Xcode中下载的Provisioning Profile文件
1810 1
|
机器学习/深度学习 人工智能 运维
智能化运维:AI与机器学习在IT管理中的应用
【7月更文挑战第10天】本文深入探讨了人工智能和机器学习如何革新传统的IT运维领域。文章首先界定了智能化运维的概念,随后分析了AI技术在故障预测、自动化处理和安全监控方面的应用实例,并讨论了实施智能化运维时面临的挑战及其克服策略。最终,文章展望了智能化运维的未来趋势,强调了持续学习和适应新技术的重要性。