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
236acb52
Unverified
Commit
236acb52
authored
Jul 10, 2018
by
Natalie Sampsell
Committed by
GitHub
Jul 10, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Segmented control animation (#18811)
Added animation to segmented control widget.
parent
03a1f4ac
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
722 additions
and
327 deletions
+722
-327
segmented_control.dart
packages/flutter/lib/src/cupertino/segmented_control.dart
+154
-29
segmented_control_test.dart
packages/flutter/test/cupertino/segmented_control_test.dart
+568
-298
No files found.
packages/flutter/lib/src/cupertino/segmented_control.dart
View file @
236acb52
...
@@ -23,6 +23,10 @@ const double _kMinSegmentedControlHeight = 28.0;
...
@@ -23,6 +23,10 @@ const double _kMinSegmentedControlHeight = 28.0;
// press or drag.
// press or drag.
const
Color
_kPressedBackground
=
const
Color
(
0x33007aff
);
const
Color
_kPressedBackground
=
const
Color
(
0x33007aff
);
// The duration of the fade animation used to transition when a new widget
// is selected.
const
Duration
_kFadeDuration
=
const
Duration
(
milliseconds:
165
);
/// An iOS-style segmented control.
/// An iOS-style segmented control.
///
///
/// Displays the widgets provided in the [Map] of [children] in a
/// Displays the widgets provided in the [Map] of [children] in a
...
@@ -147,19 +151,68 @@ class SegmentedControl<T> extends StatefulWidget {
...
@@ -147,19 +151,68 @@ class SegmentedControl<T> extends StatefulWidget {
_SegmentedControlState
<
T
>
createState
()
=>
_SegmentedControlState
<
T
>();
_SegmentedControlState
<
T
>
createState
()
=>
_SegmentedControlState
<
T
>();
}
}
class
_SegmentedControlState
<
T
>
extends
State
<
SegmentedControl
<
T
>>
{
class
_SegmentedControlState
<
T
>
extends
State
<
SegmentedControl
<
T
>>
with
TickerProviderStateMixin
<
SegmentedControl
<
T
>>
{
T
_pressedKey
;
T
_pressedKey
;
void
_onTapDown
(
T
currentKey
)
{
final
List
<
AnimationController
>
_selectionControllers
=
<
AnimationController
>[];
setState
(()
{
final
List
<
ColorTween
>
_childTweens
=
<
ColorTween
>[];
_pressedKey
=
currentKey
;
});
static
final
ColorTween
forwardBackgroundColorTween
=
new
ColorTween
(
begin:
_kPressedBackground
,
end:
CupertinoColors
.
activeBlue
,
);
static
final
ColorTween
reverseBackgroundColorTween
=
new
ColorTween
(
begin:
CupertinoColors
.
white
,
end:
CupertinoColors
.
activeBlue
,
);
static
final
ColorTween
textColorTween
=
new
ColorTween
(
begin:
CupertinoColors
.
activeBlue
,
end:
CupertinoColors
.
white
,
);
@override
void
initState
()
{
super
.
initState
();
for
(
T
key
in
widget
.
children
.
keys
)
{
final
AnimationController
animationController
=
createAnimationController
();
if
(
widget
.
groupValue
==
key
)
{
_childTweens
.
add
(
reverseBackgroundColorTween
);
animationController
.
value
=
1.0
;
}
else
{
_childTweens
.
add
(
forwardBackgroundColorTween
);
}
_selectionControllers
.
add
(
animationController
);
}
}
}
void
_onTapUp
(
TapUpDetails
event
)
{
AnimationController
createAnimationController
()
{
setState
(()
{
return
new
AnimationController
(
_pressedKey
=
null
;
duration:
_kFadeDuration
,
});
vsync:
this
,
)..
addListener
(()
{
setState
(()
{
// State of background/text colors has changed
});
});
}
@override
void
dispose
()
{
for
(
AnimationController
animationController
in
_selectionControllers
)
{
animationController
.
dispose
();
}
super
.
dispose
();
}
void
_onTapDown
(
T
currentKey
)
{
if
(
_pressedKey
==
null
&&
currentKey
!=
widget
.
groupValue
)
{
setState
(()
{
_pressedKey
=
currentKey
;
});
}
}
}
void
_onTapCancel
()
{
void
_onTapCancel
()
{
...
@@ -169,14 +222,69 @@ class _SegmentedControlState<T> extends State<SegmentedControl<T>> {
...
@@ -169,14 +222,69 @@ class _SegmentedControlState<T> extends State<SegmentedControl<T>> {
}
}
void
_onTap
(
T
currentKey
)
{
void
_onTap
(
T
currentKey
)
{
if
(
currentKey
!=
widget
.
groupValue
)
{
if
(
currentKey
!=
widget
.
groupValue
&&
currentKey
==
_pressedKey
)
{
widget
.
onValueChanged
(
currentKey
);
widget
.
onValueChanged
(
currentKey
);
_pressedKey
=
null
;
}
}
Color
getTextColor
(
int
index
,
T
currentKey
)
{
if
(
_selectionControllers
[
index
].
isAnimating
)
return
textColorTween
.
evaluate
(
_selectionControllers
[
index
]);
if
(
widget
.
groupValue
==
currentKey
)
return
CupertinoColors
.
white
;
return
CupertinoColors
.
activeBlue
;
}
Color
getBackgroundColor
(
int
index
,
T
currentKey
)
{
if
(
_selectionControllers
[
index
].
isAnimating
)
return
_childTweens
[
index
].
evaluate
(
_selectionControllers
[
index
]);
if
(
widget
.
groupValue
==
currentKey
)
return
CupertinoColors
.
activeBlue
;
if
(
_pressedKey
==
currentKey
)
return
_kPressedBackground
;
return
CupertinoColors
.
white
;
}
void
updateAnimationControllers
()
{
if
(
_selectionControllers
.
length
>
widget
.
children
.
length
)
{
_selectionControllers
.
length
=
widget
.
children
.
length
;
_childTweens
.
length
=
widget
.
children
.
length
;
}
else
{
for
(
int
index
=
_selectionControllers
.
length
;
index
<
widget
.
children
.
length
;
index
+=
1
)
{
_selectionControllers
.
add
(
createAnimationController
());
_childTweens
.
add
(
reverseBackgroundColorTween
);
}
}
}
@override
void
didUpdateWidget
(
SegmentedControl
<
T
>
oldWidget
)
{
super
.
didUpdateWidget
(
oldWidget
);
if
(
oldWidget
.
children
.
length
!=
widget
.
children
.
length
)
{
updateAnimationControllers
();
}
if
(
oldWidget
.
groupValue
!=
widget
.
groupValue
)
{
int
index
=
0
;
for
(
T
key
in
widget
.
children
.
keys
)
{
if
(
widget
.
groupValue
==
key
)
{
_childTweens
[
index
]
=
forwardBackgroundColorTween
;
_selectionControllers
[
index
].
forward
();
}
else
{
_childTweens
[
index
]
=
reverseBackgroundColorTween
;
_selectionControllers
[
index
].
reverse
();
}
index
+=
1
;
}
}
}
}
}
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
final
List
<
Widget
>
gestureChildren
=
<
Widget
>[];
final
List
<
Widget
>
_gestureChildren
=
<
Widget
>[];
final
List
<
Color
>
_backgroundColors
=
<
Color
>[];
int
index
=
0
;
int
index
=
0
;
int
selectedIndex
;
int
selectedIndex
;
int
pressedIndex
;
int
pressedIndex
;
...
@@ -185,12 +293,10 @@ class _SegmentedControlState<T> extends State<SegmentedControl<T>> {
...
@@ -185,12 +293,10 @@ class _SegmentedControlState<T> extends State<SegmentedControl<T>> {
pressedIndex
=
(
_pressedKey
==
currentKey
)
?
index
:
pressedIndex
;
pressedIndex
=
(
_pressedKey
==
currentKey
)
?
index
:
pressedIndex
;
final
TextStyle
textStyle
=
DefaultTextStyle
.
of
(
context
).
style
.
copyWith
(
final
TextStyle
textStyle
=
DefaultTextStyle
.
of
(
context
).
style
.
copyWith
(
color:
(
widget
.
groupValue
==
currentKey
)
?
color:
getTextColor
(
index
,
currentKey
),
CupertinoColors
.
white
:
CupertinoColors
.
activeBlue
,
);
);
final
IconThemeData
iconTheme
=
new
IconThemeData
(
final
IconThemeData
iconTheme
=
new
IconThemeData
(
color:
(
widget
.
groupValue
==
currentKey
)
?
color:
getTextColor
(
index
,
currentKey
),
CupertinoColors
.
white
:
CupertinoColors
.
activeBlue
,
);
);
Widget
child
=
widget
.
children
[
currentKey
];
Widget
child
=
widget
.
children
[
currentKey
];
...
@@ -198,7 +304,6 @@ class _SegmentedControlState<T> extends State<SegmentedControl<T>> {
...
@@ -198,7 +304,6 @@ class _SegmentedControlState<T> extends State<SegmentedControl<T>> {
onTapDown:
(
TapDownDetails
event
)
{
onTapDown:
(
TapDownDetails
event
)
{
_onTapDown
(
currentKey
);
_onTapDown
(
currentKey
);
},
},
onTapUp:
_onTapUp
,
onTapCancel:
_onTapCancel
,
onTapCancel:
_onTapCancel
,
onTap:
()
{
onTap:
()
{
_onTap
(
currentKey
);
_onTap
(
currentKey
);
...
@@ -215,14 +320,17 @@ class _SegmentedControlState<T> extends State<SegmentedControl<T>> {
...
@@ -215,14 +320,17 @@ class _SegmentedControlState<T> extends State<SegmentedControl<T>> {
),
),
),
),
);
);
gestureChildren
.
add
(
child
);
_backgroundColors
.
add
(
getBackgroundColor
(
index
,
currentKey
));
_gestureChildren
.
add
(
child
);
index
+=
1
;
index
+=
1
;
}
}
final
Widget
box
=
new
_SegmentedControlRenderWidget
<
T
>(
final
Widget
box
=
new
_SegmentedControlRenderWidget
<
T
>(
children:
gestureChildren
,
children:
_
gestureChildren
,
selectedIndex:
selectedIndex
,
selectedIndex:
selectedIndex
,
pressedIndex:
pressedIndex
,
pressedIndex:
pressedIndex
,
backgroundColors:
_backgroundColors
,
);
);
return
new
Padding
(
return
new
Padding
(
...
@@ -241,6 +349,7 @@ class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
...
@@ -241,6 +349,7 @@ class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
List
<
Widget
>
children
=
const
<
Widget
>[],
List
<
Widget
>
children
=
const
<
Widget
>[],
@required
this
.
selectedIndex
,
@required
this
.
selectedIndex
,
@required
this
.
pressedIndex
,
@required
this
.
pressedIndex
,
@required
this
.
backgroundColors
,
})
:
super
(
})
:
super
(
key:
key
,
key:
key
,
children:
children
,
children:
children
,
...
@@ -248,6 +357,7 @@ class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
...
@@ -248,6 +357,7 @@ class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
final
int
selectedIndex
;
final
int
selectedIndex
;
final
int
pressedIndex
;
final
int
pressedIndex
;
final
List
<
Color
>
backgroundColors
;
@override
@override
RenderObject
createRenderObject
(
BuildContext
context
)
{
RenderObject
createRenderObject
(
BuildContext
context
)
{
...
@@ -255,6 +365,7 @@ class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
...
@@ -255,6 +365,7 @@ class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
textDirection:
Directionality
.
of
(
context
),
textDirection:
Directionality
.
of
(
context
),
selectedIndex:
selectedIndex
,
selectedIndex:
selectedIndex
,
pressedIndex:
pressedIndex
,
pressedIndex:
pressedIndex
,
backgroundColors:
backgroundColors
,
);
);
}
}
...
@@ -263,7 +374,8 @@ class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
...
@@ -263,7 +374,8 @@ class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
renderObject
renderObject
..
textDirection
=
Directionality
.
of
(
context
)
..
textDirection
=
Directionality
.
of
(
context
)
..
selectedIndex
=
selectedIndex
..
selectedIndex
=
selectedIndex
..
pressedIndex
=
pressedIndex
;
..
pressedIndex
=
pressedIndex
..
backgroundColors
=
backgroundColors
;
}
}
}
}
...
@@ -281,10 +393,12 @@ class _RenderSegmentedControl<T> extends RenderBox
...
@@ -281,10 +393,12 @@ class _RenderSegmentedControl<T> extends RenderBox
@required
int
selectedIndex
,
@required
int
selectedIndex
,
@required
int
pressedIndex
,
@required
int
pressedIndex
,
@required
TextDirection
textDirection
,
@required
TextDirection
textDirection
,
@required
List
<
Color
>
backgroundColors
,
})
:
assert
(
textDirection
!=
null
),
})
:
assert
(
textDirection
!=
null
),
_textDirection
=
textDirection
,
_textDirection
=
textDirection
,
_selectedIndex
=
selectedIndex
,
_selectedIndex
=
selectedIndex
,
_pressedIndex
=
pressedIndex
{
_pressedIndex
=
pressedIndex
,
_backgroundColors
=
backgroundColors
{
addAll
(
children
);
addAll
(
children
);
}
}
...
@@ -318,6 +432,16 @@ class _RenderSegmentedControl<T> extends RenderBox
...
@@ -318,6 +432,16 @@ class _RenderSegmentedControl<T> extends RenderBox
markNeedsLayout
();
markNeedsLayout
();
}
}
List
<
Color
>
get
backgroundColors
=>
_backgroundColors
;
List
<
Color
>
_backgroundColors
;
set
backgroundColors
(
List
<
Color
>
value
)
{
if
(
_backgroundColors
==
value
)
{
return
;
}
_backgroundColors
=
value
;
markNeedsPaint
();
}
final
Paint
_outlinePaint
=
new
Paint
()
final
Paint
_outlinePaint
=
new
Paint
()
..
color
=
CupertinoColors
.
activeBlue
..
color
=
CupertinoColors
.
activeBlue
..
strokeWidth
=
1.0
..
strokeWidth
=
1.0
...
@@ -481,17 +605,10 @@ class _RenderSegmentedControl<T> extends RenderBox
...
@@ -481,17 +605,10 @@ class _RenderSegmentedControl<T> extends RenderBox
final
_SegmentedControlContainerBoxParentData
childParentData
=
child
.
parentData
;
final
_SegmentedControlContainerBoxParentData
childParentData
=
child
.
parentData
;
Color
color
=
CupertinoColors
.
white
;
if
(
selectedIndex
!=
null
&&
selectedIndex
==
childIndex
)
{
color
=
CupertinoColors
.
activeBlue
;
}
else
if
(
pressedIndex
!=
null
&&
pressedIndex
==
childIndex
)
{
color
=
_kPressedBackground
;
}
context
.
canvas
.
drawRRect
(
context
.
canvas
.
drawRRect
(
childParentData
.
surroundingRect
.
shift
(
offset
),
childParentData
.
surroundingRect
.
shift
(
offset
),
new
Paint
()
new
Paint
()
..
color
=
color
..
color
=
backgroundColors
[
childIndex
]
..
style
=
PaintingStyle
.
fill
,
..
style
=
PaintingStyle
.
fill
,
);
);
context
.
canvas
.
drawRRect
(
context
.
canvas
.
drawRRect
(
...
@@ -505,6 +622,14 @@ class _RenderSegmentedControl<T> extends RenderBox
...
@@ -505,6 +622,14 @@ class _RenderSegmentedControl<T> extends RenderBox
@override
@override
bool
hitTestChildren
(
HitTestResult
result
,
{
@required
Offset
position
})
{
bool
hitTestChildren
(
HitTestResult
result
,
{
@required
Offset
position
})
{
assert
(
position
!=
null
);
assert
(
position
!=
null
);
return
defaultHitTestChildren
(
result
,
position:
position
);
RenderBox
child
=
lastChild
;
while
(
child
!=
null
)
{
final
_SegmentedControlContainerBoxParentData
childParentData
=
child
.
parentData
;
if
(
childParentData
.
surroundingRect
.
contains
(
position
))
{
return
child
.
hitTest
(
result
,
position:
(
Offset
.
zero
&
child
.
size
).
center
);
}
child
=
childParentData
.
previousSibling
;
}
return
false
;
}
}
}
}
packages/flutter/test/cupertino/segmented_control_test.dart
View file @
236acb52
...
@@ -8,7 +8,6 @@ import 'package:flutter/widgets.dart';
...
@@ -8,7 +8,6 @@ import 'package:flutter/widgets.dart';
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/cupertino.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'../rendering/mock_canvas.dart'
;
import
'../widgets/semantics_tester.dart'
;
import
'../widgets/semantics_tester.dart'
;
dynamic
getRenderSegmentedControl
(
WidgetTester
tester
)
{
dynamic
getRenderSegmentedControl
(
WidgetTester
tester
)
{
...
@@ -23,7 +22,6 @@ StatefulBuilder setupSimpleSegmentedControl() {
...
@@ -23,7 +22,6 @@ StatefulBuilder setupSimpleSegmentedControl() {
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
1
]
=
const
Text
(
'Child 2'
);
children
[
1
]
=
const
Text
(
'Child 2'
);
int
sharedValue
=
0
;
int
sharedValue
=
0
;
return
new
StatefulBuilder
(
return
new
StatefulBuilder
(
...
@@ -50,6 +48,10 @@ Widget boilerplate({Widget child}) {
...
@@ -50,6 +48,10 @@ Widget boilerplate({Widget child}) {
);
);
}
}
Color
getBackgroundColor
(
WidgetTester
tester
,
int
childIndex
)
{
return
getRenderSegmentedControl
(
tester
).
backgroundColors
[
childIndex
];
}
void
main
(
)
{
void
main
(
)
{
testWidgets
(
'Tap changes toggle state'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Tap changes toggle state'
,
(
WidgetTester
tester
)
async
{
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
...
@@ -96,8 +98,7 @@ void main() {
...
@@ -96,8 +98,7 @@ void main() {
),
),
),
),
);
);
fail
(
fail
(
'Should not be possible to create a segmented control with no children'
);
'Should not be possible to create a segmented control with no children'
);
}
on
AssertionError
catch
(
e
)
{
}
on
AssertionError
catch
(
e
)
{
expect
(
e
.
toString
(),
contains
(
'children.length'
));
expect
(
e
.
toString
(),
contains
(
'children.length'
));
}
}
...
@@ -112,15 +113,14 @@ void main() {
...
@@ -112,15 +113,14 @@ void main() {
),
),
),
),
);
);
fail
(
fail
(
'Should not be possible to create a segmented control with just one child'
);
'Should not be possible to create a segmented control with just one child'
);
}
on
AssertionError
catch
(
e
)
{
}
on
AssertionError
catch
(
e
)
{
expect
(
e
.
toString
(),
contains
(
'children.length'
));
expect
(
e
.
toString
(),
contains
(
'children.length'
));
}
}
});
});
testWidgets
(
'Value attribute must be the key of one of the children widgets'
,
testWidgets
(
'Value attribute must be the key of one of the children widgets'
,
(
WidgetTester
tester
)
async
{
(
WidgetTester
tester
)
async
{
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
1
]
=
const
Text
(
'Child 2'
);
children
[
1
]
=
const
Text
(
'Child 2'
);
...
@@ -142,8 +142,7 @@ void main() {
...
@@ -142,8 +142,7 @@ void main() {
}
}
});
});
testWidgets
(
'Children and onValueChanged can not be null'
,
testWidgets
(
'Children and onValueChanged can not be null'
,
(
WidgetTester
tester
)
async
{
(
WidgetTester
tester
)
async
{
try
{
try
{
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
boilerplate
(
...
@@ -153,8 +152,7 @@ void main() {
...
@@ -153,8 +152,7 @@ void main() {
),
),
),
),
);
);
fail
(
fail
(
'Should not be possible to create segmented control with null children'
);
'Should not be possible to create segmented control with null children'
);
}
on
AssertionError
catch
(
e
)
{
}
on
AssertionError
catch
(
e
)
{
expect
(
e
.
toString
(),
contains
(
'children'
));
expect
(
e
.
toString
(),
contains
(
'children'
));
}
}
...
@@ -172,16 +170,14 @@ void main() {
...
@@ -172,16 +170,14 @@ void main() {
),
),
),
),
);
);
fail
(
fail
(
'Should not be possible to create segmented control with null onValueChanged'
);
'Should not be possible to create segmented control with null onValueChanged'
);
}
on
AssertionError
catch
(
e
)
{
}
on
AssertionError
catch
(
e
)
{
expect
(
e
.
toString
(),
contains
(
'onValueChanged'
));
expect
(
e
.
toString
(),
contains
(
'onValueChanged'
));
}
}
});
});
testWidgets
(
testWidgets
(
'Widgets have correct default text/icon styles, change correctly on selection'
,
'Widgets have correct default text/icon styles, change correctly on selection'
,
(
WidgetTester
tester
)
async
{
(
WidgetTester
tester
)
async
{
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
1
]
=
const
Icon
(
IconData
(
1
));
children
[
1
]
=
const
Icon
(
IconData
(
1
));
...
@@ -206,20 +202,19 @@ void main() {
...
@@ -206,20 +202,19 @@ void main() {
),
),
);
);
DefaultTextStyle
textStyle
=
await
tester
.
pumpAndSettle
();
tester
.
widget
(
find
.
widgetWithText
(
DefaultTextStyle
,
'Child 1'
));
IconTheme
iconTheme
=
DefaultTextStyle
textStyle
=
tester
.
widget
(
find
.
widgetWithText
(
DefaultTextStyle
,
'Child 1'
));
tester
.
widget
(
find
.
widgetWithIcon
(
IconTheme
,
const
IconData
(
1
)));
IconTheme
iconTheme
=
tester
.
widget
(
find
.
widgetWithIcon
(
IconTheme
,
const
IconData
(
1
)));
expect
(
textStyle
.
style
.
color
,
CupertinoColors
.
white
);
expect
(
textStyle
.
style
.
color
,
CupertinoColors
.
white
);
expect
(
iconTheme
.
data
.
color
,
CupertinoColors
.
activeBlue
);
expect
(
iconTheme
.
data
.
color
,
CupertinoColors
.
activeBlue
);
await
tester
.
tap
(
find
.
widgetWithIcon
(
IconTheme
,
const
IconData
(
1
)));
await
tester
.
tap
(
find
.
widgetWithIcon
(
IconTheme
,
const
IconData
(
1
)));
await
tester
.
pump
();
await
tester
.
pump
AndSettle
();
textStyle
=
tester
.
widget
(
find
.
widgetWithText
(
DefaultTextStyle
,
'Child 1'
));
textStyle
=
tester
.
widget
(
find
.
widgetWithText
(
DefaultTextStyle
,
'Child 1'
));
iconTheme
=
iconTheme
=
tester
.
widget
(
find
.
widgetWithIcon
(
IconTheme
,
const
IconData
(
1
)));
tester
.
widget
(
find
.
widgetWithIcon
(
IconTheme
,
const
IconData
(
1
)));
expect
(
textStyle
.
style
.
color
,
CupertinoColors
.
activeBlue
);
expect
(
textStyle
.
style
.
color
,
CupertinoColors
.
activeBlue
);
expect
(
iconTheme
.
data
.
color
,
CupertinoColors
.
white
);
expect
(
iconTheme
.
data
.
color
,
CupertinoColors
.
white
);
...
@@ -254,9 +249,8 @@ void main() {
...
@@ -254,9 +249,8 @@ void main() {
expect
(
value
,
isTrue
);
expect
(
value
,
isTrue
);
});
});
testWidgets
(
testWidgets
(
'State does not change if onValueChanged does not call setState()'
,
'State does not change if onValueChanged does not call setState()'
,
(
WidgetTester
tester
)
async
{
(
WidgetTester
tester
)
async
{
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
1
]
=
const
Text
(
'Child 2'
);
children
[
1
]
=
const
Text
(
'Child 2'
);
...
@@ -277,49 +271,14 @@ void main() {
...
@@ -277,49 +271,14 @@ void main() {
),
),
);
);
final
dynamic
childList
=
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
activeBlue
);
getRenderSegmentedControl
(
tester
).
getChildrenAsList
();
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
white
);
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
(
rrect:
childList
.
elementAt
(
0
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
activeBlue
,
),
);
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
()
..
rrect
()
..
rrect
(
rrect:
childList
.
elementAt
(
1
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
white
,
),
);
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
activeBlue
);
getRenderSegmentedControl
(
tester
),
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
white
);
paints
..
rrect
(
rrect:
childList
.
elementAt
(
0
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
activeBlue
,
),
);
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
()
..
rrect
()
..
rrect
(
rrect:
childList
.
elementAt
(
1
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
white
,
),
);
});
});
testWidgets
(
testWidgets
(
...
@@ -327,47 +286,17 @@ void main() {
...
@@ -327,47 +286,17 @@ void main() {
'and should not change when tapped again'
,
(
WidgetTester
tester
)
async
{
'and should not change when tapped again'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
setupSimpleSegmentedControl
());
await
tester
.
pumpWidget
(
setupSimpleSegmentedControl
());
final
dynamic
childList
=
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
white
);
getRenderSegmentedControl
(
tester
).
getChildrenAsList
();
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
()
..
rrect
()
..
rrect
(
rrect:
childList
.
elementAt
(
1
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
white
,
),
);
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
pump
(
);
await
tester
.
pump
AndSettle
(
const
Duration
(
milliseconds:
200
)
);
expect
(
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
activeBlue
);
getRenderSegmentedControl
(
tester
),
paints
..
rrect
()
..
rrect
()
..
rrect
(
rrect:
childList
.
elementAt
(
1
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
activeBlue
,
),
);
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
activeBlue
);
getRenderSegmentedControl
(
tester
),
paints
..
rrect
()
..
rrect
()
..
rrect
(
rrect:
childList
.
elementAt
(
1
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
activeBlue
,
),
);
});
});
testWidgets
(
testWidgets
(
...
@@ -404,36 +333,17 @@ void main() {
...
@@ -404,36 +333,17 @@ void main() {
);
);
testWidgets
(
'Passed in value is child initially selected'
,
testWidgets
(
'Passed in value is child initially selected'
,
(
WidgetTester
tester
)
async
{
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
setupSimpleSegmentedControl
());
await
tester
.
pumpWidget
(
setupSimpleSegmentedControl
());
expect
(
getRenderSegmentedControl
(
tester
).
selectedIndex
,
0
);
expect
(
getRenderSegmentedControl
(
tester
).
selectedIndex
,
0
);
final
dynamic
childList
=
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
activeBlue
);
getRenderSegmentedControl
(
tester
).
getChildrenAsList
();
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
white
);
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
(
rrect:
childList
.
elementAt
(
0
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
activeBlue
,
),
);
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
()
..
rrect
()
..
rrect
(
rrect:
childList
.
elementAt
(
1
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
white
,
),
);
});
});
testWidgets
(
'Null input for value results in no child initially selected'
,
testWidgets
(
'Null input for value results in no child initially selected'
,
(
WidgetTester
tester
)
async
{
(
WidgetTester
tester
)
async
{
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
1
]
=
const
Text
(
'Child 2'
);
children
[
1
]
=
const
Text
(
'Child 2'
);
...
@@ -460,132 +370,42 @@ void main() {
...
@@ -460,132 +370,42 @@ void main() {
expect
(
getRenderSegmentedControl
(
tester
).
selectedIndex
,
null
);
expect
(
getRenderSegmentedControl
(
tester
).
selectedIndex
,
null
);
final
dynamic
childList
=
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
white
);
getRenderSegmentedControl
(
tester
).
getChildrenAsList
();
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
white
);
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
(
rrect:
childList
.
elementAt
(
0
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
white
,
),
);
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
()
..
rrect
()
..
rrect
(
rrect:
childList
.
elementAt
(
1
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
white
,
),
);
});
});
testWidgets
(
'Long press changes background color of not-selected child'
,
testWidgets
(
'Long press changes background color of not-selected child'
,
(
WidgetTester
tester
)
async
{
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
setupSimpleSegmentedControl
());
await
tester
.
pumpWidget
(
setupSimpleSegmentedControl
());
final
dynamic
childList
=
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
activeBlue
);
getRenderSegmentedControl
(
tester
).
getChildrenAsList
();
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
white
);
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
(
rrect:
childList
.
elementAt
(
0
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
activeBlue
,
),
);
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
()
..
rrect
()
..
rrect
(
rrect:
childList
.
elementAt
(
1
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
white
,
),
);
final
Offset
center
=
tester
.
getCenter
(
find
.
text
(
'Child 2'
));
final
Offset
center
=
tester
.
getCenter
(
find
.
text
(
'Child 2'
));
await
tester
.
startGesture
(
center
);
await
tester
.
startGesture
(
center
);
await
tester
.
pumpAndSettle
();
await
tester
.
pumpAndSettle
();
expect
(
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
activeBlue
);
getRenderSegmentedControl
(
tester
),
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x33007aff
));
paints
..
rrect
(
rrect:
childList
.
elementAt
(
0
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
activeBlue
,
),
);
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
()
..
rrect
()
..
rrect
(
rrect:
childList
.
elementAt
(
1
).
parentData
.
surroundingRect
,
color:
const
Color
(
0x33007aff
),
),
);
});
});
testWidgets
(
testWidgets
(
'Long press does not change background color of currently-selected child'
,
'Long press does not change background color of currently-selected child'
,
(
WidgetTester
tester
)
async
{
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
setupSimpleSegmentedControl
());
await
tester
.
pumpWidget
(
setupSimpleSegmentedControl
());
final
dynamic
childList
=
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
activeBlue
);
getRenderSegmentedControl
(
tester
).
getChildrenAsList
();
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
white
);
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
(
rrect:
childList
.
elementAt
(
0
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
activeBlue
,
),
);
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
()
..
rrect
()
..
rrect
(
rrect:
childList
.
elementAt
(
1
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
white
,
),
);
final
Offset
center
=
tester
.
getCenter
(
find
.
text
(
'Child 1'
));
final
Offset
center
=
tester
.
getCenter
(
find
.
text
(
'Child 1'
));
await
tester
.
startGesture
(
center
);
await
tester
.
startGesture
(
center
);
await
tester
.
pumpAndSettle
();
await
tester
.
pumpAndSettle
();
expect
(
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
activeBlue
);
getRenderSegmentedControl
(
tester
),
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
white
);
paints
..
rrect
(
rrect:
childList
.
elementAt
(
0
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
activeBlue
,
),
);
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
()
..
rrect
()
..
rrect
(
rrect:
childList
.
elementAt
(
1
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
white
,
),
);
});
});
testWidgets
(
'Height of segmented control is determined by tallest widget'
,
testWidgets
(
'Height of segmented control is determined by tallest widget'
,
(
WidgetTester
tester
)
async
{
(
WidgetTester
tester
)
async
{
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
new
Container
(
children
[
0
]
=
new
Container
(
constraints:
const
BoxConstraints
.
tightFor
(
height:
100.0
),
constraints:
const
BoxConstraints
.
tightFor
(
height:
100.0
),
...
@@ -611,16 +431,15 @@ void main() {
...
@@ -611,16 +431,15 @@ void main() {
),
),
);
);
final
RenderBox
buttonBox
=
tester
final
RenderBox
buttonBox
=
tester
.
renderObject
(
.
renderObject
(
find
.
byKey
(
const
ValueKey
<
String
>(
'Segmented Control'
)));
find
.
byKey
(
const
ValueKey
<
String
>(
'Segmented Control'
)));
// Default height of Placeholder is 400.0px, which is greater than heights
// Default height of Placeholder is 400.0px, which is greater than heights
// of other child widgets.
// of other child widgets.
expect
(
buttonBox
.
size
.
height
,
400.0
);
expect
(
buttonBox
.
size
.
height
,
400.0
);
});
});
testWidgets
(
'Width of each child widget is the same'
,
testWidgets
(
'Width of each child widget is the same'
,
(
WidgetTester
tester
)
async
{
(
WidgetTester
tester
)
async
{
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
new
Container
();
children
[
0
]
=
new
Container
();
children
[
1
]
=
const
Placeholder
();
children
[
1
]
=
const
Placeholder
();
...
@@ -640,23 +459,22 @@ void main() {
...
@@ -640,23 +459,22 @@ void main() {
),
),
);
);
final
RenderBox
segmentedControl
=
tester
final
RenderBox
segmentedControl
=
tester
.
renderObject
(
.
renderObject
(
find
.
byKey
(
const
ValueKey
<
String
>(
'Segmented Control'
)));
find
.
byKey
(
const
ValueKey
<
String
>(
'Segmented Control'
)));
// Subtract the 16.0px from each side. Remaining width should be allocated
// Subtract the 16.0px from each side. Remaining width should be allocated
// to each child equally.
// to each child equally.
final
double
childWidth
=
(
segmentedControl
.
size
.
width
-
32.0
)
/
3
;
final
double
childWidth
=
(
segmentedControl
.
size
.
width
-
32.0
)
/
3
;
final
dynamic
childList
=
expect
(
childWidth
,
getRenderSegmentedControl
(
tester
).
getChildrenAsList
();
getRenderSegmentedControl
(
tester
).
getChildrenAsList
()
[
0
].
parentData
.
surroundingRect
.
width
)
;
expect
(
childWidth
,
for
(
dynamic
child
in
childList
)
{
getRenderSegmentedControl
(
tester
).
getChildrenAsList
()[
1
].
parentData
.
surroundingRect
.
width
);
expect
(
childWidth
,
child
.
parentData
.
surroundingRect
.
width
);
expect
(
childWidth
,
}
getRenderSegmentedControl
(
tester
).
getChildrenAsList
()[
2
].
parentData
.
surroundingRect
.
width
);
});
});
testWidgets
(
'Width is finite in unbounded space'
,
testWidgets
(
'Width is finite in unbounded space'
,
(
WidgetTester
tester
)
async
{
(
WidgetTester
tester
)
async
{
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
1
]
=
const
Text
(
'Child 2'
);
children
[
1
]
=
const
Text
(
'Child 2'
);
...
@@ -679,14 +497,14 @@ void main() {
...
@@ -679,14 +497,14 @@ void main() {
),
),
);
);
final
RenderBox
segmentedControl
=
tester
final
RenderBox
segmentedControl
=
tester
.
renderObject
(
.
renderObject
(
find
.
byKey
(
const
ValueKey
<
String
>(
'Segmented Control'
)));
find
.
byKey
(
const
ValueKey
<
String
>(
'Segmented Control'
)));
expect
(
segmentedControl
.
size
.
width
.
isFinite
,
isTrue
);
expect
(
segmentedControl
.
size
.
width
.
isFinite
,
isTrue
);
});
});
testWidgets
(
'Directionality test - RTL should reverse order of widgets'
,
testWidgets
(
'Directionality test - RTL should reverse order of widgets'
,
(
WidgetTester
tester
)
async
{
(
WidgetTester
tester
)
async
{
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
1
]
=
const
Text
(
'Child 2'
);
children
[
1
]
=
const
Text
(
'Child 2'
);
...
@@ -703,14 +521,12 @@ void main() {
...
@@ -703,14 +521,12 @@ void main() {
),
),
);
);
expect
(
expect
(
tester
.
getTopRight
(
find
.
text
(
'Child 1'
)).
dx
>
tester
.
getTopRight
(
find
.
text
(
'Child 1'
)).
dx
>
tester
.
getTopRight
(
find
.
text
(
'Child 2'
)).
dx
,
isTrue
);
tester
.
getTopRight
(
find
.
text
(
'Child 2'
)).
dx
,
isTrue
);
});
});
testWidgets
(
'Correct initial selection and toggling behavior - RTL'
,
testWidgets
(
'Correct initial selection and toggling behavior - RTL'
,
(
WidgetTester
tester
)
async
{
(
WidgetTester
tester
)
async
{
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
1
]
=
const
Text
(
'Child 2'
);
children
[
1
]
=
const
Text
(
'Child 2'
);
...
@@ -738,63 +554,19 @@ void main() {
...
@@ -738,63 +554,19 @@ void main() {
),
),
);
);
final
dynamic
childList
=
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
activeBlue
);
getRenderSegmentedControl
(
tester
).
getChildrenAsList
();
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
white
);
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
(
rrect:
childList
.
elementAt
(
0
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
activeBlue
,
),
);
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
()
..
rrect
()
..
rrect
(
rrect:
childList
.
elementAt
(
1
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
white
,
),
);
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
pump
();
await
tester
.
pump
AndSettle
();
expect
(
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
white
);
getRenderSegmentedControl
(
tester
),
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
activeBlue
);
paints
..
rrect
(
rrect:
childList
.
elementAt
(
0
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
white
,
),
);
expect
(
getRenderSegmentedControl
(
tester
),
paints
..
rrect
()
..
rrect
()
..
rrect
(
rrect:
childList
.
elementAt
(
1
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
activeBlue
,
),
);
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
activeBlue
);
getRenderSegmentedControl
(
tester
),
paints
..
rrect
()
..
rrect
()
..
rrect
(
rrect:
childList
.
elementAt
(
1
).
parentData
.
surroundingRect
,
color:
CupertinoColors
.
activeBlue
,
),
);
});
});
testWidgets
(
'Segmented control semantics'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Segmented control semantics'
,
(
WidgetTester
tester
)
async
{
...
@@ -894,6 +666,504 @@ void main() {
...
@@ -894,6 +666,504 @@ void main() {
semantics
.
dispose
();
semantics
.
dispose
();
});
});
testWidgets
(
'Non-centered taps work on smaller widgets'
,
(
WidgetTester
tester
)
async
{
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
const
Text
(
'A'
);
children
[
1
]
=
const
Text
(
'B'
);
int
sharedValue
=
1
;
await
tester
.
pumpWidget
(
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
boilerplate
(
child:
new
SegmentedControl
<
int
>(
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
children:
children
,
onValueChanged:
(
int
newValue
)
{
setState
(()
{
sharedValue
=
newValue
;
});
},
groupValue:
sharedValue
,
),
);
},
),
);
expect
(
sharedValue
,
1
);
final
double
childWidth
=
getRenderSegmentedControl
(
tester
).
firstChild
.
size
.
width
;
final
Offset
centerOfSegmentedControl
=
tester
.
getCenter
(
find
.
text
(
'A'
));
// Tap just inside segment bounds
await
tester
.
tapAt
(
new
Offset
(
childWidth
-
10.0
,
centerOfSegmentedControl
.
dy
));
expect
(
sharedValue
,
0
);
});
testWidgets
(
'Animation is correct when the selected segment changes'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
setupSimpleSegmentedControl
());
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
pump
();
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
activeBlue
);
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x33007aff
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xff3d9aff
));
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x64007aff
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xff7bbaff
));
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x95007aff
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xffb9daff
));
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0xc7007aff
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xfff7faff
));
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0xf8007aff
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
white
);
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
activeBlue
);
});
testWidgets
(
'Animation is correct when widget is rebuilt'
,
(
WidgetTester
tester
)
async
{
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
1
]
=
const
Text
(
'Child 2'
);
int
sharedValue
=
0
;
await
tester
.
pumpWidget
(
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
boilerplate
(
child:
new
SegmentedControl
<
int
>(
children:
children
,
onValueChanged:
(
int
newValue
)
{
setState
(()
{
sharedValue
=
newValue
;
});
},
groupValue:
sharedValue
,
),
);
},
),
);
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
pumpWidget
(
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
boilerplate
(
child:
new
SegmentedControl
<
int
>(
children:
children
,
onValueChanged:
(
int
newValue
)
{
setState
(()
{
sharedValue
=
newValue
;
});
},
groupValue:
sharedValue
,
),
);
},
),
);
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
activeBlue
);
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x33007aff
));
await
tester
.
pumpWidget
(
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
boilerplate
(
child:
new
SegmentedControl
<
int
>(
children:
children
,
onValueChanged:
(
int
newValue
)
{
setState
(()
{
sharedValue
=
newValue
;
});
},
groupValue:
sharedValue
,
),
);
},
),
const
Duration
(
milliseconds:
40
),
);
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xff3d9aff
));
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x64007aff
));
await
tester
.
pumpWidget
(
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
boilerplate
(
child:
new
SegmentedControl
<
int
>(
children:
children
,
onValueChanged:
(
int
newValue
)
{
setState
(()
{
sharedValue
=
newValue
;
});
},
groupValue:
sharedValue
,
),
);
},
),
const
Duration
(
milliseconds:
40
),
);
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xff7bbaff
));
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x95007aff
));
await
tester
.
pumpWidget
(
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
boilerplate
(
child:
new
SegmentedControl
<
int
>(
children:
children
,
onValueChanged:
(
int
newValue
)
{
setState
(()
{
sharedValue
=
newValue
;
});
},
groupValue:
sharedValue
,
),
);
},
),
const
Duration
(
milliseconds:
40
),
);
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xffb9daff
));
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0xc7007aff
));
await
tester
.
pumpWidget
(
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
boilerplate
(
child:
new
SegmentedControl
<
int
>(
children:
children
,
onValueChanged:
(
int
newValue
)
{
setState
(()
{
sharedValue
=
newValue
;
});
},
groupValue:
sharedValue
,
),
);
},
),
const
Duration
(
milliseconds:
40
),
);
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xfff7faff
));
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0xf8007aff
));
await
tester
.
pumpWidget
(
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
boilerplate
(
child:
new
SegmentedControl
<
int
>(
children:
children
,
onValueChanged:
(
int
newValue
)
{
setState
(()
{
sharedValue
=
newValue
;
});
},
groupValue:
sharedValue
,
),
);
},
),
const
Duration
(
milliseconds:
40
),
);
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
white
);
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
activeBlue
);
});
testWidgets
(
'Multiple segments are pressed'
,
(
WidgetTester
tester
)
async
{
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
const
Text
(
'A'
);
children
[
1
]
=
const
Text
(
'B'
);
children
[
2
]
=
const
Text
(
'C'
);
int
sharedValue
=
0
;
await
tester
.
pumpWidget
(
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
boilerplate
(
child:
new
SegmentedControl
<
int
>(
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
children:
children
,
onValueChanged:
(
int
newValue
)
{
setState
(()
{
sharedValue
=
newValue
;
});
},
groupValue:
sharedValue
,
),
);
},
),
);
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
white
);
await
tester
.
startGesture
(
tester
.
getCenter
(
find
.
text
(
'B'
)));
await
tester
.
pumpAndSettle
(
const
Duration
(
milliseconds:
200
));
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x33007aff
));
expect
(
getBackgroundColor
(
tester
,
2
),
CupertinoColors
.
white
);
await
tester
.
startGesture
(
tester
.
getCenter
(
find
.
text
(
'C'
)));
await
tester
.
pumpAndSettle
(
const
Duration
(
milliseconds:
200
));
// Press on C has no effect while B is held down.
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x33007aff
));
expect
(
getBackgroundColor
(
tester
,
2
),
CupertinoColors
.
white
);
});
testWidgets
(
'Transition is triggered while a transition is already occurring'
,
(
WidgetTester
tester
)
async
{
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
const
Text
(
'A'
);
children
[
1
]
=
const
Text
(
'B'
);
children
[
2
]
=
const
Text
(
'C'
);
int
sharedValue
=
0
;
await
tester
.
pumpWidget
(
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
boilerplate
(
child:
new
SegmentedControl
<
int
>(
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
children:
children
,
onValueChanged:
(
int
newValue
)
{
setState
(()
{
sharedValue
=
newValue
;
});
},
groupValue:
sharedValue
,
),
);
},
),
);
await
tester
.
tap
(
find
.
text
(
'B'
));
await
tester
.
pump
();
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
activeBlue
);
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x33007aff
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xff3d9aff
));
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x64007aff
));
// While A to B transition is occurring, press on C.
await
tester
.
tap
(
find
.
text
(
'C'
));
await
tester
.
pump
();
// A and B are now both transitioning to white.
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xff3d9aff
));
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0xffc1deff
));
expect
(
getBackgroundColor
(
tester
,
2
),
const
Color
(
0x33007aff
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
// B background color has reached unselected state.
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xff7bbaff
));
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
white
);
expect
(
getBackgroundColor
(
tester
,
2
),
const
Color
(
0x64007aff
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
100
));
// A background color has reached unselected state.
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
white
);
expect
(
getBackgroundColor
(
tester
,
2
),
const
Color
(
0xe0007aff
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
// C background color has reached selected state.
expect
(
getBackgroundColor
(
tester
,
2
),
CupertinoColors
.
activeBlue
);
});
testWidgets
(
'Segment is selected while it is transitioning to unselected state'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
setupSimpleSegmentedControl
());
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
pump
();
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
activeBlue
);
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x33007aff
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xff3d9aff
));
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x64007aff
));
// While A to B transition is occurring, press on A again.
await
tester
.
tap
(
find
.
text
(
'Child 1'
));
await
tester
.
pump
();
// Both transitions start to reverse.
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xcd007aff
));
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0xffc1deff
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
// A and B finish transitioning.
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
activeBlue
);
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
white
);
});
testWidgets
(
'Add segment while animation is running'
,
(
WidgetTester
tester
)
async
{
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
const
Text
(
'A'
);
children
[
1
]
=
const
Text
(
'B'
);
children
[
2
]
=
const
Text
(
'C'
);
int
sharedValue
=
0
;
await
tester
.
pumpWidget
(
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
boilerplate
(
child:
new
SegmentedControl
<
int
>(
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
children:
children
,
onValueChanged:
(
int
newValue
)
{
setState
(()
{
sharedValue
=
newValue
;
});
if
(
sharedValue
==
1
)
{
children
=
new
Map
<
int
,
Widget
>.
from
(
children
);
children
[
3
]
=
const
Text
(
'D'
);
}
},
groupValue:
sharedValue
,
),
);
},
),
);
await
tester
.
tap
(
find
.
text
(
'B'
));
await
tester
.
pump
();
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xff007aff
));
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x33007aff
));
expect
(
getBackgroundColor
(
tester
,
3
),
CupertinoColors
.
white
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xff3d9aff
));
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x64007aff
));
expect
(
getBackgroundColor
(
tester
,
3
),
CupertinoColors
.
white
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
150
));
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
white
);
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
activeBlue
);
expect
(
getBackgroundColor
(
tester
,
3
),
CupertinoColors
.
white
);
});
testWidgets
(
'Remove segment while animation is running'
,
(
WidgetTester
tester
)
async
{
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
const
Text
(
'A'
);
children
[
1
]
=
const
Text
(
'B'
);
children
[
2
]
=
const
Text
(
'C'
);
int
sharedValue
=
0
;
await
tester
.
pumpWidget
(
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
boilerplate
(
child:
new
SegmentedControl
<
int
>(
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
children:
children
,
onValueChanged:
(
int
newValue
)
{
setState
(()
{
sharedValue
=
newValue
;
});
if
(
sharedValue
==
1
)
{
children
.
remove
(
2
);
children
=
new
Map
<
int
,
Widget
>.
from
(
children
);
}
},
groupValue:
sharedValue
,
),
);
},
),
);
expect
(
getRenderSegmentedControl
(
tester
).
getChildrenAsList
().
length
,
3
);
await
tester
.
tap
(
find
.
text
(
'B'
));
await
tester
.
pump
();
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x33007aff
));
expect
(
getRenderSegmentedControl
(
tester
).
getChildrenAsList
().
length
,
2
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
getBackgroundColor
(
tester
,
1
),
const
Color
(
0x64007aff
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
150
));
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
activeBlue
);
});
testWidgets
(
'Remove currently animating segment'
,
(
WidgetTester
tester
)
async
{
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
children
[
0
]
=
const
Text
(
'A'
);
children
[
1
]
=
const
Text
(
'B'
);
children
[
2
]
=
const
Text
(
'C'
);
int
sharedValue
=
0
;
await
tester
.
pumpWidget
(
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
boilerplate
(
child:
new
SegmentedControl
<
int
>(
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
children:
children
,
onValueChanged:
(
int
newValue
)
{
setState
(()
{
sharedValue
=
newValue
;
});
if
(
sharedValue
==
1
)
{
children
.
remove
(
1
);
children
=
new
Map
<
int
,
Widget
>.
from
(
children
);
sharedValue
=
null
;
}
},
groupValue:
sharedValue
,
),
);
},
),
);
expect
(
getRenderSegmentedControl
(
tester
).
getChildrenAsList
().
length
,
3
);
await
tester
.
tap
(
find
.
text
(
'B'
));
await
tester
.
pump
();
expect
(
getRenderSegmentedControl
(
tester
).
getChildrenAsList
().
length
,
2
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xff3d9aff
));
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
white
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
getBackgroundColor
(
tester
,
0
),
const
Color
(
0xff7bbaff
));
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
white
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
100
));
expect
(
getBackgroundColor
(
tester
,
0
),
CupertinoColors
.
white
);
expect
(
getBackgroundColor
(
tester
,
1
),
CupertinoColors
.
white
);
});
testWidgets
(
'Golden Test Placeholder Widget'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Golden Test Placeholder Widget'
,
(
WidgetTester
tester
)
async
{
// Different machines render this content differently. Since the golden
// Different machines render this content differently. Since the golden
// files are rendered on MacOS, this test should only be run on MacOS.
// files are rendered on MacOS, this test should only be run on MacOS.
...
...
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