Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
484c2268
Unverified
Commit
484c2268
authored
Mar 20, 2023
by
Kate Lovett
Committed by
GitHub
Mar 20, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix error message for unbounded viewports (#123035)
Fix error message for unbounded viewports
parent
76ee8ad2
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
198 additions
and
71 deletions
+198
-71
debug.dart
packages/flutter/lib/src/rendering/debug.dart
+78
-0
viewport.dart
packages/flutter/lib/src/rendering/viewport.dart
+37
-71
debug_test.dart
packages/flutter/test/rendering/debug_test.dart
+11
-0
viewport_test.dart
packages/flutter/test/rendering/viewport_test.dart
+72
-0
No files found.
packages/flutter/lib/src/rendering/debug.dart
View file @
484c2268
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
import
'box.dart'
;
import
'object.dart'
;
import
'object.dart'
;
export
'package:flutter/foundation.dart'
show
debugPrint
;
export
'package:flutter/foundation.dart'
show
debugPrint
;
...
@@ -311,3 +312,80 @@ bool debugAssertAllRenderVarsUnset(String reason, { bool debugCheckIntrinsicSize
...
@@ -311,3 +312,80 @@ bool debugAssertAllRenderVarsUnset(String reason, { bool debugCheckIntrinsicSize
}());
}());
return
true
;
return
true
;
}
}
/// Returns true if the given [Axis] is bounded within the given
/// [BoxConstraints] in both the main and cross axis, throwing an exception
/// otherwise.
///
/// This is used by viewports during `performLayout` and `computeDryLayout`
/// because bounded constraints are required in order to layout their children.
bool
debugCheckHasBoundedAxis
(
Axis
axis
,
BoxConstraints
constraints
)
{
assert
(()
{
if
(!
constraints
.
hasBoundedHeight
||
!
constraints
.
hasBoundedWidth
)
{
switch
(
axis
)
{
case
Axis
.
vertical
:
if
(!
constraints
.
hasBoundedHeight
)
{
throw
FlutterError
.
fromParts
(<
DiagnosticsNode
>[
ErrorSummary
(
'Vertical viewport was given unbounded height.'
),
ErrorDescription
(
'Viewports expand in the scrolling direction to fill their container. '
'In this case, a vertical viewport was given an unlimited amount of '
'vertical space in which to expand. This situation typically happens '
'when a scrollable widget is nested inside another scrollable widget.'
,
),
ErrorHint
(
'If this widget is always nested in a scrollable widget there '
'is no need to use a viewport because there will always be enough '
'vertical space for the children. In this case, consider using a '
'Column or Wrap instead. Otherwise, consider using a '
'CustomScrollView to concatenate arbitrary slivers into a '
'single scrollable.'
,
),
]);
}
if
(!
constraints
.
hasBoundedWidth
)
{
throw
FlutterError
(
'Vertical viewport was given unbounded width.
\n
'
'Viewports expand in the cross axis to fill their container and '
'constrain their children to match their extent in the cross axis. '
'In this case, a vertical viewport was given an unlimited amount of '
'horizontal space in which to expand.'
,
);
}
break
;
case
Axis
.
horizontal
:
if
(!
constraints
.
hasBoundedWidth
)
{
throw
FlutterError
.
fromParts
(<
DiagnosticsNode
>[
ErrorSummary
(
'Horizontal viewport was given unbounded width.'
),
ErrorDescription
(
'Viewports expand in the scrolling direction to fill their container. '
'In this case, a horizontal viewport was given an unlimited amount of '
'horizontal space in which to expand. This situation typically happens '
'when a scrollable widget is nested inside another scrollable widget.'
,
),
ErrorHint
(
'If this widget is always nested in a scrollable widget there '
'is no need to use a viewport because there will always be enough '
'horizontal space for the children. In this case, consider using a '
'Row or Wrap instead. Otherwise, consider using a '
'CustomScrollView to concatenate arbitrary slivers into a '
'single scrollable.'
,
),
]);
}
if
(!
constraints
.
hasBoundedHeight
)
{
throw
FlutterError
(
'Horizontal viewport was given unbounded height.
\n
'
'Viewports expand in the cross axis to fill their container and '
'constrain their children to match their extent in the cross axis. '
'In this case, a horizontal viewport was given an unlimited amount of '
'vertical space in which to expand.'
,
);
}
break
;
}
}
return
true
;
}());
return
true
;
}
packages/flutter/lib/src/rendering/viewport.dart
View file @
484c2268
...
@@ -9,6 +9,7 @@ import 'package:flutter/foundation.dart';
...
@@ -9,6 +9,7 @@ import 'package:flutter/foundation.dart';
import
'package:flutter/semantics.dart'
;
import
'package:flutter/semantics.dart'
;
import
'box.dart'
;
import
'box.dart'
;
import
'debug.dart'
;
import
'layer.dart'
;
import
'layer.dart'
;
import
'object.dart'
;
import
'object.dart'
;
import
'sliver.dart'
;
import
'sliver.dart'
;
...
@@ -1388,73 +1389,7 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
...
@@ -1388,73 +1389,7 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
@override
@override
Size
computeDryLayout
(
BoxConstraints
constraints
)
{
Size
computeDryLayout
(
BoxConstraints
constraints
)
{
assert
(()
{
assert
(
debugCheckHasBoundedAxis
(
axis
,
constraints
));
if
(!
constraints
.
hasBoundedHeight
||
!
constraints
.
hasBoundedWidth
)
{
switch
(
axis
)
{
case
Axis
.
vertical
:
if
(!
constraints
.
hasBoundedHeight
)
{
throw
FlutterError
.
fromParts
(<
DiagnosticsNode
>[
ErrorSummary
(
'Vertical viewport was given unbounded height.'
),
ErrorDescription
(
'Viewports expand in the scrolling direction to fill their container. '
'In this case, a vertical viewport was given an unlimited amount of '
'vertical space in which to expand. This situation typically happens '
'when a scrollable widget is nested inside another scrollable widget.'
,
),
ErrorHint
(
'If this widget is always nested in a scrollable widget there '
'is no need to use a viewport because there will always be enough '
'vertical space for the children. In this case, consider using a '
'Column or Wrap instead. Otherwise, consider using a '
'CustomScrollView to concatenate arbitrary slivers into a '
'single scrollable.'
,
),
]);
}
if
(!
constraints
.
hasBoundedWidth
)
{
throw
FlutterError
(
'Vertical viewport was given unbounded width.
\n
'
'Viewports expand in the cross axis to fill their container and '
'constrain their children to match their extent in the cross axis. '
'In this case, a vertical viewport was given an unlimited amount of '
'horizontal space in which to expand.'
,
);
}
break
;
case
Axis
.
horizontal
:
if
(!
constraints
.
hasBoundedWidth
)
{
throw
FlutterError
.
fromParts
(<
DiagnosticsNode
>[
ErrorSummary
(
'Horizontal viewport was given unbounded width.'
),
ErrorDescription
(
'Viewports expand in the scrolling direction to fill their container. '
'In this case, a horizontal viewport was given an unlimited amount of '
'horizontal space in which to expand. This situation typically happens '
'when a scrollable widget is nested inside another scrollable widget.'
,
),
ErrorHint
(
'If this widget is always nested in a scrollable widget there '
'is no need to use a viewport because there will always be enough '
'horizontal space for the children. In this case, consider using a '
'Row or Wrap instead. Otherwise, consider using a '
'CustomScrollView to concatenate arbitrary slivers into a '
'single scrollable.'
,
),
]);
}
if
(!
constraints
.
hasBoundedHeight
)
{
throw
FlutterError
(
'Horizontal viewport was given unbounded height.
\n
'
'Viewports expand in the cross axis to fill their container and '
'constrain their children to match their extent in the cross axis. '
'In this case, a horizontal viewport was given an unlimited amount of '
'vertical space in which to expand.'
,
);
}
break
;
}
}
return
true
;
}());
return
constraints
.
biggest
;
return
constraints
.
biggest
;
}
}
...
@@ -1858,17 +1793,48 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
...
@@ -1858,17 +1793,48 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
late
double
_shrinkWrapExtent
;
late
double
_shrinkWrapExtent
;
bool
_hasVisualOverflow
=
false
;
bool
_hasVisualOverflow
=
false
;
bool
_debugCheckHasBoundedCrossAxis
()
{
assert
(()
{
switch
(
axis
)
{
case
Axis
.
vertical
:
if
(!
constraints
.
hasBoundedWidth
)
{
throw
FlutterError
(
'Vertical viewport was given unbounded width.
\n
'
'Viewports expand in the cross axis to fill their container and '
'constrain their children to match their extent in the cross axis. '
'In this case, a vertical shrinkwrapping viewport was given an '
'unlimited amount of horizontal space in which to expand.'
,
);
}
break
;
case
Axis
.
horizontal
:
if
(!
constraints
.
hasBoundedHeight
)
{
throw
FlutterError
(
'Horizontal viewport was given unbounded height.
\n
'
'Viewports expand in the cross axis to fill their container and '
'constrain their children to match their extent in the cross axis. '
'In this case, a horizontal shrinkwrapping viewport was given an '
'unlimited amount of vertical space in which to expand.'
,
);
}
break
;
}
return
true
;
}());
return
true
;
}
@override
@override
void
performLayout
()
{
void
performLayout
()
{
final
BoxConstraints
constraints
=
this
.
constraints
;
final
BoxConstraints
constraints
=
this
.
constraints
;
if
(
firstChild
==
null
)
{
if
(
firstChild
==
null
)
{
// Shrinkwrapping viewport only requires the cross axis to be bounded.
assert
(
_debugCheckHasBoundedCrossAxis
());
switch
(
axis
)
{
switch
(
axis
)
{
case
Axis
.
vertical
:
case
Axis
.
vertical
:
assert
(
constraints
.
hasBoundedWidth
);
size
=
Size
(
constraints
.
maxWidth
,
constraints
.
minHeight
);
size
=
Size
(
constraints
.
maxWidth
,
constraints
.
minHeight
);
break
;
break
;
case
Axis
.
horizontal
:
case
Axis
.
horizontal
:
assert
(
constraints
.
hasBoundedHeight
);
size
=
Size
(
constraints
.
minWidth
,
constraints
.
maxHeight
);
size
=
Size
(
constraints
.
minWidth
,
constraints
.
maxHeight
);
break
;
break
;
}
}
...
@@ -1882,14 +1848,14 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
...
@@ -1882,14 +1848,14 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
final
double
mainAxisExtent
;
final
double
mainAxisExtent
;
final
double
crossAxisExtent
;
final
double
crossAxisExtent
;
// Shrinkwrapping viewport only requires the cross axis to be bounded.
assert
(
_debugCheckHasBoundedCrossAxis
());
switch
(
axis
)
{
switch
(
axis
)
{
case
Axis
.
vertical
:
case
Axis
.
vertical
:
assert
(
constraints
.
hasBoundedWidth
);
mainAxisExtent
=
constraints
.
maxHeight
;
mainAxisExtent
=
constraints
.
maxHeight
;
crossAxisExtent
=
constraints
.
maxWidth
;
crossAxisExtent
=
constraints
.
maxWidth
;
break
;
break
;
case
Axis
.
horizontal
:
case
Axis
.
horizontal
:
assert
(
constraints
.
hasBoundedHeight
);
mainAxisExtent
=
constraints
.
maxWidth
;
mainAxisExtent
=
constraints
.
maxWidth
;
crossAxisExtent
=
constraints
.
maxHeight
;
crossAxisExtent
=
constraints
.
maxHeight
;
break
;
break
;
...
...
packages/flutter/test/rendering/debug_test.dart
View file @
484c2268
...
@@ -261,4 +261,15 @@ void main() {
...
@@ -261,4 +261,15 @@ void main() {
expect
(()
=>
debugAssertAllRenderVarsUnset
(
'ERROR'
),
throwsFlutterError
);
expect
(()
=>
debugAssertAllRenderVarsUnset
(
'ERROR'
),
throwsFlutterError
);
debugDisableOpacityLayers
=
false
;
debugDisableOpacityLayers
=
false
;
});
});
test
(
'debugCheckHasBoundedAxis warns for vertical and horizontal axis'
,
()
{
expect
(
()
=>
debugCheckHasBoundedAxis
(
Axis
.
vertical
,
const
BoxConstraints
()),
throwsFlutterError
,
);
expect
(
()
=>
debugCheckHasBoundedAxis
(
Axis
.
horizontal
,
const
BoxConstraints
()),
throwsFlutterError
,
);
});
}
}
packages/flutter/test/rendering/viewport_test.dart
View file @
484c2268
...
@@ -2188,4 +2188,76 @@ void main() {
...
@@ -2188,4 +2188,76 @@ void main() {
});
});
expect
(
visited
,
true
);
expect
(
visited
,
true
);
});
});
testWidgets
(
'Shrinkwrapping viewport asserts bounded cross axis'
,
(
WidgetTester
tester
)
async
{
final
List
<
FlutterErrorDetails
>
errors
=
<
FlutterErrorDetails
>[];
FlutterError
.
onError
=
(
FlutterErrorDetails
error
)
=>
errors
.
add
(
error
);
// Vertical
await
tester
.
pumpWidget
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
ListView
(
scrollDirection:
Axis
.
horizontal
,
children:
<
Widget
>[
ListView
(
shrinkWrap:
true
,
children:
const
<
Widget
>[
SizedBox
.
square
(
dimension:
500
)
],
),
],
),
));
expect
(
errors
,
isNotEmpty
);
expect
(
errors
.
first
.
exception
,
isFlutterError
);
FlutterError
error
=
errors
.
first
.
exception
as
FlutterError
;
expect
(
error
.
toString
(),
contains
(
'Viewports expand in the cross axis to fill their container'
),
);
errors
.
clear
();
// Horizontal
await
tester
.
pumpWidget
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
ListView
(
children:
<
Widget
>[
ListView
(
scrollDirection:
Axis
.
horizontal
,
shrinkWrap:
true
,
children:
const
<
Widget
>[
SizedBox
.
square
(
dimension:
500
)
],
),
],
),
));
expect
(
errors
,
isNotEmpty
);
expect
(
errors
.
first
.
exception
,
isFlutterError
);
error
=
errors
.
first
.
exception
as
FlutterError
;
expect
(
error
.
toString
(),
contains
(
'Viewports expand in the cross axis to fill their container'
),
);
errors
.
clear
();
// No children
await
tester
.
pumpWidget
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
ListView
(
scrollDirection:
Axis
.
horizontal
,
children:
<
Widget
>[
ListView
(
shrinkWrap:
true
,
),
],
),
));
expect
(
errors
,
isNotEmpty
);
expect
(
errors
.
first
.
exception
,
isFlutterError
);
error
=
errors
.
first
.
exception
as
FlutterError
;
expect
(
error
.
toString
(),
contains
(
'Viewports expand in the cross axis to fill their container'
),
);
errors
.
clear
();
});
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment