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
6139708e
Unverified
Commit
6139708e
authored
Jul 29, 2020
by
Hans Muller
Committed by
GitHub
Jul 29, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added OverflowBar widget (#62350)
parent
c177db17
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
764 additions
and
0 deletions
+764
-0
overflow_bar.dart
packages/flutter/lib/src/widgets/overflow_bar.dart
+524
-0
widgets.dart
packages/flutter/lib/widgets.dart
+1
-0
overflow_bar_test.dart
packages/flutter/test/widgets/overflow_bar_test.dart
+239
-0
No files found.
packages/flutter/lib/src/widgets/overflow_bar.dart
0 → 100644
View file @
6139708e
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'dart:math'
as
math
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/rendering.dart'
;
import
'basic.dart'
;
import
'framework.dart'
;
/// Defines the horizontal alignment of [OverflowBar] children
/// when they're laid out in an overflow column.
///
/// This value must be interpreted relative to the ambient
/// [TextDirection].
enum
OverflowBarAlignment
{
/// Each child is left-aligned for [TextDirection.ltr],
/// right-aligned for [TextDirection.rtl].
start
,
/// Each child is right-aligned for [TextDirection.ltr],
/// left-aligned for [TextDirection.rtl].
end
,
/// Each child is horizontally centered.
center
,
}
/// A widget that lays out its [children] in a row unless they
/// "overflow" the available horizontal space, in which case it lays
/// them out in a column instead.
///
/// This widget's width will expand to contain its children and the
/// specified [spacing] until it overflows. The overflow column will
/// consume all of the available width. The [overflowAlignment]
/// defines how each child will be aligned within the overflow column
/// and the [overflowSpacing] defines the gap between each child.
///
/// The order that the children appear in the horizontal layout
/// is defined by the [textDirection], just like the [Row] widget.
/// If the layout overflows, then children's order within their
/// column is specified by [overflowDirection] instead.
///
/// {@tool dartpad --template=stateless_widget_scaffold_center}
///
/// This example defines a simple approximation of a dialog
/// layout, where the layout of the dialog's action buttons are
/// defined by an [OverflowBar]. The content is wrapped in a
/// [SingleChildScrollView], so that if overflow occurs, the
/// action buttons will still be accessible by scrolling,
/// no matter how much vertical space is available.
///
/// ```dart
/// Widget build(BuildContext context) {
/// return Container(
/// alignment: Alignment.center,
/// padding: EdgeInsets.all(16),
/// color: Colors.black.withOpacity(0.15),
/// child: Material(
/// color: Colors.white,
/// elevation: 24,
/// shape: RoundedRectangleBorder(
/// borderRadius: BorderRadius.all(Radius.circular(4))
/// ),
/// child: Padding(
/// padding: EdgeInsets.all(8),
/// child: SingleChildScrollView(
/// child: Column(
/// mainAxisSize: MainAxisSize.min,
/// crossAxisAlignment: CrossAxisAlignment.stretch,
/// children: <Widget>[
/// Container(height: 128, child: Placeholder()),
/// Align(
/// alignment: AlignmentDirectional.centerEnd,
/// child: OverflowBar(
/// spacing: 8,
/// overflowAlignment: OverflowBarAlignment.end,
/// children: <Widget>[
/// TextButton(child: Text('Cancel'), onPressed: () { }),
/// TextButton(child: Text('Really Really Cancel'), onPressed: () { }),
/// OutlinedButton(child: Text('OK'), onPressed: () { }),
/// ],
/// ),
/// ),
/// ],
/// ),
/// ),
/// ),
/// ),
/// );
/// }
/// ```
/// {@end-tool}
class
OverflowBar
extends
MultiChildRenderObjectWidget
{
/// Constructs an OverflowBar.
///
/// The [spacing], [overflowSpacing], [overflowAlignment],
/// [overflowDirection], and [clipBehavior] parameters must not be
/// null. The [children] argument must not be null and must not contain
/// any null objects.
OverflowBar
({
Key
key
,
this
.
spacing
=
0.0
,
this
.
overflowSpacing
=
0.0
,
this
.
overflowAlignment
=
OverflowBarAlignment
.
start
,
this
.
overflowDirection
=
VerticalDirection
.
down
,
this
.
textDirection
,
this
.
clipBehavior
=
Clip
.
none
,
List
<
Widget
>
children
=
const
<
Widget
>[],
})
:
assert
(
spacing
!=
null
),
assert
(
overflowSpacing
!=
null
),
assert
(
overflowAlignment
!=
null
),
assert
(
overflowDirection
!=
null
),
assert
(
clipBehavior
!=
null
),
super
(
key:
key
,
children:
children
);
/// The width of the gap between [children] for the default
/// horizontal layout.
///
/// If the horizontal layout overflows, then [overflowSpacing] is
/// used instead.
///
/// Defaults to 0.0.
final
double
spacing
;
/// The height of the gap between [children] in the vertical
/// "overflow" layout.
///
/// This parameter is only used if the horizontal layout overflows, i.e.
/// if there isn't enough horizontal room for the [children] and [spacing].
///
/// Defaults to 0.0.
///
/// See also:
///
/// * [spacing], The width of the gap between each pair of children
/// for the default horizontal layout.
final
double
overflowSpacing
;
/// The horizontal alignment of the [children] within the vertical
/// "overflow" layout.
///
/// This parameter is only used if the horizontal layout overflows, i.e.
/// if there isn't enough horizontal room for the [children] and [spacing].
/// In that case the overflow bar will expand to fill the available
/// width and it will layout its [children] in a column. The
/// horizontal alignment of each child within that column is
/// defined by this parameter and the [textDirection]. If the
/// [textDirection] is [TextDirection.ltr] then each child will be
/// aligned with the left edge of the available space for
/// [OverflowBarAlignment.start], with the right edge of the
/// available space for [OverflowBarAlignment.end]. Similarly, if the
/// [textDirection] is [TextDirection.rtl] then each child will
/// be aligned with the right edge of the available space for
/// [OverflowBarAlignment.start], and with the left edge of the
/// available space for [OverflowBarAlignment.end]. For
/// [OverflowBarAlignment.center] each child is horizontally
/// centered within the available space.
///
/// Defaults to [OverflowBarAlignment.start].
///
/// See also:
///
/// * [overflowDirection], which defines the order that the
/// [OverflowBar]'s children appear in, if the horizontal layout
/// overflows.
final
OverflowBarAlignment
overflowAlignment
;
/// Defines the order that the [children] appear in, if
/// the horizontal layout overflows.
///
/// This parameter is only used if the horizontal layout overflows, i.e.
/// if there isn't enough horizontal room for the [children] and [spacing].
///
/// If the children do not fit into a single row, then they
/// are arranged in a column. The first child is at the top of the
/// column if this property is set to [VerticalDirection.down], since it
/// "starts" at the top and "ends" at the bottom. On the other hand,
/// the first child will be at the bottom of the column if this
/// property is set to [VerticalDirection.up], since it "starts" at the
/// bottom and "ends" at the top.
///
/// Defaults to [VerticalDirection.down].
///
/// See also:
///
/// * [overflowAlignment], which defines the horizontal alignment
/// of the children within the vertical "overflow" layout.
final
VerticalDirection
overflowDirection
;
/// Determines the order that the [children] appear in for the default
/// horizontal layout, and the interpretation of
/// [OverflowBarAlignment.start] and [OverflowBarAlignment.end] for
/// the vertical overflow layout.
///
/// For the default horizontal layout, if [textDirection] is
/// [TextDirection.rtl] then the last child is laid out first. If
/// [textDirection] is [TextDirection.ltr] then the first child is
/// laid out first.
///
/// If this parameter is null, then the value of
/// `Directionality.of(context)` is used.
///
/// See also:
///
/// * [overflowDirection], which defines the order that the
/// [OverflowBar]'s children appear in, if the horizontal layout
/// overflows.
/// * [Directionality], which defines the ambient directionality of
/// text and text-direction-sensitive render objects.
final
TextDirection
textDirection
;
/// {@macro flutter.widgets.Clip}
///
/// Defaults to [Clip.none], and must not be null.
final
Clip
clipBehavior
;
@override
_RenderOverflowBar
createRenderObject
(
BuildContext
context
)
{
return
_RenderOverflowBar
(
spacing:
spacing
,
overflowSpacing:
overflowSpacing
,
overflowAlignment:
overflowAlignment
,
overflowDirection:
overflowDirection
,
textDirection:
textDirection
??
Directionality
.
of
(
context
),
clipBehavior:
clipBehavior
,
);
}
@override
void
updateRenderObject
(
BuildContext
context
,
_RenderOverflowBar
renderObject
)
{
renderObject
..
spacing
=
spacing
..
overflowSpacing
=
overflowSpacing
..
overflowAlignment
=
overflowAlignment
..
overflowDirection
=
overflowDirection
..
textDirection
=
textDirection
??
Directionality
.
of
(
context
)
..
clipBehavior
=
clipBehavior
;
}
@override
void
debugFillProperties
(
DiagnosticPropertiesBuilder
properties
)
{
super
.
debugFillProperties
(
properties
);
properties
.
add
(
DoubleProperty
(
'spacing'
,
spacing
,
defaultValue:
0
));
properties
.
add
(
DoubleProperty
(
'overflowSpacing'
,
overflowSpacing
,
defaultValue:
0
));
properties
.
add
(
EnumProperty
<
OverflowBarAlignment
>(
'overflowAlignment'
,
overflowAlignment
,
defaultValue:
OverflowBarAlignment
.
start
));
properties
.
add
(
EnumProperty
<
VerticalDirection
>(
'overflowDirection'
,
overflowDirection
,
defaultValue:
VerticalDirection
.
down
));
properties
.
add
(
EnumProperty
<
TextDirection
>(
'textDirection'
,
textDirection
,
defaultValue:
null
));
}
}
class
_OverflowBarParentData
extends
ContainerBoxParentData
<
RenderBox
>
{
}
class
_RenderOverflowBar
extends
RenderBox
with
ContainerRenderObjectMixin
<
RenderBox
,
_OverflowBarParentData
>,
RenderBoxContainerDefaultsMixin
<
RenderBox
,
_OverflowBarParentData
>
{
_RenderOverflowBar
({
List
<
RenderBox
>
children
,
double
spacing
=
0.0
,
double
overflowSpacing
=
0.0
,
OverflowBarAlignment
overflowAlignment
=
OverflowBarAlignment
.
start
,
VerticalDirection
overflowDirection
=
VerticalDirection
.
down
,
TextDirection
textDirection
,
Clip
clipBehavior
=
Clip
.
none
,
})
:
assert
(
spacing
!=
null
),
assert
(
overflowSpacing
!=
null
),
assert
(
overflowAlignment
!=
null
),
assert
(
textDirection
!=
null
),
assert
(
clipBehavior
!=
null
),
_spacing
=
spacing
,
_overflowSpacing
=
overflowSpacing
,
_overflowAlignment
=
overflowAlignment
,
_overflowDirection
=
overflowDirection
,
_textDirection
=
textDirection
,
_clipBehavior
=
clipBehavior
{
addAll
(
children
);
}
double
get
spacing
=>
_spacing
;
double
_spacing
;
set
spacing
(
double
value
)
{
assert
(
value
!=
null
);
if
(
_spacing
==
value
)
return
;
_spacing
=
value
;
markNeedsLayout
();
}
double
get
overflowSpacing
=>
_overflowSpacing
;
double
_overflowSpacing
;
set
overflowSpacing
(
double
value
)
{
assert
(
value
!=
null
);
if
(
_overflowSpacing
==
value
)
return
;
_overflowSpacing
=
value
;
markNeedsLayout
();
}
OverflowBarAlignment
get
overflowAlignment
=>
_overflowAlignment
;
OverflowBarAlignment
_overflowAlignment
;
set
overflowAlignment
(
OverflowBarAlignment
value
)
{
assert
(
value
!=
null
);
if
(
_overflowAlignment
==
value
)
return
;
_overflowAlignment
=
value
;
markNeedsLayout
();
}
VerticalDirection
get
overflowDirection
=>
_overflowDirection
;
VerticalDirection
_overflowDirection
;
set
overflowDirection
(
VerticalDirection
value
)
{
assert
(
value
!=
null
);
if
(
_overflowDirection
==
value
)
return
;
_overflowDirection
=
value
;
markNeedsLayout
();
}
TextDirection
get
textDirection
=>
_textDirection
;
TextDirection
_textDirection
;
set
textDirection
(
TextDirection
value
)
{
if
(
_textDirection
==
value
)
return
;
_textDirection
=
value
;
markNeedsLayout
();
}
Clip
get
clipBehavior
=>
_clipBehavior
;
Clip
_clipBehavior
=
Clip
.
none
;
set
clipBehavior
(
Clip
value
)
{
assert
(
value
!=
null
);
if
(
value
==
_clipBehavior
)
return
;
_clipBehavior
=
value
;
markNeedsPaint
();
markNeedsSemanticsUpdate
();
}
@override
void
setupParentData
(
RenderBox
child
)
{
if
(
child
.
parentData
is
!
_OverflowBarParentData
)
child
.
parentData
=
_OverflowBarParentData
();
}
@override
double
computeMinIntrinsicHeight
(
double
width
)
{
RenderBox
child
=
firstChild
;
if
(
child
==
null
)
return
0
;
double
barWidth
=
0.0
;
while
(
child
!=
null
)
{
barWidth
+=
child
.
getMinIntrinsicWidth
(
double
.
infinity
);
child
=
childAfter
(
child
);
}
barWidth
+=
spacing
*
(
childCount
-
1
);
double
height
=
0.0
;
if
(
barWidth
>
width
)
{
child
=
firstChild
;
while
(
child
!=
null
)
{
height
+=
child
.
getMinIntrinsicHeight
(
width
);
child
=
childAfter
(
child
);
}
return
height
+
overflowSpacing
*
(
childCount
-
1
);
}
else
{
child
=
firstChild
;
while
(
child
!=
null
)
{
height
=
math
.
max
(
height
,
child
.
getMinIntrinsicHeight
(
width
));
child
=
childAfter
(
child
);
}
return
height
;
}
}
@override
double
computeMaxIntrinsicHeight
(
double
width
)
{
RenderBox
child
=
firstChild
;
if
(
child
==
null
)
return
0
;
double
barWidth
=
0.0
;
while
(
child
!=
null
)
{
barWidth
+=
child
.
getMinIntrinsicWidth
(
double
.
infinity
);
child
=
childAfter
(
child
);
}
barWidth
+=
spacing
*
(
childCount
-
1
);
double
height
=
0.0
;
if
(
barWidth
>
width
)
{
child
=
firstChild
;
while
(
child
!=
null
)
{
height
+=
child
.
getMaxIntrinsicHeight
(
width
);
child
=
childAfter
(
child
);
}
return
height
+
overflowSpacing
*
(
childCount
-
1
);
}
else
{
child
=
firstChild
;
while
(
child
!=
null
)
{
height
=
math
.
max
(
height
,
child
.
getMaxIntrinsicHeight
(
width
));
child
=
childAfter
(
child
);
}
return
height
;
}
}
@override
double
computeMinIntrinsicWidth
(
double
height
)
{
RenderBox
child
=
firstChild
;
if
(
child
==
null
)
return
0
;
double
width
=
0.0
;
while
(
child
!=
null
)
{
width
+=
child
.
getMinIntrinsicWidth
(
double
.
infinity
);
child
=
childAfter
(
child
);
}
return
width
+
spacing
*
(
childCount
-
1
);
}
@override
double
computeMaxIntrinsicWidth
(
double
height
)
{
RenderBox
child
=
firstChild
;
if
(
child
==
null
)
return
0
;
double
width
=
0.0
;
while
(
child
!=
null
)
{
width
+=
child
.
getMaxIntrinsicWidth
(
double
.
infinity
);
child
=
childAfter
(
child
);
}
return
width
+
spacing
*
(
childCount
-
1
);
}
@override
double
computeDistanceToActualBaseline
(
TextBaseline
baseline
)
{
return
defaultComputeDistanceToHighestActualBaseline
(
baseline
);
}
@override
void
performLayout
()
{
RenderBox
child
=
firstChild
;
if
(
child
==
null
)
{
size
=
constraints
.
smallest
;
return
;
}
final
BoxConstraints
childConstraints
=
constraints
.
loosen
();
double
childrenWidth
=
0
;
double
maxChildHeight
=
0
;
double
maxChildWidth
=
0
;
while
(
child
!=
null
)
{
child
.
layout
(
childConstraints
,
parentUsesSize:
true
);
childrenWidth
+=
child
.
size
.
width
;
maxChildHeight
=
math
.
max
(
maxChildHeight
,
child
.
size
.
height
);
maxChildWidth
=
math
.
max
(
maxChildWidth
,
child
.
size
.
width
);
child
=
childAfter
(
child
);
}
final
bool
rtl
=
textDirection
==
TextDirection
.
rtl
;
final
double
actualWidth
=
childrenWidth
+
spacing
*
(
childCount
-
1
);
if
(
actualWidth
>
constraints
.
maxWidth
)
{
// Overflow vertical layout
child
=
overflowDirection
==
VerticalDirection
.
down
?
firstChild
:
lastChild
;
RenderBox
nextChild
()
=>
overflowDirection
==
VerticalDirection
.
down
?
childAfter
(
child
)
:
childBefore
(
child
);
double
y
=
0
;
while
(
child
!=
null
)
{
final
_OverflowBarParentData
childParentData
=
child
.
parentData
as
_OverflowBarParentData
;
double
x
=
0
;
switch
(
overflowAlignment
)
{
case
OverflowBarAlignment
.
start
:
x
=
rtl
?
constraints
.
maxWidth
-
child
.
size
.
width
:
0
;
break
;
case
OverflowBarAlignment
.
center
:
x
=
(
constraints
.
maxWidth
-
child
.
size
.
width
)
/
2
;
break
;
case
OverflowBarAlignment
.
end
:
x
=
rtl
?
0
:
constraints
.
maxWidth
-
child
.
size
.
width
;
break
;
}
assert
(
x
!=
null
);
childParentData
.
offset
=
Offset
(
x
,
y
);
y
+=
child
.
size
.
height
+
overflowSpacing
;
child
=
nextChild
();
}
size
=
constraints
.
constrain
(
Size
(
constraints
.
maxWidth
,
y
-
overflowSpacing
));
}
else
{
// Default horizontal layout
child
=
rtl
?
lastChild
:
firstChild
;
RenderBox
nextChild
()
=>
rtl
?
childBefore
(
child
)
:
childAfter
(
child
);
double
x
=
0
;
while
(
child
!=
null
)
{
final
_OverflowBarParentData
childParentData
=
child
.
parentData
as
_OverflowBarParentData
;
childParentData
.
offset
=
Offset
(
x
,
(
maxChildHeight
-
child
.
size
.
height
)
/
2
);
x
+=
child
.
size
.
width
+
spacing
;
child
=
nextChild
();
}
size
=
constraints
.
constrain
(
Size
(
actualWidth
,
maxChildHeight
));
}
}
@override
bool
hitTestChildren
(
BoxHitTestResult
result
,
{
Offset
position
})
{
return
defaultHitTestChildren
(
result
,
position:
position
);
}
@override
void
paint
(
PaintingContext
context
,
Offset
offset
)
{
defaultPaint
(
context
,
offset
);
}
@override
void
debugFillProperties
(
DiagnosticPropertiesBuilder
properties
)
{
super
.
debugFillProperties
(
properties
);
properties
.
add
(
DoubleProperty
(
'spacing'
,
spacing
,
defaultValue:
0
));
properties
.
add
(
DoubleProperty
(
'overflowSpacing'
,
overflowSpacing
,
defaultValue:
0
));
properties
.
add
(
EnumProperty
<
OverflowBarAlignment
>(
'overflowAlignment'
,
overflowAlignment
,
defaultValue:
OverflowBarAlignment
.
start
));
properties
.
add
(
EnumProperty
<
VerticalDirection
>(
'overflowDirection'
,
overflowDirection
,
defaultValue:
VerticalDirection
.
down
));
properties
.
add
(
EnumProperty
<
TextDirection
>(
'textDirection'
,
textDirection
,
defaultValue:
null
));
}
}
packages/flutter/lib/widgets.dart
View file @
6139708e
...
...
@@ -71,6 +71,7 @@ export 'src/widgets/navigator.dart';
export
'src/widgets/nested_scroll_view.dart'
;
export
'src/widgets/notification_listener.dart'
;
export
'src/widgets/orientation_builder.dart'
;
export
'src/widgets/overflow_bar.dart'
;
export
'src/widgets/overlay.dart'
;
export
'src/widgets/overscroll_indicator.dart'
;
export
'src/widgets/page_storage.dart'
;
...
...
packages/flutter/test/widgets/overflow_bar_test.dart
0 → 100644
View file @
6139708e
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter/widgets.dart'
;
void
main
(
)
{
testWidgets
(
'OverflowBar documented defaults'
,
(
WidgetTester
tester
)
async
{
final
OverflowBar
bar
=
OverflowBar
();
expect
(
bar
.
spacing
,
0
);
expect
(
bar
.
overflowSpacing
,
0
);
expect
(
bar
.
overflowDirection
,
VerticalDirection
.
down
);
expect
(
bar
.
textDirection
,
null
);
expect
(
bar
.
clipBehavior
,
Clip
.
none
);
expect
(
bar
.
children
,
const
<
Widget
>[]);
});
testWidgets
(
'Empty OverflowBar'
,
(
WidgetTester
tester
)
async
{
const
Size
size
=
Size
(
16
,
24
);
await
tester
.
pumpWidget
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
Center
(
child:
ConstrainedBox
(
constraints:
BoxConstraints
.
tight
(
size
),
child:
OverflowBar
(),
),
),
),
);
expect
(
tester
.
getSize
(
find
.
byType
(
OverflowBar
)),
size
);
await
tester
.
pumpWidget
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
Center
(
child:
OverflowBar
(),
),
),
);
expect
(
tester
.
getSize
(
find
.
byType
(
OverflowBar
)),
Size
.
zero
);
});
testWidgets
(
'OverflowBar horizontal layout'
,
(
WidgetTester
tester
)
async
{
final
Key
child1Key
=
UniqueKey
();
final
Key
child2Key
=
UniqueKey
();
final
Key
child3Key
=
UniqueKey
();
Widget
buildFrame
({
double
spacing
,
TextDirection
textDirection
})
{
return
Directionality
(
textDirection:
textDirection
,
child:
Align
(
alignment:
Alignment
.
topLeft
,
child:
OverflowBar
(
spacing:
spacing
,
children:
<
Widget
>[
SizedBox
(
width:
48
,
height:
48
,
key:
child1Key
),
SizedBox
(
width:
64
,
height:
64
,
key:
child2Key
),
SizedBox
(
width:
32
,
height:
32
,
key:
child3Key
),
],
),
),
);
}
// Children are vertically centered, start at x=0
await
tester
.
pumpWidget
(
buildFrame
(
spacing:
0
,
textDirection:
TextDirection
.
ltr
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child1Key
)),
const
Rect
.
fromLTRB
(
0
,
8
,
48
,
56
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child2Key
)),
const
Rect
.
fromLTRB
(
48
,
0
,
112
,
64
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child3Key
)),
const
Rect
.
fromLTRB
(
112
,
16
,
144
,
48
));
// Children are vertically centered, start at x=0
await
tester
.
pumpWidget
(
buildFrame
(
spacing:
10
,
textDirection:
TextDirection
.
ltr
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child1Key
)),
const
Rect
.
fromLTRB
(
0
,
8
,
48
,
56
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child2Key
)),
const
Rect
.
fromLTRB
(
10.0
+
48
,
0
,
10.0
+
112
,
64
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child3Key
)),
const
Rect
.
fromLTRB
(
10.0
+
112
+
10.0
,
16
,
10.0
+
10.0
+
144
,
48
));
// Children appear in reverse order for RTL
await
tester
.
pumpWidget
(
buildFrame
(
spacing:
0
,
textDirection:
TextDirection
.
rtl
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child3Key
)),
const
Rect
.
fromLTRB
(
0
,
16
,
32
,
48
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child2Key
)),
const
Rect
.
fromLTRB
(
32
,
0
,
96
,
64
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child1Key
)),
const
Rect
.
fromLTRB
(
96
,
8
,
144
,
56
));
// Children appear in reverse order for RTL
await
tester
.
pumpWidget
(
buildFrame
(
spacing:
10
,
textDirection:
TextDirection
.
rtl
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child3Key
)),
const
Rect
.
fromLTRB
(
0
,
16
,
32
,
48
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child2Key
)),
const
Rect
.
fromLTRB
(
10.0
+
32
,
0
,
10.0
+
96
,
64
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child1Key
)),
const
Rect
.
fromLTRB
(
10.0
+
96
+
10.0
,
8
,
10.0
+
10.0
+
144
,
56
));
});
testWidgets
(
'OverflowBar vertical layout'
,
(
WidgetTester
tester
)
async
{
final
Key
child1Key
=
UniqueKey
();
final
Key
child2Key
=
UniqueKey
();
final
Key
child3Key
=
UniqueKey
();
Widget
buildFrame
({
double
overflowSpacing
=
0
,
VerticalDirection
overflowDirection
=
VerticalDirection
.
down
,
OverflowBarAlignment
overflowAlignment
=
OverflowBarAlignment
.
start
,
TextDirection
textDirection
=
TextDirection
.
ltr
,
})
{
return
Directionality
(
textDirection:
textDirection
,
child:
Align
(
alignment:
Alignment
.
topLeft
,
child:
ConstrainedBox
(
constraints:
BoxConstraints
.
loose
(
const
Size
(
100
,
double
.
infinity
)),
child:
OverflowBar
(
overflowSpacing:
overflowSpacing
,
overflowAlignment:
overflowAlignment
,
overflowDirection:
overflowDirection
,
children:
<
Widget
>[
SizedBox
(
width:
48
,
height:
48
,
key:
child1Key
),
SizedBox
(
width:
64
,
height:
64
,
key:
child2Key
),
SizedBox
(
width:
32
,
height:
32
,
key:
child3Key
),
],
),
),
),
);
}
// Children are left aligned
await
tester
.
pumpWidget
(
buildFrame
());
expect
(
tester
.
getRect
(
find
.
byKey
(
child1Key
)),
const
Rect
.
fromLTRB
(
0
,
0
,
48
,
48
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child2Key
)),
const
Rect
.
fromLTRB
(
0
,
48
,
64
,
112
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child3Key
)),
const
Rect
.
fromLTRB
(
0
,
112
,
32
,
144
));
// Children are left aligned
await
tester
.
pumpWidget
(
buildFrame
(
overflowAlignment:
OverflowBarAlignment
.
end
,
textDirection:
TextDirection
.
rtl
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child1Key
)),
const
Rect
.
fromLTRB
(
0
,
0
,
48
,
48
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child2Key
)),
const
Rect
.
fromLTRB
(
0
,
48
,
64
,
112
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child3Key
)),
const
Rect
.
fromLTRB
(
0
,
112
,
32
,
144
));
// Spaced children are left aligned
await
tester
.
pumpWidget
(
buildFrame
(
overflowSpacing:
10
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child1Key
)),
const
Rect
.
fromLTRB
(
0
,
0
,
48
,
48
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child2Key
)),
const
Rect
.
fromLTRB
(
0
,
10.0
+
48
,
64
,
10.0
+
112
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child3Key
)),
const
Rect
.
fromLTRB
(
0
,
10.0
+
112
+
10.0
,
32
,
10.0
+
10.0
+
144
));
// Left-aligned children appear in reverse order for VerticalDirection.up
await
tester
.
pumpWidget
(
buildFrame
(
overflowDirection:
VerticalDirection
.
up
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child3Key
)),
const
Rect
.
fromLTRB
(
0
,
0
,
32
,
32
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child2Key
)),
const
Rect
.
fromLTRB
(
0
,
32
,
64
,
96
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child1Key
)),
const
Rect
.
fromLTRB
(
0
,
96
,
48
,
144
));
// Left-aligned spaced children appear in reverse order for VerticalDirection.up
await
tester
.
pumpWidget
(
buildFrame
(
overflowSpacing:
10
,
overflowDirection:
VerticalDirection
.
up
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child3Key
)),
const
Rect
.
fromLTRB
(
0
,
0
,
32
,
32
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child2Key
)),
const
Rect
.
fromLTRB
(
0
,
10.0
+
32
,
64
,
10.0
+
96
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child1Key
)),
const
Rect
.
fromLTRB
(
0
,
10.0
+
10.0
+
96
,
48
,
10.0
+
10.0
+
144
));
// Children are right aligned
await
tester
.
pumpWidget
(
buildFrame
(
overflowAlignment:
OverflowBarAlignment
.
end
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child1Key
)),
const
Rect
.
fromLTRB
(
100.0
-
48
,
0
,
100
,
48
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child2Key
)),
const
Rect
.
fromLTRB
(
100.0
-
64
,
48
,
100
,
112
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child3Key
)),
const
Rect
.
fromLTRB
(
100.0
-
32
,
112
,
100
,
144
));
// Children are right aligned
await
tester
.
pumpWidget
(
buildFrame
(
overflowAlignment:
OverflowBarAlignment
.
start
,
textDirection:
TextDirection
.
rtl
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child1Key
)),
const
Rect
.
fromLTRB
(
100.0
-
48
,
0
,
100
,
48
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child2Key
)),
const
Rect
.
fromLTRB
(
100.0
-
64
,
48
,
100
,
112
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child3Key
)),
const
Rect
.
fromLTRB
(
100.0
-
32
,
112
,
100
,
144
));
// Children are centered
await
tester
.
pumpWidget
(
buildFrame
(
overflowAlignment:
OverflowBarAlignment
.
center
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child1Key
)),
const
Rect
.
fromLTRB
(
100.0
/
2.0
-
48
/
2
,
0
,
100.0
/
2.0
+
48
/
2
,
48
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child2Key
)),
const
Rect
.
fromLTRB
(
100.0
/
2.0
-
64
/
2
,
48
,
100.0
/
2.0
+
64
/
2
,
112
));
expect
(
tester
.
getRect
(
find
.
byKey
(
child3Key
)),
const
Rect
.
fromLTRB
(
100.0
/
2.0
-
32
/
2
,
112
,
100.0
/
2.0
+
32
/
2
,
144
));
});
testWidgets
(
'OverflowBar intrinsic width'
,
(
WidgetTester
tester
)
async
{
Widget
buildFrame
({
double
width
})
{
return
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
Center
(
child:
Container
(
width:
width
,
alignment:
Alignment
.
topLeft
,
child:
IntrinsicWidth
(
child:
OverflowBar
(
spacing:
4
,
overflowSpacing:
8
,
children:
const
<
Widget
>[
SizedBox
(
width:
48
,
height:
50
),
SizedBox
(
width:
64
,
height:
25
),
SizedBox
(
width:
32
,
height:
75
),
],
),
),
),
),
);
}
await
tester
.
pumpWidget
(
buildFrame
(
width:
800
));
expect
(
tester
.
getSize
(
find
.
byType
(
OverflowBar
)).
width
,
152
);
// 152 = 48 + 4 + 64 + 4 + 32
await
tester
.
pumpWidget
(
buildFrame
(
width:
150
));
expect
(
tester
.
getSize
(
find
.
byType
(
OverflowBar
)).
width
,
150
);
});
testWidgets
(
'OverflowBar intrinsic height'
,
(
WidgetTester
tester
)
async
{
Widget
buildFrame
({
double
maxWidth
})
{
return
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
Center
(
child:
Container
(
width:
maxWidth
,
alignment:
Alignment
.
topLeft
,
child:
IntrinsicHeight
(
child:
OverflowBar
(
spacing:
4
,
overflowSpacing:
8
,
children:
const
<
Widget
>[
SizedBox
(
width:
48
,
height:
50
),
SizedBox
(
width:
64
,
height:
25
),
SizedBox
(
width:
32
,
height:
75
),
],
),
),
),
),
);
}
await
tester
.
pumpWidget
(
buildFrame
(
maxWidth:
800
));
expect
(
tester
.
getSize
(
find
.
byType
(
OverflowBar
)).
height
,
75
);
// 75 = max(50, 25, 75)
await
tester
.
pumpWidget
(
buildFrame
(
maxWidth:
150
));
expect
(
tester
.
getSize
(
find
.
byType
(
OverflowBar
)).
height
,
166
);
// 166 = 50 + 8 + 25 + 8 + 75
});
}
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