Fix SliverAppBar title opacity and test all cases (#26021)

diff --git a/packages/flutter/lib/src/material/app_bar.dart b/packages/flutter/lib/src/material/app_bar.dart
index ed3fbad..c4f160e6 100644
--- a/packages/flutter/lib/src/material/app_bar.dart
+++ b/packages/flutter/lib/src/material/app_bar.dart
@@ -650,8 +650,22 @@
   @override
   Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
     final double visibleMainHeight = maxExtent - shrinkOffset - topPadding;
-    final double toolbarOpacity = pinned ? 1.0
-      : ((visibleMainHeight - _bottomHeight) / kToolbarHeight).clamp(0.0, 1.0);
+
+    // Truth table for `toolbarOpacity`:
+    // pinned | floating | bottom != null || opacity
+    // ----------------------------------------------
+    //    0   |    0     |        0       ||  fade
+    //    0   |    0     |        1       ||  fade
+    //    0   |    1     |        0       ||  fade
+    //    0   |    1     |        1       ||  fade
+    //    1   |    0     |        0       ||  1.0
+    //    1   |    0     |        1       ||  1.0
+    //    1   |    1     |        0       ||  1.0
+    //    1   |    1     |        1       ||  fade
+    final double toolbarOpacity = !pinned || (floating && bottom != null)
+      ? ((visibleMainHeight - _bottomHeight) / kToolbarHeight).clamp(0.0, 1.0)
+      : 1.0;
+
     final Widget appBar = FlexibleSpaceBar.createSettings(
       minExtent: minExtent,
       maxExtent: maxExtent,
diff --git a/packages/flutter/test/widgets/sliver_appbar_opacity.dart b/packages/flutter/test/widgets/sliver_appbar_opacity.dart
new file mode 100644
index 0000000..385a14d
--- /dev/null
+++ b/packages/flutter/test/widgets/sliver_appbar_opacity.dart
@@ -0,0 +1,205 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/rendering.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:flutter/material.dart';
+
+void main() {
+  testWidgets('!pinned && !floating && !bottom ==> fade opactiy', (WidgetTester tester) async {
+    final ScrollController controller = ScrollController();
+    await tester.pumpWidget(
+        _TestWidget(
+          pinned: false,
+          floating: false,
+          bottom: false,
+          controller: controller,
+        )
+    );
+
+    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
+    expect(render.text.style.color.opacity, 1.0);
+
+    controller.jumpTo(200.0);
+    await tester.pumpAndSettle();
+    expect(render.text.style.color.opacity, 0.0);
+  });
+
+  testWidgets('!pinned && !floating && bottom ==> fade opactiy', (WidgetTester tester) async {
+    final ScrollController controller = ScrollController();
+    await tester.pumpWidget(
+        _TestWidget(
+          pinned: false,
+          floating: false,
+          bottom: true,
+          controller: controller,
+        )
+    );
+
+    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
+    expect(render.text.style.color.opacity, 1.0);
+
+    controller.jumpTo(200.0);
+    await tester.pumpAndSettle();
+    expect(render.text.style.color.opacity, 0.0);
+  });
+
+  testWidgets('!pinned && floating && !bottom ==> fade opactiy', (WidgetTester tester) async {
+    final ScrollController controller = ScrollController();
+    await tester.pumpWidget(
+        _TestWidget(
+          pinned: false,
+          floating: true,
+          bottom: false,
+          controller: controller,
+        )
+    );
+
+    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
+    expect(render.text.style.color.opacity, 1.0);
+
+    controller.jumpTo(200.0);
+    await tester.pumpAndSettle();
+    expect(render.text.style.color.opacity, 0.0);
+  });
+
+  testWidgets('!pinned && floating && bottom ==> fade opactiy', (WidgetTester tester) async {
+    final ScrollController controller = ScrollController();
+    await tester.pumpWidget(
+        _TestWidget(
+          pinned: false,
+          floating: true,
+          bottom: true,
+          controller: controller,
+        )
+    );
+
+    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
+    expect(render.text.style.color.opacity, 1.0);
+
+    controller.jumpTo(200.0);
+    await tester.pumpAndSettle();
+    expect(render.text.style.color.opacity, 0.0);
+  });
+
+  testWidgets('pinned && !floating && !bottom ==> 1.0 opacity', (WidgetTester tester) async {
+    final ScrollController controller = ScrollController();
+    await tester.pumpWidget(
+        _TestWidget(
+          pinned: true,
+          floating: false,
+          bottom: false,
+          controller: controller,
+        )
+    );
+
+    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
+    expect(render.text.style.color.opacity, 1.0);
+
+    controller.jumpTo(200.0);
+    await tester.pumpAndSettle();
+    expect(render.text.style.color.opacity, 1.0);
+  });
+
+  testWidgets('pinned && !floating && bottom ==> 1.0 opacity', (WidgetTester tester) async {
+    final ScrollController controller = ScrollController();
+    await tester.pumpWidget(
+        _TestWidget(
+          pinned: true,
+          floating: false,
+          bottom: true,
+          controller: controller,
+        )
+    );
+
+    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
+    expect(render.text.style.color.opacity, 1.0);
+
+    controller.jumpTo(200.0);
+    await tester.pumpAndSettle();
+    expect(render.text.style.color.opacity, 1.0);
+  });
+
+  testWidgets('pinned && floating && !bottom ==> 1.0 opacity', (WidgetTester tester) async {
+    // Regression test for https://github.com/flutter/flutter/issues/25000.
+
+    final ScrollController controller = ScrollController();
+    await tester.pumpWidget(
+        _TestWidget(
+          pinned: true,
+          floating: true,
+          bottom: false,
+          controller: controller,
+        )
+    );
+
+    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
+    expect(render.text.style.color.opacity, 1.0);
+
+    controller.jumpTo(200.0);
+    await tester.pumpAndSettle();
+    expect(render.text.style.color.opacity, 1.0);
+  });
+
+  testWidgets('pinned && floating && bottom ==> fade opactiy', (WidgetTester tester) async {
+    // Regression test for https://github.com/flutter/flutter/issues/25993.
+
+    final ScrollController controller = ScrollController();
+    await tester.pumpWidget(
+      _TestWidget(
+        pinned: true,
+        floating: true,
+        bottom: true,
+        controller: controller,
+      )
+    );
+
+    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
+    expect(render.text.style.color.opacity, 1.0);
+
+    controller.jumpTo(200.0);
+    await tester.pumpAndSettle();
+    expect(render.text.style.color.opacity, 0.0);
+  });
+}
+
+class _TestWidget extends StatelessWidget {
+
+  const _TestWidget({this.pinned, this.floating, this.bottom, this.controller,});
+
+  final bool pinned;
+  final bool floating;
+  final bool bottom;
+  final ScrollController controller;
+
+  @override
+  Widget build(BuildContext context) {
+    return MaterialApp(
+      home: CustomScrollView(
+        controller: controller,
+        slivers: <Widget>[
+          SliverAppBar(
+            pinned: pinned,
+            floating: floating,
+            expandedHeight: 120.0,
+            title: const Text('Hallo Welt!!1'),
+            bottom: !bottom ? null :  PreferredSize(
+              preferredSize: const Size.fromHeight(35.0),
+              child: Container(),
+            ),
+          ),
+          SliverList(
+            delegate: SliverChildListDelegate(List<Widget>.generate(20, (int i) {
+              return Container(
+                child: Text('Tile $i'),
+                height: 100.0,
+              );
+            })),
+          )
+        ],
+      ),
+    );
+  }
+
+}
diff --git a/packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart b/packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart
index 3ee0986..69614fe 100644
--- a/packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart
+++ b/packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart
@@ -112,40 +112,4 @@
     expect(render.geometry.paintExtent, availableHeight);
     expect(render.geometry.layoutExtent, 0.0);
   });
-
-  testWidgets('Text does not dissapear when scrolled up', (WidgetTester tester) async {
-    // Regression test for https://github.com/flutter/flutter/issues/25000.
-
-    final ScrollController controller = ScrollController();
-    await tester.pumpWidget(
-      MaterialApp(
-        home: CustomScrollView(
-          controller: controller,
-          slivers: <Widget>[
-            const SliverAppBar(
-              pinned: true,
-              floating: true,
-              expandedHeight: 120.0,
-              title: Text('Hallo Welt!!1'),
-            ),
-            SliverList(
-              delegate: SliverChildListDelegate(List<Widget>.generate(20, (int i) {
-                return Container(
-                  child: Text('Tile $i'),
-                  height: 100.0,
-                );
-              })),
-            )
-          ],
-        ),
-      ),
-    );
-
-    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
-    expect(render.text.style.color.opacity, 1.0);
-
-    controller.jumpTo(200.0);
-    await tester.pumpAndSettle();
-    expect(render.text.style.color.opacity, 1.0);
-  });
 }