From 3f0024e164a78fa281dd63c59aea4e54d793baa5 Mon Sep 17 00:00:00 2001 From: Mjk Date: Wed, 6 May 2020 23:16:01 +0300 Subject: [PATCH] Fix compute intrinsic size for wrap (#55469) --- AUTHORS | 1 + packages/flutter/lib/src/rendering/wrap.dart | 24 ++-- .../flutter/test/rendering/wrap_test.dart | 126 ++++++++++++++++++ 3 files changed, 135 insertions(+), 16 deletions(-) diff --git a/AUTHORS b/AUTHORS index 901b250547..4c673d627f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -54,3 +54,4 @@ Cédric Wyss Michel Feinstein Michael Lee Katarina Sheremet +Mikhail Zotyev diff --git a/packages/flutter/lib/src/rendering/wrap.dart b/packages/flutter/lib/src/rendering/wrap.dart index 30cdc10b84..c1bb0d75f9 100644 --- a/packages/flutter/lib/src/rendering/wrap.dart +++ b/packages/flutter/lib/src/rendering/wrap.dart @@ -383,7 +383,6 @@ class RenderWrap extends RenderBox with ContainerRenderObjectMixin width) { - height += runHeight; - if (runCount > 0) - height += runSpacing; - runCount += 1; + // There must be at least one child before we move on to the next run. + if (childCount > 0 && runWidth + childWidth + spacing > width) { + height += runHeight + runSpacing; runWidth = 0.0; runHeight = 0.0; childCount = 0; @@ -408,14 +405,12 @@ class RenderWrap extends RenderBox with ContainerRenderObjectMixin 0) - height += runHeight + runSpacing; + height += runHeight; return height; } double _computeIntrinsicWidthForHeight(double height) { assert(direction == Axis.vertical); - int runCount = 0; double width = 0.0; double runHeight = 0.0; double runWidth = 0.0; @@ -424,11 +419,9 @@ class RenderWrap extends RenderBox with ContainerRenderObjectMixin height) { - width += runWidth; - if (runCount > 0) - width += runSpacing; - runCount += 1; + // There must be at least one child before we move on to the next run. + if (childCount > 0 && runHeight + childHeight + spacing > height) { + width += runWidth + runSpacing; runHeight = 0.0; runWidth = 0.0; childCount = 0; @@ -440,8 +433,7 @@ class RenderWrap extends RenderBox with ContainerRenderObjectMixin 0) - width += runWidth + runSpacing; + width += runWidth; return width; } diff --git a/packages/flutter/test/rendering/wrap_test.dart b/packages/flutter/test/rendering/wrap_test.dart index 57d2210610..e6dac87e97 100644 --- a/packages/flutter/test/rendering/wrap_test.dart +++ b/packages/flutter/test/rendering/wrap_test.dart @@ -25,4 +25,130 @@ void main() { ), ); }); + + test('Compute intrinsic height test', () { + final List children = [ + RenderConstrainedBox( + additionalConstraints: const BoxConstraints( + minWidth: 80, + minHeight: 80, + ), + ), + RenderConstrainedBox( + additionalConstraints: const BoxConstraints( + minWidth: 80, + minHeight: 80, + ), + ), + RenderConstrainedBox( + additionalConstraints: const BoxConstraints( + minWidth: 80, + minHeight: 80, + ), + ), + ]; + + final RenderWrap renderWrap = RenderWrap(); + + children.forEach(renderWrap.add); + + renderWrap.spacing = 5; + renderWrap.runSpacing = 5; + renderWrap.direction = Axis.horizontal; + + expect(renderWrap.computeMaxIntrinsicHeight(245), 165); + expect(renderWrap.computeMaxIntrinsicHeight(250), 80); + expect(renderWrap.computeMaxIntrinsicHeight(80), 250); + expect(renderWrap.computeMaxIntrinsicHeight(79), 250); + expect(renderWrap.computeMinIntrinsicHeight(245), 165); + expect(renderWrap.computeMinIntrinsicHeight(250), 80); + expect(renderWrap.computeMinIntrinsicHeight(80), 250); + expect(renderWrap.computeMinIntrinsicHeight(79), 250); + }); + + test('Compute intrinsic width test', () { + final List children = [ + RenderConstrainedBox( + additionalConstraints: const BoxConstraints( + minWidth: 80, + minHeight: 80, + ), + ), + RenderConstrainedBox( + additionalConstraints: const BoxConstraints( + minWidth: 80, + minHeight: 80, + ), + ), + RenderConstrainedBox( + additionalConstraints: const BoxConstraints( + minWidth: 80, + minHeight: 80, + ), + ), + ]; + + final RenderWrap renderWrap = RenderWrap(); + + children.forEach(renderWrap.add); + + renderWrap.spacing = 5; + renderWrap.runSpacing = 5; + renderWrap.direction = Axis.vertical; + + expect(renderWrap.computeMaxIntrinsicWidth(245), 165); + expect(renderWrap.computeMaxIntrinsicWidth(250), 80); + expect(renderWrap.computeMaxIntrinsicWidth(80), 250); + expect(renderWrap.computeMaxIntrinsicWidth(79), 250); + expect(renderWrap.computeMinIntrinsicWidth(245), 165); + expect(renderWrap.computeMinIntrinsicWidth(250), 80); + expect(renderWrap.computeMinIntrinsicWidth(80), 250); + expect(renderWrap.computeMinIntrinsicWidth(79), 250); + }); + + test('Compute intrinsic height for only one run', () { + final RenderBox child = RenderConstrainedBox( + additionalConstraints: const BoxConstraints( + minWidth: 80, + minHeight: 80, + ), + ); + + final RenderWrap renderWrap = RenderWrap(); + renderWrap.add(child); + + renderWrap.spacing = 5; + renderWrap.runSpacing = 5; + renderWrap.direction = Axis.horizontal; + + expect(renderWrap.computeMaxIntrinsicHeight(100), 80); + expect(renderWrap.computeMaxIntrinsicHeight(79), 80); + expect(renderWrap.computeMaxIntrinsicHeight(80), 80); + expect(renderWrap.computeMinIntrinsicHeight(100), 80); + expect(renderWrap.computeMinIntrinsicHeight(79), 80); + expect(renderWrap.computeMinIntrinsicHeight(80), 80); + }); + + test('Compute intrinsic width for only one run', () { + final RenderBox child = RenderConstrainedBox( + additionalConstraints: const BoxConstraints( + minWidth: 80, + minHeight: 80, + ), + ); + + final RenderWrap renderWrap = RenderWrap(); + renderWrap.add(child); + + renderWrap.spacing = 5; + renderWrap.runSpacing = 5; + renderWrap.direction = Axis.vertical; + + expect(renderWrap.computeMaxIntrinsicWidth(100), 80); + expect(renderWrap.computeMaxIntrinsicWidth(79), 80); + expect(renderWrap.computeMaxIntrinsicWidth(80), 80); + expect(renderWrap.computeMinIntrinsicWidth(100), 80); + expect(renderWrap.computeMinIntrinsicWidth(79), 80); + expect(renderWrap.computeMinIntrinsicWidth(80), 80); + }); }