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;
 }