From 76baa5efc8df385fce3bab7f2ab4ade8f5dcd6d8 Mon Sep 17 00:00:00 2001 From: Ian Hickson Date: Thu, 14 Sep 2017 17:40:33 -0700 Subject: [PATCH] Fix the maths for floating pinned app bars. (#11996) (#12073) --- .../flutter/lib/src/material/app_bar.dart | 1 - .../rendering/sliver_persistent_header.dart | 2 +- .../slivers_appbar_floating_pinned_test.dart | 62 +++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart diff --git a/packages/flutter/lib/src/material/app_bar.dart b/packages/flutter/lib/src/material/app_bar.dart index 3403b6c8673..231152256f5 100644 --- a/packages/flutter/lib/src/material/app_bar.dart +++ b/packages/flutter/lib/src/material/app_bar.dart @@ -724,7 +724,6 @@ class SliverAppBar extends StatefulWidget { assert(titleSpacing != null), assert(floating != null), assert(pinned != null), - assert(!pinned || !floating || bottom != null, 'A pinned and floating app bar must have a bottom widget.'), assert(snap != null), assert(floating || !snap, 'The "snap" argument only makes sense for floating app bars.'), super(key: key); diff --git a/packages/flutter/lib/src/rendering/sliver_persistent_header.dart b/packages/flutter/lib/src/rendering/sliver_persistent_header.dart index 46dae375897..7be33ecc44d 100644 --- a/packages/flutter/lib/src/rendering/sliver_persistent_header.dart +++ b/packages/flutter/lib/src/rendering/sliver_persistent_header.dart @@ -512,7 +512,7 @@ abstract class RenderSliverFloatingPinnedPersistentHeader extends RenderSliverFl @override double updateGeometry() { - final double minExtent = this.maxExtent; + final double minExtent = this.minExtent; final double maxExtent = this.maxExtent; final double paintExtent = (maxExtent - _effectiveScrollOffset); final double layoutExtent = (maxExtent - constraints.scrollOffset); diff --git a/packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart b/packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart new file mode 100644 index 00000000000..2e5e59ca333 --- /dev/null +++ b/packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart @@ -0,0 +1,62 @@ +// Copyright 2017 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_test/flutter_test.dart'; +import 'package:flutter/material.dart'; + +void main() { + testWidgets('Sliver appbars - floating and pinned - second app bar stacks below', (WidgetTester tester) async { + final ScrollController controller = new ScrollController(); + await tester.pumpWidget( + new Directionality( + textDirection: TextDirection.ltr, + child: new MediaQuery( + data: const MediaQueryData(), + child: new CustomScrollView( + controller: controller, + slivers: [ + const SliverAppBar(floating: true, pinned: true, expandedHeight: 200.0, title: const Text('A')), + const SliverAppBar(primary: false, pinned: true, title: const Text('B')), + new SliverList( + delegate: new SliverChildListDelegate( + [ + const Text('C'), + const Text('D'), + const SizedBox(height: 500.0), + const Text('E'), + const SizedBox(height: 500.0), + ], + ), + ), + ], + ), + ), + ), + ); + const Offset textPositionInAppBar = const Offset(16.0, 18.0); + expect(tester.getTopLeft(find.text('A')), textPositionInAppBar); + // top app bar is 200.0 high at this point + expect(tester.getTopLeft(find.text('B')), const Offset(0.0, 200.0) + textPositionInAppBar); + // second app bar is 56.0 high + expect(tester.getTopLeft(find.text('C')), const Offset(0.0, 200.0 + 56.0)); // height of both appbars + final Size cSize = tester.getSize(find.text('C')); + controller.jumpTo(200.0 - 56.0); + await tester.pump(); + expect(tester.getTopLeft(find.text('A')), textPositionInAppBar); + // top app bar is now only 56.0 high, same as second + expect(tester.getTopLeft(find.text('B')), const Offset(0.0, 56.0) + textPositionInAppBar); + expect(tester.getTopLeft(find.text('C')), const Offset(0.0, 56.0 * 2.0)); // height of both collapsed appbars + expect(find.text('E'), findsNothing); + controller.jumpTo(600.0); + await tester.pump(); + expect(tester.getTopLeft(find.text('A')), textPositionInAppBar); // app bar is pinned at top + expect(tester.getTopLeft(find.text('B')), const Offset(0.0, 56.0) + textPositionInAppBar); // second one too + expect(find.text('C'), findsNothing); // contents are scrolled off though + expect(find.text('D'), findsNothing); + // we have scrolled 600.0 pixels + // initial position of E was 200 + 56 + cSize.height + cSize.height + 500 + // we've scrolled that up by 600.0, meaning it's at that minus 600 now: + expect(tester.getTopLeft(find.text('E')), new Offset(0.0, 200.0 + 56.0 + cSize.height * 2.0 + 500.0 - 600.0)); + }); +} \ No newline at end of file