Unverified Commit 27394f60 authored by Fedor Blagodyr's avatar Fedor Blagodyr Committed by GitHub

Fix sliver persistent header expand animation (#137913)

Added animation status check at showOnScreen method to prevent broken animation of expanding SliverAppBar when focusing EditableText

close #137901
parent 4d788b10
...@@ -741,7 +741,7 @@ abstract class RenderSliverFloatingPersistentHeader extends RenderSliverPersiste ...@@ -741,7 +741,7 @@ abstract class RenderSliverFloatingPersistentHeader extends RenderSliverPersiste
effectiveMaxExtent); effectiveMaxExtent);
// Expands the header if needed, with animation. // Expands the header if needed, with animation.
if (targetExtent > childExtent) { if (targetExtent > childExtent && _controller?.status != AnimationStatus.forward) {
final double targetScrollOffset = maxExtent - targetExtent; final double targetScrollOffset = maxExtent - targetExtent;
assert( assert(
vsync != null, vsync != null,
......
...@@ -1314,6 +1314,46 @@ void main() { ...@@ -1314,6 +1314,46 @@ void main() {
}, },
); );
testWidgetsWithLeakTracking('RenderViewportBase.showOnScreen twice almost instantly', (WidgetTester tester) async{
// Regression test for https://github.com/flutter/flutter/issues/137901
await tester.pumpWidget(
buildList(
floatingHeader: SliverPersistentHeader(
pinned: true,
floating: true,
delegate: _TestSliverPersistentHeaderDelegate(minExtent: 100, maxExtent: 300, key: headerKey, vsync: vsync),
),
),
);
final Finder pinnedHeaderContent = find.byKey(headerKey, skipOffstage: false);
controller.jumpTo(300.0 * 15);
await tester.pumpAndSettle();
expect(mainAxisExtent(tester, pinnedHeaderContent), lessThan(300));
tester.renderObject(pinnedHeaderContent).showOnScreen(
descendant: tester.renderObject(pinnedHeaderContent),
// Adding different rect to check if the second showOnScreen call
// leads to a different result.
// When the animation has forward status and the second showOnScreen
// is called, the new animation won't start.
rect: Offset.zero & const Size(150, 150),
duration: const Duration(seconds: 3),
);
await tester.pump(const Duration(seconds: 1));
tester.renderObject(pinnedHeaderContent).showOnScreen(
descendant: tester.renderObject(pinnedHeaderContent),
rect: Offset.zero & const Size(300, 300),
);
await tester.pumpAndSettle();
expect(controller.offset, 300.0 * 15);
expect(mainAxisExtent(tester, pinnedHeaderContent), 150);
});
testWidgetsWithLeakTracking( testWidgetsWithLeakTracking(
'RenderViewportBase.showOnScreen but no child', 'RenderViewportBase.showOnScreen but no child',
(WidgetTester tester) async { (WidgetTester tester) async {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment