Makes FlexibleSpaceBarSettings public (#23803) * Makes FlexibleSpaceSettingsPublic and adds a test
diff --git a/packages/flutter/lib/src/material/flexible_space_bar.dart b/packages/flutter/lib/src/material/flexible_space_bar.dart index 1f37b47..7ae83c1 100644 --- a/packages/flutter/lib/src/material/flexible_space_bar.dart +++ b/packages/flutter/lib/src/material/flexible_space_bar.dart
@@ -75,6 +75,19 @@ /// to the [FlexibleSpaceBar]. /// /// Used by [Scaffold] and [SliverAppBar]. + /// + /// `toolbarOpacity` affects how transparent the text within the toolbar + /// appears. `minExtent` sets the minimum height of the resulting + /// [FlexibleSpaceBar] when fully collapsed. `maxExtent` sets the maximum + /// height of the resulting [FlexibleSpaceBar] when fully expanded. + /// `currentExtent` sets the scale of the [FlexibleSpaceBar.background] and + /// [FlexibleSpaceBar.title] widgets of [FlexibleSpaceBar] upon + /// initialization. + /// + /// See also: + /// + /// * [FlexibleSpaceBarSettings] which creates a settings object that can be + /// used to specify these settings to a [FlexibleSpaceBar]. static Widget createSettings({ double toolbarOpacity, double minExtent, @@ -83,7 +96,7 @@ @required Widget child, }) { assert(currentExtent != null); - return _FlexibleSpaceBarSettings( + return FlexibleSpaceBarSettings( toolbarOpacity: toolbarOpacity ?? 1.0, minExtent: minExtent ?? currentExtent, maxExtent: maxExtent ?? currentExtent, @@ -125,7 +138,7 @@ return null; } - double _getCollapsePadding(double t, _FlexibleSpaceBarSettings settings) { + double _getCollapsePadding(double t, FlexibleSpaceBarSettings settings) { switch (widget.collapseMode) { case CollapseMode.pin: return -(settings.maxExtent - settings.currentExtent); @@ -140,7 +153,7 @@ @override Widget build(BuildContext context) { - final _FlexibleSpaceBarSettings settings = context.inheritFromWidgetOfExactType(_FlexibleSpaceBarSettings); + final FlexibleSpaceBarSettings settings = context.inheritFromWidgetOfExactType(FlexibleSpaceBarSettings); assert(settings != null, 'A FlexibleSpaceBar must be wrapped in the widget returned by FlexibleSpaceBar.createSettings().'); final List<Widget> children = <Widget>[]; @@ -221,23 +234,42 @@ } } -class _FlexibleSpaceBarSettings extends InheritedWidget { - const _FlexibleSpaceBarSettings({ +/// Provides sizing and opacity information to a [FlexibleSpaceBar]. +/// +/// See also: +/// +/// * [FlexibleSpaceBar] which creates a flexible space bar. +class FlexibleSpaceBarSettings extends InheritedWidget { + /// Creates a Flexible Space Bar Settings widget. + /// + /// Used by [Scaffold] and [SliverAppBar]. [child] must have a + /// [FlexibleSpaceBar] widget in its tree for the settings to take affect. + const FlexibleSpaceBarSettings({ Key key, this.toolbarOpacity, this.minExtent, this.maxExtent, - this.currentExtent, - Widget child, - }) : super(key: key, child: child); + @required this.currentExtent, + @required Widget child, + }) : assert(currentExtent != null), + super(key: key, child: child); + /// Affects how transparent the text within the toolbar appears. final double toolbarOpacity; + + /// Minimum height of the resulting [FlexibleSpaceBar] when fully collapsed. final double minExtent; + + /// Maximum height of the resulting [FlexibleSpaceBar] when fully expanded. final double maxExtent; + + /// If the [FlexibleSpaceBar.title] or the [FlexibleSpaceBar.background] is + /// not null, then this value is used to calculate the relative scale of + /// these elements upon initialization. final double currentExtent; @override - bool updateShouldNotify(_FlexibleSpaceBarSettings oldWidget) { + bool updateShouldNotify(FlexibleSpaceBarSettings oldWidget) { return toolbarOpacity != oldWidget.toolbarOpacity || minExtent != oldWidget.minExtent || maxExtent != oldWidget.maxExtent
diff --git a/packages/flutter/test/material/flexible_space_bar_test.dart b/packages/flutter/test/material/flexible_space_bar_test.dart index 1c04e39..e3c7c13 100644 --- a/packages/flutter/test/material/flexible_space_bar_test.dart +++ b/packages/flutter/test/material/flexible_space_bar_test.dart
@@ -46,4 +46,95 @@ expect(center.dx, greaterThan(400.0 - size.width / 2.0)); expect(center.dx, lessThan(400.0 + size.width / 2.0)); }); + + testWidgets('FlexibleSpaceBarSettings provides settings to a FlexibleSpaceBar', (WidgetTester tester) async { + const double minExtent = 100.0; + const double initExtent = 200.0; + const double maxExtent = 300.0; + const double alpha = 0.5; + + final FlexibleSpaceBarSettings customSettings = FlexibleSpaceBar.createSettings( + currentExtent: initExtent, + minExtent: minExtent, + maxExtent: maxExtent, + toolbarOpacity: alpha, + child: AppBar( + flexibleSpace: const FlexibleSpaceBar( + title: Text('title'), + background: Text('X2'), + collapseMode: CollapseMode.pin, + ), + ), + ); + + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: CustomScrollView( + primary: true, + slivers: <Widget>[ + SliverPersistentHeader( + floating: true, + pinned: true, + delegate: TestDelegate(settings: customSettings), + ), + SliverToBoxAdapter( + child: Container( + height: 1200.0, + color: Colors.orange[400], + ), + ), + ], + ), + ), + ), + ); + + final RenderBox clipRect = tester.renderObject(find.byType(ClipRect).first); + final Transform transform = tester.firstWidget(find.byType(Transform)); + + // The current (200) is half way between the min (100) and max (300) and the + // lerp values used to calculate the scale are 1 and 1.5, so we check for 1.25. + expect(transform.transform.getMaxScaleOnAxis(), 1.25); + + // The space bar rect always starts fully expanded. + expect(clipRect.size.height, maxExtent); + + final Element actionTextBox = tester.element(find.text('title')); + final Text textWidget = actionTextBox.widget; + final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(actionTextBox); + + TextStyle effectiveStyle = textWidget.style; + effectiveStyle = defaultTextStyle.style.merge(textWidget.style); + expect(effectiveStyle.color.alpha, 128); // Which is alpha of .5 + + // We drag up to fully collapse the space bar. + await tester.drag(find.byType(Container).first, const Offset(0, -400.0)); + await tester.pumpAndSettle(); + + expect(clipRect.size.height, minExtent); + }); +} + +class TestDelegate extends SliverPersistentHeaderDelegate { + + const TestDelegate({ + this.settings, + }); + + final FlexibleSpaceBarSettings settings; + + @override + double get maxExtent => settings.maxExtent; + + @override + double get minExtent => settings.minExtent; + + @override + Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { + return settings; + } + + @override + bool shouldRebuild(TestDelegate oldDelegate) => false; }