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
8ce2f859
Commit
8ce2f859
authored
Apr 24, 2016
by
Adam Barth
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3516 from abarth/tweaks
Add Flow layout
parents
9d900ea7
f53a5a52
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
643 additions
and
24 deletions
+643
-24
rendering.dart
packages/flutter/lib/rendering.dart
+1
-0
snack_bar.dart
packages/flutter/lib/src/material/snack_bar.dart
+1
-1
box.dart
packages/flutter/lib/src/rendering/box.dart
+14
-3
flex.dart
packages/flutter/lib/src/rendering/flex.dart
+1
-1
flow.dart
packages/flutter/lib/src/rendering/flow.dart
+388
-0
proxy_box.dart
packages/flutter/lib/src/rendering/proxy_box.dart
+10
-3
shifted_box.dart
packages/flutter/lib/src/rendering/shifted_box.dart
+6
-6
stack.dart
packages/flutter/lib/src/rendering/stack.dart
+5
-1
image_resource.dart
packages/flutter/lib/src/services/image_resource.dart
+1
-1
basic.dart
packages/flutter/lib/src/widgets/basic.dart
+126
-8
flow_test.dart
packages/flutter/test/widget/flow_test.dart
+90
-0
No files found.
packages/flutter/lib/rendering.dart
View file @
8ce2f859
...
...
@@ -30,6 +30,7 @@ export 'src/rendering/debug.dart';
export
'src/rendering/editable_line.dart'
;
export
'src/rendering/error.dart'
;
export
'src/rendering/flex.dart'
;
export
'src/rendering/flow.dart'
;
export
'src/rendering/grid.dart'
;
export
'src/rendering/image.dart'
;
export
'src/rendering/layer.dart'
;
...
...
packages/flutter/lib/src/material/snack_bar.dart
View file @
8ce2f859
...
...
@@ -51,7 +51,7 @@ class SnackBarAction extends StatefulWidget {
/// The button label.
final
String
label
;
/// The callback to be invoked when the button is pressed. Must
be non-
null.
/// The callback to be invoked when the button is pressed. Must
not be
null.
///
/// This callback will be invoked at most once each time this action is
/// displayed in a [SnackBar].
...
...
packages/flutter/lib/src/rendering/box.dart
View file @
8ce2f859
...
...
@@ -1049,7 +1049,7 @@ abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare
/// appear in the child list.
double
defaultComputeDistanceToFirstActualBaseline
(
TextBaseline
baseline
)
{
assert
(!
needsLayout
);
RenderBox
child
=
firstChild
;
ChildType
child
=
firstChild
;
while
(
child
!=
null
)
{
final
ParentDataType
childParentData
=
child
.
parentData
;
double
result
=
child
.
getDistanceToActualBaseline
(
baseline
);
...
...
@@ -1067,7 +1067,7 @@ abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare
double
defaultComputeDistanceToHighestActualBaseline
(
TextBaseline
baseline
)
{
assert
(!
needsLayout
);
double
result
;
RenderBox
child
=
firstChild
;
ChildType
child
=
firstChild
;
while
(
child
!=
null
)
{
final
ParentDataType
childParentData
=
child
.
parentData
;
double
candidate
=
child
.
getDistanceToActualBaseline
(
baseline
);
...
...
@@ -1103,13 +1103,24 @@ abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare
/// Paints each child by walking the child list forwards.
void
defaultPaint
(
PaintingContext
context
,
Offset
offset
)
{
RenderBox
child
=
firstChild
;
ChildType
child
=
firstChild
;
while
(
child
!=
null
)
{
final
ParentDataType
childParentData
=
child
.
parentData
;
context
.
paintChild
(
child
,
childParentData
.
offset
+
offset
);
child
=
childParentData
.
nextSibling
;
}
}
List
<
ChildType
>
getChildrenAsList
()
{
List
<
ChildType
>
result
=
<
ChildType
>[];
RenderBox
child
=
firstChild
;
while
(
child
!=
null
)
{
final
ParentDataType
childParentData
=
child
.
parentData
;
result
.
add
(
child
);
child
=
childParentData
.
nextSibling
;
}
return
result
;
}
}
class
FractionalOffsetTween
extends
Tween
<
FractionalOffset
>
{
...
...
packages/flutter/lib/src/rendering/flex.dart
View file @
8ce2f859
...
...
@@ -7,7 +7,7 @@ import 'dart:math' as math;
import
'box.dart'
;
import
'object.dart'
;
/// Parent data for use with [RenderFlex]
/// Parent data for use with [RenderFlex]
.
class
FlexParentData
extends
ContainerBoxParentDataMixin
<
RenderBox
>
{
/// The flex factor to use for this child
///
...
...
packages/flutter/lib/src/rendering/flow.dart
0 → 100644
View file @
8ce2f859
This diff is collapsed.
Click to expand it.
packages/flutter/lib/src/rendering/proxy_box.dart
View file @
8ce2f859
...
...
@@ -806,6 +806,7 @@ abstract class CustomClipper<T> {
/// Returns a description of the clip given that the render object being
/// clipped is of the given size.
T
getClip
(
Size
size
);
/// Returns an approximation of the clip returned by [getClip], as
/// an axis-aligned Rect. This is used by the semantics layer to
/// determine whether widgets should be excluded.
...
...
@@ -815,6 +816,7 @@ abstract class CustomClipper<T> {
/// same size as the RenderObject (e.g. it's a rounded rectangle
/// with very small arcs in the corners), then this may be adequate.
Rect
getApproximateClipRect
(
Size
size
)
=>
Point
.
origin
&
size
;
/// Returns `true` if the new instance will result in a different clip
/// than the oldClipper instance.
bool
shouldRepaint
(
CustomClipper
<
T
>
oldClipper
);
...
...
@@ -995,7 +997,10 @@ enum DecorationPosition {
/// Paints a [Decoration] either before or after its child paints.
class
RenderDecoratedBox
extends
RenderProxyBox
{
/// Creates a decorated box.
///
/// Both the [decoration] and the [position] arguments are required. By
/// default the decoration paints behind the child.
RenderDecoratedBox
({
Decoration
decoration
,
DecorationPosition
position:
DecorationPosition
.
background
,
...
...
@@ -1010,6 +1015,8 @@ class RenderDecoratedBox extends RenderProxyBox {
BoxPainter
_painter
;
/// What decoration to paint.
///
/// Commonly a [BoxDecoration].
Decoration
get
decoration
=>
_decoration
;
Decoration
_decoration
;
void
set
decoration
(
Decoration
newDecoration
)
{
...
...
@@ -1023,7 +1030,7 @@ class RenderDecoratedBox extends RenderProxyBox {
markNeedsPaint
();
}
/// Whe
re to paint the box decoration
.
/// Whe
ther to paint the box decoration behind or in front of the child
.
DecorationPosition
get
position
=>
_position
;
DecorationPosition
_position
;
void
set
position
(
DecorationPosition
newPosition
)
{
...
...
@@ -1118,7 +1125,7 @@ class RenderTransform extends RenderProxyBox {
/// The alignment of the origin, relative to the size of the box.
///
/// This is equivalent to setting an origin based on the size of the box.
/// If it is specifi
c
ed at the same time as an offset, both are applied.
/// If it is specified at the same time as an offset, both are applied.
FractionalOffset
get
alignment
=>
_alignment
;
FractionalOffset
_alignment
;
void
set
alignment
(
FractionalOffset
newAlignment
)
{
...
...
packages/flutter/lib/src/rendering/shifted_box.dart
View file @
8ce2f859
...
...
@@ -221,7 +221,7 @@ class RenderPadding extends RenderShiftedBox {
abstract
class
RenderAligningShiftedBox
extends
RenderShiftedBox
{
RenderAligningShiftedBox
({
RenderBox
child
,
FractionalOffset
alignment:
const
FractionalOffset
(
0.5
,
0.5
)
FractionalOffset
alignment:
FractionalOffset
.
center
})
:
_alignment
=
alignment
,
super
(
child
)
{
assert
(
alignment
!=
null
&&
alignment
.
dx
!=
null
&&
alignment
.
dy
!=
null
);
...
...
@@ -277,7 +277,7 @@ abstract class RenderAligningShiftedBox extends RenderShiftedBox {
///
/// For example, to align a box at the bottom right, you would pass this box a
/// tight constraint that is bigger than the child's natural size,
/// with an alignment of [
const FractionalOffset(1.0, 1.0)
].
/// with an alignment of [
FractionalOffset.bottomRight
].
///
/// By default, sizes to be as big as possible in both axes. If either axis is
/// unconstrained, then in that direction it will be sized to fit the child's
...
...
@@ -288,7 +288,7 @@ class RenderPositionedBox extends RenderAligningShiftedBox {
RenderBox
child
,
double
widthFactor
,
double
heightFactor
,
FractionalOffset
alignment:
const
FractionalOffset
(
0.5
,
0.5
)
FractionalOffset
alignment:
FractionalOffset
.
center
})
:
_widthFactor
=
widthFactor
,
_heightFactor
=
heightFactor
,
super
(
child:
child
,
alignment:
alignment
)
{
...
...
@@ -432,7 +432,7 @@ class RenderConstrainedOverflowBox extends RenderAligningShiftedBox {
double
maxWidth
,
double
minHeight
,
double
maxHeight
,
FractionalOffset
alignment:
const
FractionalOffset
(
0.5
,
0.5
)
FractionalOffset
alignment:
FractionalOffset
.
center
})
:
_minWidth
=
minWidth
,
_maxWidth
=
maxWidth
,
_minHeight
=
minHeight
,
...
...
@@ -548,7 +548,7 @@ class RenderSizedOverflowBox extends RenderAligningShiftedBox {
RenderSizedOverflowBox
({
RenderBox
child
,
Size
requestedSize
,
FractionalOffset
alignment:
const
FractionalOffset
(
0.5
,
0.5
)
FractionalOffset
alignment:
FractionalOffset
.
center
})
:
_requestedSize
=
requestedSize
,
super
(
child:
child
,
alignment:
alignment
)
{
assert
(
requestedSize
!=
null
);
...
...
@@ -620,7 +620,7 @@ class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
RenderBox
child
,
double
widthFactor
,
double
heightFactor
,
FractionalOffset
alignment:
const
FractionalOffset
(
0.5
,
0.5
)
FractionalOffset
alignment:
FractionalOffset
.
center
})
:
_widthFactor
=
widthFactor
,
_heightFactor
=
heightFactor
,
super
(
child:
child
,
alignment:
alignment
)
{
...
...
packages/flutter/lib/src/rendering/stack.dart
View file @
8ce2f859
...
...
@@ -133,7 +133,7 @@ class RelativeRect {
String
toString
()
=>
"RelativeRect.fromLTRB(
${left?.toStringAsFixed(1)}
,
${top?.toStringAsFixed(1)}
,
${right?.toStringAsFixed(1)}
,
${bottom?.toStringAsFixed(1)}
)"
;
}
/// Parent data for use with [RenderStack]
/// Parent data for use with [RenderStack]
.
class
StackParentData
extends
ContainerBoxParentDataMixin
<
RenderBox
>
{
/// The distance by which the child's top edge is inset from the top of the stack.
double
top
;
...
...
@@ -437,6 +437,10 @@ abstract class RenderStackBase extends RenderBox
/// edge of the stack. If the child extends beyond the bounds of the
/// stack, the stack will clip the child's painting to the bounds of
/// the stack.
///
/// See also:
///
/// * [RenderFlow]
class
RenderStack
extends
RenderStackBase
{
RenderStack
({
List
<
RenderBox
>
children
,
...
...
packages/flutter/lib/src/services/image_resource.dart
View file @
8ce2f859
...
...
@@ -14,7 +14,7 @@ import 'package:flutter/foundation.dart';
class
ImageInfo
{
/// Creates an [ImageInfo] object for the given image and scale.
///
/// Both the image and the scale must
be non-
null.
/// Both the image and the scale must
not be
null.
ImageInfo
({
this
.
image
,
this
.
scale
:
1.0
})
{
assert
(
image
!=
null
);
assert
(
scale
!=
null
);
...
...
packages/flutter/lib/src/widgets/basic.dart
View file @
8ce2f859
...
...
@@ -21,6 +21,8 @@ export 'package:flutter/rendering.dart' show
CustomPainter
,
FixedColumnCountGridDelegate
,
FlexDirection
,
FlowDelegate
,
FlowPaintingContext
,
FractionalOffsetTween
,
GridDelegate
,
GridDelegateWithInOrderChildPlacement
,
...
...
@@ -165,7 +167,7 @@ class DecoratedBox extends SingleChildRenderObjectWidget {
/// Commonly a [BoxDecoration].
final
Decoration
decoration
;
/// Whe
re to paint the box decoration
.
/// Whe
ther to paint the box decoration behind or in front of the child
.
final
DecorationPosition
position
;
@override
...
...
@@ -431,16 +433,25 @@ class Padding extends SingleChildRenderObjectWidget {
///
/// For example, to align a box at the bottom right, you would pass this box a
/// tight constraint that is bigger than the child's natural size,
/// with an alignment of [
const FractionalOffset(1.0, 1.0)
].
/// with an alignment of [
FractionalOffset.bottomRight
].
///
/// By default, sizes to be as big as possible in both axes. If either axis is
/// unconstrained, then in that direction it will be sized to fit the child's
/// dimensions. Using widthFactor and heightFactor you can force this latter
/// behavior in all cases.
///
/// See also:
///
/// * [CustomSingleChildLayout]
/// * [Center] (which is the same as [Align] but with the [alignment] always
/// set to [FractionalOffset.center])
class
Align
extends
SingleChildRenderObjectWidget
{
/// Creates an alignment widget.
///
/// The alignment defaults to [FractionalOffset.center].
Align
({
Key
key
,
this
.
alignment
:
const
FractionalOffset
(
0.5
,
0.5
)
,
this
.
alignment
:
FractionalOffset
.
center
,
this
.
widthFactor
,
this
.
heightFactor
,
Widget
child
...
...
@@ -494,6 +505,10 @@ class Align extends SingleChildRenderObjectWidget {
}
/// Centers its child within itself.
///
/// See also:
///
/// * [Align]
class
Center
extends
Align
{
Center
({
Key
key
,
double
widthFactor
,
double
heightFactor
,
Widget
child
})
:
super
(
key:
key
,
widthFactor:
widthFactor
,
heightFactor:
heightFactor
,
child:
child
);
...
...
@@ -505,7 +520,17 @@ class Center extends Align {
/// decide where to position the child. The delegate can also determine the size
/// of the parent, but the size of the parent cannot depend on the size of the
/// child.
///
/// See also:
///
/// * [SingleChildLayoutDelegate]
/// * [Align] (which positions a single child according to a [FractionalOffset])
/// * [CustomMultiChildLayout] (which uses a delegate to position multiple
/// children)
class
CustomSingleChildLayout
extends
SingleChildRenderObjectWidget
{
/// Creates a custom single child layout.
///
/// The delegate argument must not be null.
CustomSingleChildLayout
({
Key
key
,
this
.
delegate
,
...
...
@@ -514,6 +539,7 @@ class CustomSingleChildLayout extends SingleChildRenderObjectWidget {
assert
(
delegate
!=
null
);
}
/// The delegate that controls the layout of the child.
final
SingleChildLayoutDelegate
delegate
;
@override
...
...
@@ -527,6 +553,9 @@ class CustomSingleChildLayout extends SingleChildRenderObjectWidget {
/// Metadata for identifying children in a [CustomMultiChildLayout].
class
LayoutId
extends
ParentDataWidget
<
CustomMultiChildLayout
>
{
/// Marks a child with a layout identifier.
///
/// Both the child and the id arguments must not be null.
LayoutId
({
Key
key
,
Widget
child
,
...
...
@@ -566,7 +595,17 @@ const List<Widget> _emptyWidgetList = const <Widget>[];
/// decide where to position each child. The delegate can also determine the
/// size of the parent, but the size of the parent cannot depend on the sizes of
/// the children.
///
/// See also:
///
/// * [MultiChildLayoutDelegate]
/// * [CustomSingleChildLayout]
/// * [Stack]
/// * [Flow]
class
CustomMultiChildLayout
extends
MultiChildRenderObjectWidget
{
/// Creates a custom multi-child layout.
///
/// The delegate argument must not be null.
CustomMultiChildLayout
({
Key
key
,
List
<
Widget
>
children:
_emptyWidgetList
,
...
...
@@ -667,7 +706,7 @@ class ConstrainedBox extends SingleChildRenderObjectWidget {
class
FractionallySizedBox
extends
SingleChildRenderObjectWidget
{
FractionallySizedBox
({
Key
key
,
this
.
alignment
:
const
FractionalOffset
(
0.5
,
0.5
)
,
this
.
alignment
:
FractionalOffset
.
center
,
this
.
width
,
this
.
height
,
Widget
child
...
...
@@ -772,7 +811,7 @@ class LimitedBox extends SingleChildRenderObjectWidget {
class
OverflowBox
extends
SingleChildRenderObjectWidget
{
OverflowBox
({
Key
key
,
this
.
alignment
:
const
FractionalOffset
(
0.5
,
0.5
)
,
this
.
alignment
:
FractionalOffset
.
center
,
this
.
minWidth
,
this
.
maxWidth
,
this
.
minHeight
,
...
...
@@ -844,7 +883,7 @@ class OverflowBox extends SingleChildRenderObjectWidget {
class
SizedOverflowBox
extends
SingleChildRenderObjectWidget
{
SizedOverflowBox
({
Key
key
,
this
.
alignment
:
const
FractionalOffset
(
0.5
,
0.5
)
,
this
.
alignment
:
FractionalOffset
.
center
,
this
.
size
,
Widget
child
})
:
super
(
key:
key
,
child:
child
)
{
...
...
@@ -1265,11 +1304,18 @@ abstract class StackRenderObjectWidgetBase extends MultiChildRenderObjectWidget
/// For more details about the stack layout algorithm, see
/// [RenderStack]. To control the position of child widgets, see the
/// [Positioned] widget.
///
/// See also:
///
/// * [Flow]
/// * [Align] (which positions a single child according to a [FractionalOffset])
/// * [CustomSingleChildLayout]
/// * [CustomMultiChildLayout]
class
Stack
extends
StackRenderObjectWidgetBase
{
Stack
({
Key
key
,
List
<
Widget
>
children:
_emptyWidgetList
,
this
.
alignment
:
const
FractionalOffset
(
0.0
,
0.0
)
this
.
alignment
:
FractionalOffset
.
topLeft
})
:
super
(
key:
key
,
children:
children
);
/// How to align the non-positioned children in the stack.
...
...
@@ -1289,7 +1335,7 @@ class IndexedStack extends StackRenderObjectWidgetBase {
IndexedStack
({
Key
key
,
List
<
Widget
>
children:
_emptyWidgetList
,
this
.
alignment
:
const
FractionalOffset
(
0.0
,
0.0
)
,
this
.
alignment
:
FractionalOffset
.
topLeft
,
this
.
index
:
0
})
:
super
(
key:
key
,
children:
children
)
{
assert
(
index
!=
null
);
...
...
@@ -1718,6 +1764,71 @@ class Flexible extends ParentDataWidget<Flex> {
}
}
/// Implements the flow layout algorithm.
///
/// Flow layouts are optimized for repositioning children using transformation
/// matrices.
///
/// The flow container is sized independently from the children by the
/// [FlowDelegate.getSize] function of the delegate. The children are then sized
/// independently given the constraints from the
/// [FlowDelegate.getConstraintsForChild] function.
///
/// Rather than positioning the children during layout, the children are
/// positioned using transformation matrices during the paint phase using the
/// matrices from the [FlowDelegate.paintChildren] function. The children can be
/// repositioned efficiently by simply repainting the flow.
///
/// The most efficient way to trigger a repaint of the flow is to supply a
/// repaint argument to the constructor of the [FlowDelegate]. The flow will
/// listen to this animation and repaint whenever the animation ticks, avoiding
/// both the build and layout phases of the pipeline.
///
/// See also:
///
/// * [FlowDelegate]
/// * [Stack]
/// * [CustomSingleChildLayout]
/// * [CustomMultiChildLayout]
class
Flow
extends
MultiChildRenderObjectWidget
{
/// Creates a flow layout.
///
/// Wraps each of the given children in a [RepaintBoundary] to avoid
/// repainting the children when the flow repaints.
Flow
({
Key
key
,
List
<
Widget
>
children:
_emptyWidgetList
,
this
.
delegate
})
:
super
(
key:
key
,
children:
RepaintBoundary
.
wrapAll
(
children
))
{
assert
(
delegate
!=
null
);
}
/// Creates a flow layout.
///
/// Does not wrap the given children in repaint boundaries, unlike the default
/// constructor. Useful when the child is trivial to paint or already contains
/// a repaint boundary.
Flow
.
unwrapped
({
Key
key
,
List
<
Widget
>
children:
_emptyWidgetList
,
this
.
delegate
})
:
super
(
key:
key
,
children:
children
)
{
assert
(
delegate
!=
null
);
}
/// The delegate that controls the transformation matrices of the children.
final
FlowDelegate
delegate
;
@override
RenderFlow
createRenderObject
(
BuildContext
context
)
=>
new
RenderFlow
(
delegate:
delegate
);
@override
void
updateRenderObject
(
BuildContext
context
,
RenderFlow
renderObject
)
{
renderObject
..
delegate
=
delegate
;
}
}
/// A paragraph of rich text.
///
/// The [RichText] widget displays text that uses multiple different styles. The
...
...
@@ -2571,6 +2682,13 @@ class RepaintBoundary extends SingleChildRenderObjectWidget {
return
new
RepaintBoundary
(
key:
key
,
child:
child
);
}
static
List
<
RepaintBoundary
>
wrapAll
(
List
<
Widget
>
widgets
)
{
List
<
RepaintBoundary
>
result
=
new
List
<
RepaintBoundary
>(
widgets
.
length
);
for
(
int
i
=
0
;
i
<
result
.
length
;
++
i
)
result
[
i
]
=
new
RepaintBoundary
.
wrap
(
widgets
[
i
],
i
);
return
result
;
}
@override
RenderRepaintBoundary
createRenderObject
(
BuildContext
context
)
=>
new
RenderRepaintBoundary
();
}
...
...
packages/flutter/test/widget/flow_test.dart
0 → 100644
View file @
8ce2f859
// Copyright 2015 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/widgets.dart'
;
import
'package:test/test.dart'
;
class
TestFlowDelegate
extends
FlowDelegate
{
TestFlowDelegate
({
Animation
<
double
>
startOffset
})
:
startOffset
=
startOffset
,
super
(
repaint:
startOffset
);
final
Animation
<
double
>
startOffset
;
@override
BoxConstraints
getConstraintsForChild
(
int
i
,
BoxConstraints
constraints
)
{
return
constraints
.
loosen
();
}
@override
void
paintChildren
(
FlowPaintingContext
context
)
{
double
dy
=
startOffset
.
value
;
for
(
int
i
=
0
;
i
<
context
.
childCount
;
++
i
)
{
context
.
paintChild
(
i
,
transform:
new
Matrix4
.
translationValues
(
0.0
,
dy
,
0.0
));
dy
+=
0.75
*
context
.
getChildSize
(
i
).
height
;
}
}
@override
bool
shouldRepaint
(
TestFlowDelegate
oldDelegate
)
=>
startOffset
==
oldDelegate
.
startOffset
;
}
void
main
(
)
{
test
(
'Flow control test'
,
()
{
testWidgets
((
WidgetTester
tester
)
{
AnimationController
startOffset
=
new
AnimationController
.
unbounded
();
List
<
int
>
log
=
<
int
>[];
Widget
buildBox
(
int
i
)
{
return
new
GestureDetector
(
onTap:
()
{
log
.
add
(
i
);
},
child:
new
Container
(
width:
100.0
,
height:
100.0
,
decoration:
const
BoxDecoration
(
backgroundColor:
const
Color
(
0xFF0000FF
)
),
child:
new
Text
(
'
$i
'
)
)
);
}
tester
.
pumpWidget
(
new
Flow
(
delegate:
new
TestFlowDelegate
(
startOffset:
startOffset
),
children:
<
Widget
>[
buildBox
(
0
),
buildBox
(
1
),
buildBox
(
2
),
buildBox
(
3
),
buildBox
(
4
),
buildBox
(
5
),
buildBox
(
6
),
]
)
);
tester
.
tap
(
find
.
text
(
'0'
));
expect
(
log
,
equals
([
0
]));
tester
.
tap
(
find
.
text
(
'1'
));
expect
(
log
,
equals
([
0
,
1
]));
tester
.
tap
(
find
.
text
(
'2'
));
expect
(
log
,
equals
([
0
,
1
,
2
]));
log
.
clear
();
tester
.
tapAt
(
new
Point
(
20.0
,
90.0
));
expect
(
log
,
equals
([
1
]));
startOffset
.
value
=
50.0
;
tester
.
pump
();
log
.
clear
();
tester
.
tapAt
(
new
Point
(
20.0
,
90.0
));
expect
(
log
,
equals
([
0
]));
});
});
}
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