FlexibleSpaceBar
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(), ), ); } )