diff --git a/packages/flutter/lib/src/material/app_bar.dart b/packages/flutter/lib/src/material/app_bar.dart index ed3fbad05e..c4f160e6b7 100644 --- a/packages/flutter/lib/src/material/app_bar.dart +++ b/packages/flutter/lib/src/material/app_bar.dart @@ -650,8 +650,22 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate { @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 0000000000..385a14d063 --- /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: [ + 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.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 3ee0986792..69614fec7f 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 @@ void main() { 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: [ - const SliverAppBar( - pinned: true, - floating: true, - expandedHeight: 120.0, - title: Text('Hallo Welt!!1'), - ), - SliverList( - delegate: SliverChildListDelegate(List.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); - }); }