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
3cd8c314
Unverified
Commit
3cd8c314
authored
Nov 01, 2019
by
LongCatIsLooong
Committed by
GitHub
Nov 01, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update CupertinoSlidingSegmentedControl control/feedback mechanism (#43932)
parent
a192e296
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
308 additions
and
371 deletions
+308
-371
sliding_segmented_control.dart
.../flutter/lib/src/cupertino/sliding_segmented_control.dart
+80
-105
sliding_segmented_control_test.dart
...lutter/test/cupertino/sliding_segmented_control_test.dart
+228
-266
No files found.
packages/flutter/lib/src/cupertino/sliding_segmented_control.dart
View file @
3cd8c314
...
@@ -94,56 +94,12 @@ class _FontWeightTween extends Tween<FontWeight> {
...
@@ -94,56 +94,12 @@ class _FontWeightTween extends Tween<FontWeight> {
/// argument must be an ordered [Map] such as a [LinkedHashMap], the ordering of
/// argument must be an ordered [Map] such as a [LinkedHashMap], the ordering of
/// the keys will determine the order of the widgets in the segmented control.
/// the keys will determine the order of the widgets in the segmented control.
///
///
/// When the state of the segmented control changes, the widget changes the
/// When the state of the segmented control changes, the widget calls the
/// [controller]'s value to the map key associated with the newly selected widget,
/// [onValueChanged] callback. The map key associated with the newly selected
/// causing all of its listeners to be notified.
/// widget is returned in the [onValueChanged] callback. Typically, widgets
///
/// that use a segmented control will listen for the [onValueChanged] callback
/// {@tool dartpad --template=stateful_widget_material}
/// and rebuild the segmented control with a new [groupValue] to update which
///
/// option is currently selected.
/// This sample shows two [CupertinoSlidingSegmentedControl]s that mirror each other.
///
/// ```dart
/// final Map<int, Widget> children = const <int, Widget>{
/// 0: Text('Child 1'),
/// 1: Text('Child 2'),
/// 2: Text('Child 3'),
/// };
///
/// // No segment is initially selected because the controller's value is null.
/// final ValueNotifier<int> controller = ValueNotifier<int>(null);
///
/// @override
/// void initState() {
/// super.initState();
/// // Prints a message whenever the currently selected widget changes.
/// controller.addListener(() { print('selected: ${controller.value}'); });
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return Center(
/// child: Column(
/// children: <Widget>[
/// CupertinoSlidingSegmentedControl<int>(
/// children: children,
/// controller: controller,
/// ),
/// CupertinoSlidingSegmentedControl<int>(
/// children: children,
/// controller: controller,
/// ),
/// ],
/// ),
/// );
/// }
///
/// @override
/// void dispose() {
/// controller.dispose();
/// super.dispose();
/// }
/// ```
/// {@end-tool}
///
///
/// The [children] will be displayed in the order of the keys in the [Map].
/// The [children] will be displayed in the order of the keys in the [Map].
/// The height of the segmented control is determined by the height of the
/// The height of the segmented control is determined by the height of the
...
@@ -166,33 +122,34 @@ class _FontWeightTween extends Tween<FontWeight> {
...
@@ -166,33 +122,34 @@ class _FontWeightTween extends Tween<FontWeight> {
class
CupertinoSlidingSegmentedControl
<
T
>
extends
StatefulWidget
{
class
CupertinoSlidingSegmentedControl
<
T
>
extends
StatefulWidget
{
/// Creates an iOS-style segmented control bar.
/// Creates an iOS-style segmented control bar.
///
///
/// The [children] and [
controller] arguments must not be null. The [children]
/// The [children] and [
onValueChanged] arguments must not be null. The
///
argument must be an ordered [Map] such as a [LinkedHashMap]. Further, the
///
[children] argument must be an ordered [Map] such as a [LinkedHashMap].
/// length of the [children] list must be greater than one.
///
Further, the
length of the [children] list must be greater than one.
///
///
/// Each widget value in the map of [children] must have an associated
[Map]
key
/// Each widget value in the map of [children] must have an associated key
///
of type [T] that uniquely identifies this widget. This key will become the
///
that uniquely identifies this widget. This key is what will be returned
///
[controller]'s new value, when the corresponding child widget from the
///
in the [onValueChanged] callback when a new value from the [children] map
///
[children] map
is selected.
/// is selected.
///
///
/// The [
controller]'s [ValueNotifier.value] is the currently selected value for
/// The [
groupValue] is the currently selected value for the segmented control.
///
the segmented control. If it is null, no widget will appear as selected. The
///
If no [groupValue] is provided, or the [groupValue] is null, no widget will
///
[controller]'s value must be either null or one of the keys in the [children]
///
appear as selected. The [groupValue] must be either null or one of the keys
/// map.
///
in the [children]
map.
CupertinoSlidingSegmentedControl
({
CupertinoSlidingSegmentedControl
({
Key
key
,
Key
key
,
@required
this
.
children
,
@required
this
.
children
,
@required
this
.
controller
,
@required
this
.
onValueChanged
,
this
.
groupValue
,
this
.
thumbColor
=
_kThumbColor
,
this
.
thumbColor
=
_kThumbColor
,
this
.
padding
=
_kHorizontalItemPadding
,
this
.
padding
=
_kHorizontalItemPadding
,
this
.
backgroundColor
=
CupertinoColors
.
tertiarySystemFill
,
this
.
backgroundColor
=
CupertinoColors
.
tertiarySystemFill
,
})
:
assert
(
children
!=
null
),
})
:
assert
(
children
!=
null
),
assert
(
children
.
length
>=
2
),
assert
(
children
.
length
>=
2
),
assert
(
padding
!=
null
),
assert
(
padding
!=
null
),
assert
(
controller
!=
null
),
assert
(
onValueChanged
!=
null
),
assert
(
assert
(
controller
.
value
==
null
||
children
.
keys
.
any
((
T
child
)
=>
child
==
controller
.
v
alue
),
groupValue
==
null
||
children
.
keys
.
contains
(
groupV
alue
),
"The controller's value must be either null or one of the keys in the children map."
,
'The groupValue must be either null or one of the keys in the children map.'
,
),
),
super
(
key:
key
);
super
(
key:
key
);
...
@@ -203,16 +160,58 @@ class CupertinoSlidingSegmentedControl<T> extends StatefulWidget {
...
@@ -203,16 +160,58 @@ class CupertinoSlidingSegmentedControl<T> extends StatefulWidget {
/// This attribute must be an ordered [Map] such as a [LinkedHashMap].
/// This attribute must be an ordered [Map] such as a [LinkedHashMap].
final
Map
<
T
,
Widget
>
children
;
final
Map
<
T
,
Widget
>
children
;
/// A [ValueNotifier]<[T]> that controls the currently selected child.
/// The identifier of the widget that is currently selected.
///
/// This must be one of the keys in the [Map] of [children].
/// If this attribute is null, no widget will be initially selected.
final
T
groupValue
;
/// The callback that is called when a new option is tapped.
///
/// This attribute must not be null.
///
/// The segmented control passes the newly selected widget's associated key
/// to the callback but does not actually change state until the parent
/// widget rebuilds the segmented control with the new [groupValue].
///
/// The callback provided to [onValueChanged] should update the state of
/// the parent [StatefulWidget] using the [State.setState] method, so that
/// the parent gets rebuilt; for example:
///
///
/// Its value must be one of the keys in the [Map] of [children], or null, in
/// {@tool sample}
/// which case no widget will be selected.
///
///
/// The [controller]'s value changes when the user drags the thumb to a different
/// ```dart
/// child widget, or taps on a different child widget. Its value can also be
/// class SegmentedControlExample extends StatefulWidget {
/// changed programmatically, in which case all sliding animations will play as
/// @override
/// if the new selected child widget was tapped on.
/// State createState() => SegmentedControlExampleState();
final
ValueNotifier
<
T
>
controller
;
/// }
///
/// class SegmentedControlExampleState extends State<SegmentedControlExample> {
/// final Map<int, Widget> children = const {
/// 0: Text('Child 1'),
/// 1: Text('Child 2'),
/// };
///
/// int currentValue;
///
/// @override
/// Widget build(BuildContext context) {
/// return Container(
/// child: CupertinoSlidingSegmentedControl<int>(
/// children: children,
/// onValueChanged: (int newValue) {
/// setState(() {
/// currentValue = newValue;
/// });
/// },
/// groupValue: currentValue,
/// ),
/// );
/// }
/// }
/// ```
/// {@end-tool}
final
ValueChanged
<
T
>
onValueChanged
;
/// The color used to paint the rounded rect behind the [children] and the separators.
/// The color used to paint the rounded rect behind the [children] and the separators.
///
///
...
@@ -240,7 +239,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
...
@@ -240,7 +239,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
with
TickerProviderStateMixin
<
CupertinoSlidingSegmentedControl
<
T
>>
{
with
TickerProviderStateMixin
<
CupertinoSlidingSegmentedControl
<
T
>>
{
final
Map
<
T
,
AnimationController
>
_highlightControllers
=
<
T
,
AnimationController
>{};
final
Map
<
T
,
AnimationController
>
_highlightControllers
=
<
T
,
AnimationController
>{};
final
Tween
<
FontWeight
>
_highlightTween
=
_FontWeightTween
(
begin:
FontWeight
.
normal
,
end:
FontWeight
.
w
6
00
);
final
Tween
<
FontWeight
>
_highlightTween
=
_FontWeightTween
(
begin:
FontWeight
.
normal
,
end:
FontWeight
.
w
5
00
);
final
Map
<
T
,
AnimationController
>
_pressControllers
=
<
T
,
AnimationController
>{};
final
Map
<
T
,
AnimationController
>
_pressControllers
=
<
T
,
AnimationController
>{};
final
Tween
<
double
>
_pressTween
=
Tween
<
double
>(
begin:
1
,
end:
0.2
);
final
Tween
<
double
>
_pressTween
=
Tween
<
double
>(
begin:
1
,
end:
0.2
);
...
@@ -255,8 +254,6 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
...
@@ -255,8 +254,6 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
final
HorizontalDragGestureRecognizer
drag
=
HorizontalDragGestureRecognizer
();
final
HorizontalDragGestureRecognizer
drag
=
HorizontalDragGestureRecognizer
();
final
LongPressGestureRecognizer
longPress
=
LongPressGestureRecognizer
();
final
LongPressGestureRecognizer
longPress
=
LongPressGestureRecognizer
();
ValueNotifier
<
T
>
controller
;
AnimationController
_createHighlightAnimationController
({
bool
isCompleted
=
false
})
{
AnimationController
_createHighlightAnimationController
({
bool
isCompleted
=
false
})
{
return
AnimationController
(
return
AnimationController
(
duration:
_kHighlightAnimationDuration
,
duration:
_kHighlightAnimationDuration
,
...
@@ -284,9 +281,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
...
@@ -284,9 +281,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
drag
.
team
=
team
;
drag
.
team
=
team
;
team
.
captain
=
drag
;
team
.
captain
=
drag
;
controller
=
widget
.
controller
;
_highlighted
=
widget
.
groupValue
;
controller
.
addListener
(
_didChangeControllerValue
);
_highlighted
=
controller
.
value
;
thumbController
=
AnimationController
(
thumbController
=
AnimationController
(
duration:
_kSpringAnimationDuration
,
duration:
_kSpringAnimationDuration
,
...
@@ -308,7 +303,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
...
@@ -308,7 +303,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
for
(
T
currentKey
in
widget
.
children
.
keys
)
{
for
(
T
currentKey
in
widget
.
children
.
keys
)
{
_highlightControllers
[
currentKey
]
=
_createHighlightAnimationController
(
_highlightControllers
[
currentKey
]
=
_createHighlightAnimationController
(
isCompleted:
currentKey
==
controller
.
v
alue
,
// Highlight the current selection.
isCompleted:
currentKey
==
widget
.
groupV
alue
,
// Highlight the current selection.
);
);
_pressControllers
[
currentKey
]
=
_createFadeoutAnimationController
();
_pressControllers
[
currentKey
]
=
_createFadeoutAnimationController
();
}
}
...
@@ -336,15 +331,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
...
@@ -336,15 +331,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
}
}
}
}
if
(
controller
!=
widget
.
controller
)
{
highlighted
=
widget
.
groupValue
;
controller
.
removeListener
(
_didChangeControllerValue
);
controller
=
widget
.
controller
;
controller
.
addListener
(
_didChangeControllerValue
);
}
if
(
controller
.
value
!=
oldWidget
.
controller
.
value
)
{
highlighted
=
widget
.
controller
.
value
;
}
}
}
@override
@override
...
@@ -368,18 +355,6 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
...
@@ -368,18 +355,6 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
super
.
dispose
();
super
.
dispose
();
}
}
void
_didChangeControllerValue
()
{
assert
(
controller
.
value
==
null
||
widget
.
children
.
keys
.
contains
(
controller
.
value
),
"The controller's value
${controller.value}
must be either null "
'or one of the keys in the children map:
${widget.children.keys}
'
,
);
setState
(()
{
// Mark the state as dirty.
});
}
// Play highlight animation for the child located at _highlightControllers[at].
// Play highlight animation for the child located at _highlightControllers[at].
void
_animateHighlightController
({
T
at
,
bool
forward
})
{
void
_animateHighlightController
({
T
at
,
bool
forward
})
{
if
(
at
==
null
)
if
(
at
==
null
)
...
@@ -413,7 +388,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
...
@@ -413,7 +388,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
}
}
void
didChangeSelectedViaGesture
()
{
void
didChangeSelectedViaGesture
()
{
controller
.
value
=
_highlighted
;
widget
.
onValueChanged
(
_highlighted
)
;
}
}
T
indexToKey
(
int
index
)
=>
index
==
null
?
null
:
keys
[
index
];
T
indexToKey
(
int
index
)
=>
index
==
null
?
null
:
keys
[
index
];
...
@@ -447,9 +422,9 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
...
@@ -447,9 +422,9 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
style:
textStyle
,
style:
textStyle
,
child:
Semantics
(
child:
Semantics
(
button:
true
,
button:
true
,
onTap:
()
{
controller
.
value
=
currentKey
;
},
onTap:
()
{
widget
.
onValueChanged
(
currentKey
)
;
},
inMutuallyExclusiveGroup:
true
,
inMutuallyExclusiveGroup:
true
,
selected:
controller
.
v
alue
==
currentKey
,
selected:
widget
.
groupV
alue
==
currentKey
,
child:
Opacity
(
child:
Opacity
(
opacity:
_pressTween
.
evaluate
(
_pressControllers
[
currentKey
]),
opacity:
_pressTween
.
evaluate
(
_pressControllers
[
currentKey
]),
// Expand the hitTest area to be as large as the Opacity widget.
// Expand the hitTest area to be as large as the Opacity widget.
...
@@ -464,7 +439,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
...
@@ -464,7 +439,7 @@ class _SegmentedControlState<T> extends State<CupertinoSlidingSegmentedControl<T
children
.
add
(
child
);
children
.
add
(
child
);
}
}
final
int
selectedIndex
=
controller
.
value
==
null
?
null
:
keys
.
indexOf
(
controller
.
v
alue
);
final
int
selectedIndex
=
widget
.
groupValue
==
null
?
null
:
keys
.
indexOf
(
widget
.
groupV
alue
);
final
Widget
box
=
_SegmentedControlRenderWidget
<
T
>(
final
Widget
box
=
_SegmentedControlRenderWidget
<
T
>(
children:
children
,
children:
children
,
...
...
packages/flutter/test/cupertino/sliding_segmented_control_test.dart
View file @
3cd8c314
...
@@ -36,32 +36,51 @@ Widget setupSimpleSegmentedControl() {
...
@@ -36,32 +36,51 @@ Widget setupSimpleSegmentedControl() {
0
:
Text
(
'Child 1'
),
0
:
Text
(
'Child 1'
),
1
:
Text
(
'Child 2'
),
1
:
Text
(
'Child 2'
),
};
};
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
0
);
return
boilerplate
(
return
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
builder:
(
BuildContext
context
)
{
children:
children
,
return
CupertinoSlidingSegmentedControl
<
int
>(
controller:
controller
,
children:
children
,
),
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
},
);
);
}
}
Widget
boilerplate
(
{
Widget
child
})
{
StateSetter
setState
;
int
groupValue
=
0
;
void
defaultCallback
(
int
newValue
)
{
setState
(()
{
groupValue
=
newValue
;
});
}
Widget
boilerplate
(
{
WidgetBuilder
builder
})
{
return
Directionality
(
return
Directionality
(
textDirection:
TextDirection
.
ltr
,
textDirection:
TextDirection
.
ltr
,
child:
Center
(
child:
child
),
child:
Center
(
child:
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setter
)
{
setState
=
setter
;
return
builder
(
context
);
}),
),
);
);
}
}
void
main
(
)
{
void
main
(
)
{
testWidgets
(
'Children and controller and padding arguments can not be null'
,
(
WidgetTester
tester
)
async
{
setUp
(()
{
setState
=
null
;
groupValue
=
0
;
});
testWidgets
(
'Children and onValueChanged and padding arguments can not be null'
,
(
WidgetTester
tester
)
async
{
groupValue
=
null
;
try
{
try
{
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
CupertinoSlidingSegmentedControl
<
int
>(
child:
CupertinoSlidingSegmentedControl
<
int
>(
children:
null
,
children:
null
,
groupValue:
groupValue
,
controller:
ValueNotifier
<
int
>(
null
),
onValueChanged:
defaultCallback
,
),
),
),
);
);
fail
(
'Should not be possible to create segmented control with null children'
);
fail
(
'Should not be possible to create segmented control with null children'
);
...
@@ -76,26 +95,24 @@ void main() {
...
@@ -76,26 +95,24 @@ void main() {
try
{
try
{
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
CupertinoSlidingSegmentedControl
<
int
>(
child:
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
children:
children
,
groupValue:
groupValue
,
controller:
null
,
onValueChanged:
null
,
),
),
),
);
);
fail
(
'Should not be possible to create segmented control without a
controller
'
);
fail
(
'Should not be possible to create segmented control without a
n onValueChanged
'
);
}
on
AssertionError
catch
(
e
)
{
}
on
AssertionError
catch
(
e
)
{
expect
(
e
.
toString
(),
contains
(
'
controller
'
));
expect
(
e
.
toString
(),
contains
(
'
onValueChanged
'
));
}
}
try
{
try
{
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
CupertinoSlidingSegmentedControl
<
int
>(
child:
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
children:
children
,
groupValue:
groupValue
,
controller:
ValueNotifier
<
int
>(
null
),
onValueChanged:
defaultCallback
,
padding:
null
,
padding:
null
,
),
),
),
);
);
fail
(
'Should not be possible to create segmented control with null padding'
);
fail
(
'Should not be possible to create segmented control with null padding'
);
...
@@ -106,13 +123,13 @@ void main() {
...
@@ -106,13 +123,13 @@ void main() {
testWidgets
(
'Need at least 2 children'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Need at least 2 children'
,
(
WidgetTester
tester
)
async
{
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
final
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{};
groupValue
=
null
;
try
{
try
{
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
CupertinoSlidingSegmentedControl
<
int
>(
child:
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
children:
children
,
groupValue:
groupValue
,
controller:
ValueNotifier
<
int
>(
null
),
onValueChanged:
defaultCallback
,
),
),
),
);
);
fail
(
'Should not be possible to create a segmented control with no children'
);
fail
(
'Should not be possible to create a segmented control with no children'
);
...
@@ -123,11 +140,10 @@ void main() {
...
@@ -123,11 +140,10 @@ void main() {
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
0
]
=
const
Text
(
'Child 1'
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
CupertinoSlidingSegmentedControl
<
int
>(
child:
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
children:
children
,
groupValue:
groupValue
,
controller:
ValueNotifier
<
int
>(
null
),
onValueChanged:
defaultCallback
,
),
),
),
);
);
fail
(
'Should not be possible to create a segmented control with just one child'
);
fail
(
'Should not be possible to create a segmented control with just one child'
);
...
@@ -135,20 +151,20 @@ void main() {
...
@@ -135,20 +151,20 @@ void main() {
expect
(
e
.
toString
(),
contains
(
'children.length'
));
expect
(
e
.
toString
(),
contains
(
'children.length'
));
}
}
groupValue
=
-
1
;
try
{
try
{
children
[
1
]
=
const
Text
(
'Child 2'
);
children
[
1
]
=
const
Text
(
'Child 2'
);
children
[
2
]
=
const
Text
(
'Child 3'
);
children
[
2
]
=
const
Text
(
'Child 3'
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
CupertinoSlidingSegmentedControl
<
int
>(
child:
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
children:
children
,
groupValue:
groupValue
,
controller:
ValueNotifier
<
int
>(-
1
),
onValueChanged:
defaultCallback
,
),
),
),
);
);
fail
(
'Should not be possible to create a segmented control with a
controller
pointing to a non-existent child'
);
fail
(
'Should not be possible to create a segmented control with a
groupValue
pointing to a non-existent child'
);
}
on
AssertionError
catch
(
e
)
{
}
on
AssertionError
catch
(
e
)
{
expect
(
e
.
toString
(),
contains
(
'
v
alue must be either null or one of the keys in the children map'
));
expect
(
e
.
toString
(),
contains
(
'
groupV
alue must be either null or one of the keys in the children map'
));
}
}
});
});
...
@@ -185,11 +201,14 @@ void main() {
...
@@ -185,11 +201,14 @@ void main() {
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
builder:
(
BuildContext
context
)
{
key:
key
,
return
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
key:
key
,
controller:
ValueNotifier
<
int
>(
null
),
children:
children
,
),
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
},
),
),
);
);
...
@@ -204,12 +223,15 @@ void main() {
...
@@ -204,12 +223,15 @@ void main() {
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
builder:
(
BuildContext
context
)
{
key:
key
,
return
CupertinoSlidingSegmentedControl
<
int
>(
padding:
const
EdgeInsets
.
fromLTRB
(
1
,
3
,
5
,
7
),
key:
key
,
children:
children
,
padding:
const
EdgeInsets
.
fromLTRB
(
1
,
3
,
5
,
7
),
controller:
ValueNotifier
<
int
>(
null
),
children:
children
,
),
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
},
),
),
);
);
...
@@ -230,119 +252,29 @@ void main() {
...
@@ -230,119 +252,29 @@ void main() {
2
:
Text
(
'Child 3'
),
2
:
Text
(
'Child 3'
),
};
};
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
0
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
builder:
(
BuildContext
context
)
{
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
return
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
controller:
controller
,
children:
children
,
),
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
},
),
),
);
);
expect
(
controller
.
v
alue
,
0
);
expect
(
groupV
alue
,
0
);
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
expect
(
controller
.
value
,
1
);
expect
(
groupValue
,
1
);
// Tapping the currently selected item should not change controller's value.
bool
valueChanged
=
false
;
controller
.
addListener
(()
{
valueChanged
=
true
;
});
// Tapping the currently selected item should not change groupValue.
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
expect
(
valueChanged
,
isFalse
);
expect
(
groupValue
,
1
);
expect
(
controller
.
value
,
1
);
});
testWidgets
(
'Changing controller works'
,
(
WidgetTester
tester
)
async
{
const
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{
0
:
Text
(
'Child 1'
),
1
:
Text
(
'Child 2'
),
2
:
Text
(
'Child 3'
),
};
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
0
);
final
ValueNotifier
<
int
>
newControlelr
=
ValueNotifier
<
int
>(
null
);
await
tester
.
pumpWidget
(
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
children:
children
,
controller:
controller
,
),
),
);
expect
(
currentUnscaledThumbRect
(
tester
,
useGlobalCoordinate:
true
).
center
,
offsetMoreOrLessEquals
(
tester
.
getCenter
(
find
.
text
(
'Child 1'
))),
);
await
tester
.
pumpWidget
(
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
children:
children
,
controller:
newControlelr
,
),
),
);
expect
(
currentUnscaledThumbRect
(
tester
,
useGlobalCoordinate:
true
),
isNull
,
);
});
testWidgets
(
'Can change controller value in build method'
,
(
WidgetTester
tester
)
async
{
const
Map
<
int
,
Widget
>
children
=
<
int
,
Widget
>{
0
:
Text
(
'Child 1'
),
1
:
Text
(
'Child 2'
),
2
:
Text
(
'Child 3'
),
};
int
currentIndex
=
0
;
StateSetter
setState
;
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
currentIndex
);
await
tester
.
pumpWidget
(
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setter
)
{
setState
=
setter
;
if
(
controller
.
value
!=
currentIndex
)
controller
.
value
=
currentIndex
;
return
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
children:
children
,
controller:
controller
,
),
);
},
),
);
expect
(
currentUnscaledThumbRect
(
tester
,
useGlobalCoordinate:
true
).
center
,
offsetMoreOrLessEquals
(
tester
.
getCenter
(
find
.
text
(
'Child 1'
))),
);
setState
(()
{
currentIndex
=
2
;
});
await
tester
.
pump
();
await
tester
.
pumpAndSettle
();
expect
(
currentUnscaledThumbRect
(
tester
,
useGlobalCoordinate:
true
).
center
,
offsetMoreOrLessEquals
(
tester
.
getCenter
(
find
.
text
(
'Child 3'
)),
epsilon:
0.01
),
);
});
});
testWidgets
(
testWidgets
(
...
@@ -353,16 +285,15 @@ void main() {
...
@@ -353,16 +285,15 @@ void main() {
1
:
Icon
(
IconData
(
1
)),
1
:
Icon
(
IconData
(
1
)),
};
};
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
0
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
CupertinoApp
(
CupertinoApp
(
theme:
const
CupertinoThemeData
(
brightness:
Brightness
.
dark
),
theme:
const
CupertinoThemeData
(
brightness:
Brightness
.
dark
),
home:
StatefulBuilder
(
home:
boilerplate
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
builder:
(
BuildContext
context
)
{
return
CupertinoSlidingSegmentedControl
<
int
>(
return
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
children:
children
,
controller:
controller
,
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
);
},
},
),
),
...
@@ -371,7 +302,7 @@ void main() {
...
@@ -371,7 +302,7 @@ void main() {
DefaultTextStyle
textStyle
=
tester
.
widget
(
find
.
widgetWithText
(
DefaultTextStyle
,
'Child 1'
).
first
);
DefaultTextStyle
textStyle
=
tester
.
widget
(
find
.
widgetWithText
(
DefaultTextStyle
,
'Child 1'
).
first
);
expect
(
textStyle
.
style
.
fontWeight
,
FontWeight
.
w
6
00
);
expect
(
textStyle
.
style
.
fontWeight
,
FontWeight
.
w
5
00
);
await
tester
.
tap
(
find
.
byIcon
(
const
IconData
(
1
)));
await
tester
.
tap
(
find
.
byIcon
(
const
IconData
(
1
)));
await
tester
.
pump
();
await
tester
.
pump
();
...
@@ -379,6 +310,7 @@ void main() {
...
@@ -379,6 +310,7 @@ void main() {
textStyle
=
tester
.
widget
(
find
.
widgetWithText
(
DefaultTextStyle
,
'Child 1'
).
first
);
textStyle
=
tester
.
widget
(
find
.
widgetWithText
(
DefaultTextStyle
,
'Child 1'
).
first
);
expect
(
groupValue
,
1
);
expect
(
textStyle
.
style
.
fontWeight
,
FontWeight
.
normal
);
expect
(
textStyle
.
style
.
fontWeight
,
FontWeight
.
normal
);
},
},
);
);
...
@@ -389,7 +321,6 @@ void main() {
...
@@ -389,7 +321,6 @@ void main() {
1
:
Icon
(
IconData
(
1
)),
1
:
Icon
(
IconData
(
1
)),
};
};
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
0
);
Brightness
brightness
=
Brightness
.
light
;
Brightness
brightness
=
Brightness
.
light
;
StateSetter
setState
;
StateSetter
setState
;
...
@@ -400,12 +331,15 @@ void main() {
...
@@ -400,12 +331,15 @@ void main() {
return
MediaQuery
(
return
MediaQuery
(
data:
MediaQueryData
(
platformBrightness:
brightness
),
data:
MediaQueryData
(
platformBrightness:
brightness
),
child:
boilerplate
(
child:
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
builder:
(
BuildContext
context
)
{
children:
children
,
return
CupertinoSlidingSegmentedControl
<
int
>(
controller:
controller
,
children:
children
,
thumbColor:
CupertinoColors
.
systemGreen
,
groupValue:
groupValue
,
backgroundColor:
CupertinoColors
.
systemRed
,
onValueChanged:
defaultCallback
,
),
thumbColor:
CupertinoColors
.
systemGreen
,
backgroundColor:
CupertinoColors
.
systemRed
,
);
},
),
),
);
);
},
},
...
@@ -443,14 +377,15 @@ void main() {
...
@@ -443,14 +377,15 @@ void main() {
2
:
Placeholder
(),
2
:
Placeholder
(),
};
};
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
0
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
builder:
(
BuildContext
context
)
{
children:
children
,
return
CupertinoSlidingSegmentedControl
<
int
>(
controller:
controller
,
children:
children
,
),
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
},
),
),
);
);
},
},
...
@@ -468,16 +403,18 @@ void main() {
...
@@ -468,16 +403,18 @@ void main() {
1
:
Text
(
'Child 2'
),
1
:
Text
(
'Child 2'
),
};
};
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
null
);
groupValue
=
null
;
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
StatefulBuilder
(
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
boilerplate
(
return
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
builder:
(
BuildContext
context
)
{
children:
children
,
return
CupertinoSlidingSegmentedControl
<
int
>(
controller:
controller
,
children:
children
,
),
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
},
);
);
},
},
),
),
...
@@ -496,14 +433,17 @@ void main() {
...
@@ -496,14 +433,17 @@ void main() {
};
};
// Child 3 is intially selected.
// Child 3 is intially selected.
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
2
)
;
groupValue
=
2
;
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
builder:
(
BuildContext
context
)
{
children:
children
,
return
CupertinoSlidingSegmentedControl
<
int
>(
controller:
controller
,
children:
children
,
),
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
},
),
),
);
);
...
@@ -571,15 +511,16 @@ void main() {
...
@@ -571,15 +511,16 @@ void main() {
2
:
Container
(
constraints:
const
BoxConstraints
.
tightFor
(
height:
200.0
)),
2
:
Container
(
constraints:
const
BoxConstraints
.
tightFor
(
height:
200.0
)),
};
};
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
null
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
builder:
(
BuildContext
context
)
{
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
return
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
controller:
controller
,
children:
children
,
),
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
},
),
),
);
);
...
@@ -600,14 +541,16 @@ void main() {
...
@@ -600,14 +541,16 @@ void main() {
2
:
Container
(
constraints:
const
BoxConstraints
.
tightFor
(
width:
200.0
)),
2
:
Container
(
constraints:
const
BoxConstraints
.
tightFor
(
width:
200.0
)),
};
};
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
null
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
builder:
(
BuildContext
context
)
{
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
return
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
controller:
controller
,
children:
children
,
),
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
},
),
),
);
);
...
@@ -628,19 +571,20 @@ void main() {
...
@@ -628,19 +571,20 @@ void main() {
1
:
SizedBox
(
width:
70
),
1
:
SizedBox
(
width:
70
),
};
};
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
null
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
boilerplate
(
child:
Row
(
builder:
(
BuildContext
context
)
{
children:
<
Widget
>[
return
Row
(
CupertinoSlidingSegmentedControl
<
int
>(
children:
<
Widget
>[
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
controller:
controller
,
children:
children
,
),
groupValue:
groupValue
,
],
onValueChanged:
defaultCallback
,
),
),
],
);
},
),
),
);
);
...
@@ -660,14 +604,19 @@ void main() {
...
@@ -660,14 +604,19 @@ void main() {
1
:
Text
(
'Child 2'
),
1
:
Text
(
'Child 2'
),
};
};
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
null
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Directionality
(
Directionality
(
textDirection:
TextDirection
.
rtl
,
textDirection:
TextDirection
.
rtl
,
child:
Center
(
child:
Center
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
child:
StatefulBuilder
(
children:
children
,
builder:
(
BuildContext
context
,
StateSetter
setter
)
{
controller:
controller
,
setState
=
setter
;
return
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
},
),
),
),
),
),
),
...
@@ -682,16 +631,19 @@ void main() {
...
@@ -682,16 +631,19 @@ void main() {
0
:
Text
(
'Child 1'
),
0
:
Text
(
'Child 1'
),
1
:
Text
(
'Child 2'
),
1
:
Text
(
'Child 2'
),
};
};
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
0
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Directionality
(
Directionality
(
textDirection:
TextDirection
.
rtl
,
textDirection:
TextDirection
.
rtl
,
child:
Center
(
child:
Center
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
child:
StatefulBuilder
(
children:
children
,
builder:
(
BuildContext
context
,
StateSetter
setter
)
{
controller:
controller
,
setState
=
setter
;
return
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
},
),
),
),
),
),
),
...
@@ -718,17 +670,15 @@ void main() {
...
@@ -718,17 +670,15 @@ void main() {
1
:
Text
(
'Child 2'
),
1
:
Text
(
'Child 2'
),
};
};
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
0
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Directionality
(
boilerplate
(
textDirection:
TextDirection
.
ltr
,
builder:
(
BuildContext
context
)
{
child:
Center
(
return
CupertinoSlidingSegmentedControl
<
int
>(
child:
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
children:
children
,
controller:
controller
,
groupValue:
groupValue
,
),
onValueChanged:
defaultCallback
,
),
);
},
),
),
);
);
...
@@ -810,25 +760,26 @@ void main() {
...
@@ -810,25 +760,26 @@ void main() {
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
0
]
=
const
Text
(
'Child 1'
);
children
[
1
]
=
const
SizedBox
();
children
[
1
]
=
const
SizedBox
();
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
0
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
builder:
(
BuildContext
context
)
{
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
return
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
controller:
controller
,
children:
children
,
),
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
},
),
),
);
);
expect
(
controller
.
v
alue
,
0
);
expect
(
groupV
alue
,
0
);
final
Offset
centerOfTwo
=
tester
.
getCenter
(
find
.
byWidget
(
children
[
1
]));
final
Offset
centerOfTwo
=
tester
.
getCenter
(
find
.
byWidget
(
children
[
1
]));
// Tap just inside segment bounds
// Tap just inside segment bounds
await
tester
.
tapAt
(
centerOfTwo
+
const
Offset
(
10
,
0
));
await
tester
.
tapAt
(
centerOfTwo
+
const
Offset
(
10
,
0
));
expect
(
controller
.
v
alue
,
1
);
expect
(
groupV
alue
,
1
);
});
});
testWidgets
(
'Thumb animation is correct when the selected segment changes'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Thumb animation is correct when the selected segment changes'
,
(
WidgetTester
tester
)
async
{
...
@@ -917,20 +868,23 @@ void main() {
...
@@ -917,20 +868,23 @@ void main() {
1
:
Text
(
'B'
),
1
:
Text
(
'B'
),
2
:
Text
(
'C'
),
2
:
Text
(
'C'
),
};
};
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
0
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
builder:
(
BuildContext
context
)
{
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
return
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
controller:
controller
,
children:
children
,
),
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
},
),
),
);
);
await
tester
.
tap
(
find
.
text
(
'B'
));
await
tester
.
tap
(
find
.
text
(
'B'
));
await
tester
.
pump
();
await
tester
.
pump
();
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
// Between A and B.
// Between A and B.
...
@@ -965,15 +919,16 @@ void main() {
...
@@ -965,15 +919,16 @@ void main() {
children
[
2
]
=
const
Text
(
'C'
);
children
[
2
]
=
const
Text
(
'C'
);
children
[
3
]
=
const
Text
(
'D'
);
children
[
3
]
=
const
Text
(
'D'
);
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
0
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
builder:
(
BuildContext
context
)
{
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
return
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
controller:
controller
,
children:
children
,
),
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
},
),
),
);
);
...
@@ -984,11 +939,14 @@ void main() {
...
@@ -984,11 +939,14 @@ void main() {
children
[
1
]
=
const
Text
(
'B'
);
children
[
1
]
=
const
Text
(
'B'
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
boilerplate
(
boilerplate
(
child:
CupertinoSlidingSegmentedControl
<
int
>(
builder:
(
BuildContext
context
)
{
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
return
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
key:
const
ValueKey
<
String
>(
'Segmented Control'
),
controller:
controller
,
children:
children
,
),
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
},
),
),
);
);
...
@@ -1005,7 +963,6 @@ void main() {
...
@@ -1005,7 +963,6 @@ void main() {
0
:
Text
(
'Child 1'
),
0
:
Text
(
'Child 1'
),
1
:
Text
(
'Child 2'
),
1
:
Text
(
'Child 2'
),
};
};
final
ValueNotifier
<
int
>
controller
=
ValueNotifier
<
int
>(
0
);
final
ScrollController
scrollController
=
ScrollController
();
final
ScrollController
scrollController
=
ScrollController
();
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
...
@@ -1015,9 +972,14 @@ void main() {
...
@@ -1015,9 +972,14 @@ void main() {
controller:
scrollController
,
controller:
scrollController
,
children:
<
Widget
>[
children:
<
Widget
>[
const
SizedBox
(
height:
100
),
const
SizedBox
(
height:
100
),
CupertinoSlidingSegmentedControl
<
int
>(
boilerplate
(
children:
children
,
builder:
(
BuildContext
context
)
{
controller:
controller
,
return
CupertinoSlidingSegmentedControl
<
int
>(
children:
children
,
groupValue:
groupValue
,
onValueChanged:
defaultCallback
,
);
},
),
),
const
SizedBox
(
height:
1000
),
const
SizedBox
(
height:
1000
),
],
],
...
@@ -1029,7 +991,7 @@ void main() {
...
@@ -1029,7 +991,7 @@ void main() {
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
tap
(
find
.
text
(
'Child 2'
));
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
controller
.
v
alue
,
1
);
expect
(
groupV
alue
,
1
);
// Vertical drag works for the scroll view.
// Vertical drag works for the scroll view.
final
TestGesture
gesture
=
await
tester
.
startGesture
(
tester
.
getCenter
(
find
.
text
(
'Child 1'
)));
final
TestGesture
gesture
=
await
tester
.
startGesture
(
tester
.
getCenter
(
find
.
text
(
'Child 1'
)));
...
@@ -1043,14 +1005,14 @@ void main() {
...
@@ -1043,14 +1005,14 @@ void main() {
expect
(
scrollController
.
offset
,
100
);
expect
(
scrollController
.
offset
,
100
);
// Does not affect the segmented control.
// Does not affect the segmented control.
expect
(
controller
.
v
alue
,
1
);
expect
(
groupV
alue
,
1
);
await
gesture
.
moveBy
(
const
Offset
(
0
,
100
));
await
gesture
.
moveBy
(
const
Offset
(
0
,
100
));
await
gesture
.
up
();
await
gesture
.
up
();
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
scrollController
.
offset
,
0
);
expect
(
scrollController
.
offset
,
0
);
expect
(
controller
.
v
alue
,
1
);
expect
(
groupV
alue
,
1
);
// Long press vertical drag is recognized by the segmented control.
// Long press vertical drag is recognized by the segmented control.
await
gesture
.
down
(
tester
.
getCenter
(
find
.
text
(
'Child 1'
)));
await
gesture
.
down
(
tester
.
getCenter
(
find
.
text
(
'Child 1'
)));
...
@@ -1061,7 +1023,7 @@ void main() {
...
@@ -1061,7 +1023,7 @@ void main() {
// Should not scroll.
// Should not scroll.
expect
(
scrollController
.
offset
,
0
);
expect
(
scrollController
.
offset
,
0
);
expect
(
controller
.
v
alue
,
1
);
expect
(
groupV
alue
,
1
);
await
gesture
.
moveBy
(
const
Offset
(
0
,
100
));
await
gesture
.
moveBy
(
const
Offset
(
0
,
100
));
await
gesture
.
moveBy
(
const
Offset
(
0
,
100
));
await
gesture
.
moveBy
(
const
Offset
(
0
,
100
));
...
@@ -1069,7 +1031,7 @@ void main() {
...
@@ -1069,7 +1031,7 @@ void main() {
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
scrollController
.
offset
,
0
);
expect
(
scrollController
.
offset
,
0
);
expect
(
controller
.
v
alue
,
0
);
expect
(
groupV
alue
,
0
);
// Horizontal drag is recognized by the segmentedControl.
// Horizontal drag is recognized by the segmentedControl.
await
gesture
.
down
(
tester
.
getCenter
(
find
.
text
(
'Child 1'
)));
await
gesture
.
down
(
tester
.
getCenter
(
find
.
text
(
'Child 1'
)));
...
@@ -1079,6 +1041,6 @@ void main() {
...
@@ -1079,6 +1041,6 @@ void main() {
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
scrollController
.
offset
,
0
);
expect
(
scrollController
.
offset
,
0
);
expect
(
controller
.
v
alue
,
1
);
expect
(
groupV
alue
,
1
);
});
});
}
}
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