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
767ce826
Commit
767ce826
authored
Apr 04, 2016
by
Adam Barth
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for discrete material sliders
Fixes #1541
parent
daa0d2df
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
327 additions
and
78 deletions
+327
-78
slider_demo.dart
examples/material_gallery/lib/demo/slider_demo.dart
+32
-41
slider.dart
packages/flutter/lib/src/material/slider.dart
+172
-23
time_picker.dart
packages/flutter/lib/src/material/time_picker.dart
+2
-9
text_painter.dart
packages/flutter/lib/src/painting/text_painter.dart
+31
-5
slider_test.dart
packages/flutter/test/material/slider_test.dart
+90
-0
No files found.
examples/material_gallery/lib/demo/slider_demo.dart
View file @
767ce826
...
...
@@ -11,53 +11,44 @@ class SliderDemo extends StatefulWidget {
class
_SliderDemoState
extends
State
<
SliderDemo
>
{
double
_value
=
25.0
;
double
_discreteValue
=
20.0
;
@override
Widget
build
(
BuildContext
context
)
{
return
new
Scaffold
(
appBar:
new
AppBar
(
title:
new
Text
(
"Sliders"
)),
body:
new
Block
(
children:
<
Widget
>[
new
Container
(
height:
100.0
,
child:
new
Center
(
child:
new
Row
(
children:
<
Widget
>[
new
Slider
(
value:
_value
,
min:
0.0
,
max:
100.0
,
onChanged:
(
double
value
)
{
setState
(()
{
_value
=
value
;
});
}
),
new
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16.0
),
child:
new
Text
(
_value
.
round
().
toString
().
padLeft
(
3
,
'0'
))
),
],
mainAxisAlignment:
MainAxisAlignment
.
collapse
appBar:
new
AppBar
(
title:
new
Text
(
'Sliders'
)),
body:
new
Column
(
mainAxisAlignment:
MainAxisAlignment
.
spaceAround
,
children:
<
Widget
>[
new
Center
(
child:
new
Slider
(
value:
_value
,
min:
0.0
,
max:
100.0
,
onChanged:
(
double
value
)
{
setState
(()
{
_value
=
value
;
});
}
)
)
),
new
Container
(
height:
100.0
,
child:
new
Center
(
child:
new
Row
(
children:
<
Widget
>[
// Disabled, but tracking the slider above.
new
Slider
(
value:
_value
/
100.0
),
new
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16.0
),
child:
new
Text
((
_value
/
100.0
).
toStringAsFixed
(
2
))
),
],
mainAxisAlignment:
MainAxisAlignment
.
collapse
),
new
Center
(
child:
new
Slider
(
value:
_value
/
100.0
)),
new
Center
(
child:
new
Slider
(
value:
_discreteValue
,
min:
0.0
,
max:
100.0
,
divisions:
5
,
label:
'
${_discreteValue.round()}
'
,
onChanged:
(
double
value
)
{
setState
(()
{
_discreteValue
=
value
;
});
}
)
)
)
]
)
)
,
]
)
);
}
}
packages/flutter/lib/src/material/slider.dart
View file @
767ce826
...
...
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:math'
as
math
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/widgets.dart'
;
...
...
@@ -10,10 +12,18 @@ import 'colors.dart';
import
'constants.dart'
;
import
'debug.dart'
;
import
'theme.dart'
;
import
'typography.dart'
;
/// A material design slider.
///
/// Used to select from a continuous range of values.
/// Used to select from a range of values.
///
/// A slider can be used to select from either a continuous or a discrete set of
/// values. The default is use a continuous range of values from [min] to [max].
/// To use discrete values, use a non-null value for [divisions], which
/// indicates the number of discrete intervals. For example, if [min] is 0.0 and
/// [max] is 50.0 and [divisions] is 5, then the slider can take on the values
/// discrete values 0.0, 10.0, 20.0, 30.0, 40.0, and 50.0.
///
/// The slider itself does not maintain any state. Instead, when the state of
/// the slider changes, the widget calls the [onChanged] callback. Most widgets
...
...
@@ -34,6 +44,8 @@ class Slider extends StatelessWidget {
this
.
value
,
this
.
min
:
0.0
,
this
.
max
:
1.0
,
this
.
divisions
,
this
.
label
,
this
.
activeColor
,
this
.
onChanged
})
:
super
(
key:
key
)
{
...
...
@@ -41,6 +53,7 @@ class Slider extends StatelessWidget {
assert
(
min
!=
null
);
assert
(
max
!=
null
);
assert
(
value
>=
min
&&
value
<=
max
);
assert
(
divisions
==
null
||
divisions
>
0
);
}
/// The currently selected value for this slider.
...
...
@@ -58,6 +71,18 @@ class Slider extends StatelessWidget {
/// Defaults to 1.0.
final
double
max
;
/// The number of discrete divisions.
///
/// Typically used with [label] to show the current discrete value.
///
/// If null, the slider is continuous.
final
int
divisions
;
/// A label to show above the slider when the slider is active.
///
/// Typically used to display the value of a discrete slider.
final
String
label
;
/// The color to use for the portion of the slider that has been selected.
///
/// Defaults to accent color of the current [Theme].
...
...
@@ -82,6 +107,8 @@ class Slider extends StatelessWidget {
assert
(
debugCheckHasMaterial
(
context
));
return
new
_SliderRenderObjectWidget
(
value:
(
value
-
min
)
/
(
max
-
min
),
divisions:
divisions
,
label:
label
,
activeColor:
activeColor
??
Theme
.
of
(
context
).
accentColor
,
onChanged:
onChanged
!=
null
?
_handleChanged
:
null
);
...
...
@@ -89,16 +116,26 @@ class Slider extends StatelessWidget {
}
class
_SliderRenderObjectWidget
extends
LeafRenderObjectWidget
{
_SliderRenderObjectWidget
({
Key
key
,
this
.
value
,
this
.
activeColor
,
this
.
onChanged
})
:
super
(
key:
key
);
_SliderRenderObjectWidget
({
Key
key
,
this
.
value
,
this
.
divisions
,
this
.
label
,
this
.
activeColor
,
this
.
onChanged
})
:
super
(
key:
key
);
final
double
value
;
final
int
divisions
;
final
String
label
;
final
Color
activeColor
;
final
ValueChanged
<
double
>
onChanged
;
@override
_RenderSlider
createRenderObject
(
BuildContext
context
)
=>
new
_RenderSlider
(
value:
value
,
divisions:
divisions
,
label:
label
,
activeColor:
activeColor
,
onChanged:
onChanged
);
...
...
@@ -107,6 +144,8 @@ class _SliderRenderObjectWidget extends LeafRenderObjectWidget {
void
updateRenderObject
(
BuildContext
context
,
_RenderSlider
renderObject
)
{
renderObject
..
value
=
value
..
divisions
=
divisions
..
label
=
label
..
activeColor
=
activeColor
..
onChanged
=
onChanged
;
}
...
...
@@ -122,16 +161,39 @@ final Color _kActiveTrackColor = Colors.grey[500];
final
Tween
<
double
>
_kReactionRadiusTween
=
new
Tween
<
double
>(
begin:
_kThumbRadius
,
end:
_kReactionRadius
);
final
Tween
<
double
>
_kThumbRadiusTween
=
new
Tween
<
double
>(
begin:
_kThumbRadius
,
end:
_kActiveThumbRadius
);
final
ColorTween
_kTrackColorTween
=
new
ColorTween
(
begin:
_kInactiveTrackColor
,
end:
_kActiveTrackColor
);
final
ColorTween
_kTickColorTween
=
new
ColorTween
(
begin:
_kInactiveTrackColor
,
end:
Colors
.
black54
);
final
Duration
_kDiscreteTransitionDuration
=
const
Duration
(
milliseconds:
500
);
const
double
_kLabelBalloonRadius
=
14.0
;
final
Tween
<
double
>
_kLabelBalloonCenterTween
=
new
Tween
<
double
>(
begin:
0.0
,
end:
-
_kLabelBalloonRadius
*
2.0
);
final
Tween
<
double
>
_kLabelBalloonRadiusTween
=
new
Tween
<
double
>(
begin:
_kThumbRadius
,
end:
_kLabelBalloonRadius
);
final
Tween
<
double
>
_kLabelBalloonTipTween
=
new
Tween
<
double
>(
begin:
0.0
,
end:
-
8.0
);
final
double
_kLabelBalloonTipAttachmentRatio
=
math
.
sin
(
math
.
PI
/
4.0
);
double
_getAdditionalHeightForLabel
(
String
label
)
{
return
label
==
null
?
0.0
:
_kLabelBalloonRadius
*
2.0
;
}
BoxConstraints
_getAdditionalConstraints
(
String
label
)
{
return
new
BoxConstraints
.
tightFor
(
width:
_kTrackWidth
+
2
*
_kReactionRadius
,
height:
2
*
_kReactionRadius
+
_getAdditionalHeightForLabel
(
label
)
);
}
class
_RenderSlider
extends
RenderConstrainedBox
{
_RenderSlider
({
double
value
,
int
divisions
,
String
label
,
Color
activeColor
,
this
.
onChanged
})
:
_value
=
value
,
_divisions
=
divisions
,
_activeColor
=
activeColor
,
super
(
additionalConstraints:
const
BoxConstraints
.
tightFor
(
width:
_kTrackWidth
+
2
*
_kReactionRadius
,
height:
2
*
_kReactionRadius
))
{
super
(
additionalConstraints:
_getAdditionalConstraints
(
label
))
{
assert
(
value
!=
null
&&
value
>=
0.0
&&
value
<=
1.0
);
this
.
label
=
label
;
_drag
=
new
HorizontalDragGestureRecognizer
()
..
onStart
=
_handleDragStart
..
onUpdate
=
_handleDragUpdate
...
...
@@ -141,6 +203,10 @@ class _RenderSlider extends RenderConstrainedBox {
parent:
_reactionController
,
curve:
Curves
.
ease
)..
addListener
(
markNeedsPaint
);
_position
=
new
AnimationController
(
value:
value
,
duration:
_kDiscreteTransitionDuration
)..
addListener
(
markNeedsPaint
);
}
double
get
value
=>
_value
;
...
...
@@ -150,6 +216,38 @@ class _RenderSlider extends RenderConstrainedBox {
if
(
newValue
==
_value
)
return
;
_value
=
newValue
;
if
(
divisions
!=
null
)
_position
.
animateTo
(
newValue
,
curve:
Curves
.
ease
);
else
_position
.
value
=
newValue
;
}
int
get
divisions
=>
_divisions
;
int
_divisions
;
void
set
divisions
(
int
newDivisions
)
{
if
(
newDivisions
==
_divisions
)
return
;
_divisions
=
newDivisions
;
markNeedsPaint
();
}
String
get
label
=>
_label
;
String
_label
;
void
set
label
(
String
newLabel
)
{
if
(
newLabel
==
_label
)
return
;
_label
=
newLabel
;
additionalConstraints
=
_getAdditionalConstraints
(
_label
);
if
(
newLabel
!=
null
)
{
_labelPainter
..
text
=
new
TextSpan
(
style:
Typography
.
white
.
body1
.
copyWith
(
fontSize:
10.0
),
text:
newLabel
)
..
layoutToMaxIntrinsicWidth
();
}
else
{
_labelPainter
.
text
=
null
;
}
markNeedsPaint
();
}
...
...
@@ -169,15 +267,25 @@ class _RenderSlider extends RenderConstrainedBox {
Animation
<
double
>
_reaction
;
AnimationController
_reactionController
;
AnimationController
_position
;
final
TextPainter
_labelPainter
=
new
TextPainter
();
HorizontalDragGestureRecognizer
_drag
;
bool
_active
=
false
;
double
_currentDragValue
=
0.0
;
double
get
_discretizedCurrentDragValue
{
double
dragValue
=
_currentDragValue
.
clamp
(
0.0
,
1.0
);
if
(
divisions
!=
null
)
dragValue
=
(
dragValue
*
divisions
).
round
()
/
divisions
;
return
dragValue
;
}
void
_handleDragStart
(
Point
globalPosition
)
{
if
(
onChanged
!=
null
)
{
_active
=
true
;
_currentDragValue
=
(
globalToLocal
(
globalPosition
).
x
-
_kReactionRadius
)
/
_trackLength
;
onChanged
(
_
currentDragValue
.
clamp
(
0.0
,
1.0
)
);
onChanged
(
_
discretizedCurrentDragValue
);
_reactionController
.
forward
();
markNeedsPaint
();
}
...
...
@@ -186,7 +294,7 @@ class _RenderSlider extends RenderConstrainedBox {
void
_handleDragUpdate
(
double
delta
)
{
if
(
onChanged
!=
null
)
{
_currentDragValue
+=
delta
/
_trackLength
;
onChanged
(
_
currentDragValue
.
clamp
(
0.0
,
1.0
)
);
onChanged
(
_
discretizedCurrentDragValue
);
}
}
...
...
@@ -214,33 +322,74 @@ class _RenderSlider extends RenderConstrainedBox {
final
double
trackLength
=
_trackLength
;
final
bool
enabled
=
onChanged
!=
null
;
final
double
value
=
_position
.
value
;
double
trackCenter
=
offset
.
dy
+
size
.
height
/
2.0
;
double
trackLeft
=
offset
.
dx
+
_kReactionRadius
;
double
trackTop
=
trackCenter
-
1.0
;
double
trackBottom
=
trackCenter
+
1.0
;
double
trackRight
=
trackLeft
+
trackLength
;
double
trackActive
=
trackLeft
+
trackLength
*
value
;
final
double
additionalHeightForLabel
=
_getAdditionalHeightForLabel
(
label
);
final
double
trackCenter
=
offset
.
dy
+
(
size
.
height
-
additionalHeightForLabel
)
/
2.0
+
additionalHeightForLabel
;
final
double
trackLeft
=
offset
.
dx
+
_kReactionRadius
;
final
double
trackTop
=
trackCenter
-
1.0
;
final
double
trackBottom
=
trackCenter
+
1.0
;
final
double
trackRight
=
trackLeft
+
trackLength
;
final
double
trackActive
=
trackLeft
+
trackLength
*
value
;
Paint
primaryPaint
=
new
Paint
()..
color
=
enabled
?
_activeColor
:
_kInactiveTrackColor
;
Paint
trackPaint
=
new
Paint
()..
color
=
_kTrackColorTween
.
evaluate
(
_reaction
);
final
Paint
primaryPaint
=
new
Paint
()..
color
=
enabled
?
_activeColor
:
_kInactiveTrackColor
;
final
Paint
trackPaint
=
new
Paint
()..
color
=
_kTrackColorTween
.
evaluate
(
_reaction
);
double
thumbRadius
=
enabled
?
_kThumbRadiusTween
.
evaluate
(
_reaction
)
:
_kDisabledThumbRadius
;
Point
activeLocation
=
new
Point
(
trackActive
,
trackCenter
)
;
final
Point
thumbCenter
=
new
Point
(
trackActive
,
trackCenter
)
;
final
double
thumbRadius
=
enabled
?
_kThumbRadiusTween
.
evaluate
(
_reaction
)
:
_kDisabledThumbRadius
;
if
(
enabled
)
{
canvas
.
drawRect
(
new
Rect
.
fromLTRB
(
trackLeft
,
trackTop
,
trackRight
,
trackBottom
),
trackPaint
);
if
(
_value
>
0.0
)
if
(
value
>
0.0
)
canvas
.
drawRect
(
new
Rect
.
fromLTRB
(
trackLeft
,
trackTop
,
trackActive
,
trackBottom
),
primaryPaint
);
if
(
value
<
1.0
)
canvas
.
drawRect
(
new
Rect
.
fromLTRB
(
trackActive
,
trackTop
,
trackRight
,
trackBottom
),
trackPaint
);
}
else
{
canvas
.
drawRect
(
new
Rect
.
fromLTRB
(
trackLeft
,
trackTop
,
activeLocation
.
x
-
_kDisabledThumbRadius
-
2
,
trackBottom
),
trackPaint
);
canvas
.
drawRect
(
new
Rect
.
fromLTRB
(
activeLocation
.
x
+
_kDisabledThumbRadius
+
2
,
trackTop
,
trackRight
,
trackBottom
),
trackPaint
);
if
(
value
>
0.0
)
canvas
.
drawRect
(
new
Rect
.
fromLTRB
(
trackLeft
,
trackTop
,
trackActive
-
_kDisabledThumbRadius
-
2
,
trackBottom
),
trackPaint
);
if
(
value
<
1.0
)
canvas
.
drawRect
(
new
Rect
.
fromLTRB
(
trackActive
+
_kDisabledThumbRadius
+
2
,
trackTop
,
trackRight
,
trackBottom
),
trackPaint
);
}
if
(
_reaction
.
status
!=
AnimationStatus
.
dismissed
)
{
Paint
reactionPaint
=
new
Paint
()..
color
=
_activeColor
.
withAlpha
(
kRadialReactionAlpha
);
canvas
.
drawCircle
(
activeLocation
,
_kReactionRadiusTween
.
evaluate
(
_reaction
),
reactionPaint
);
final
int
divisions
=
this
.
divisions
;
if
(
divisions
!=
null
)
{
const
double
tickWidth
=
2.0
;
final
double
dx
=
(
trackLength
-
tickWidth
)
/
divisions
;
// If the ticks would be too dense, don't bother painting them.
if
(
dx
>=
3
*
tickWidth
)
{
final
Paint
tickPaint
=
new
Paint
()..
color
=
_kTickColorTween
.
evaluate
(
_reaction
);
for
(
int
i
=
0
;
i
<=
divisions
;
i
+=
1
)
{
double
left
=
trackLeft
+
i
*
dx
;
canvas
.
drawRect
(
new
Rect
.
fromLTRB
(
left
,
trackTop
,
left
+
tickWidth
,
trackBottom
),
tickPaint
);
}
}
}
if
(
label
!=
null
)
{
final
Point
center
=
new
Point
(
trackActive
,
_kLabelBalloonCenterTween
.
evaluate
(
_reaction
)
+
trackCenter
);
final
double
radius
=
_kLabelBalloonRadiusTween
.
evaluate
(
_reaction
);
final
Point
tip
=
new
Point
(
trackActive
,
_kLabelBalloonTipTween
.
evaluate
(
_reaction
)
+
trackCenter
);
final
double
tipAttachment
=
_kLabelBalloonTipAttachmentRatio
*
radius
;
canvas
.
drawCircle
(
center
,
radius
,
primaryPaint
);
Path
path
=
new
Path
()
..
moveTo
(
tip
.
x
,
tip
.
y
)
..
lineTo
(
center
.
x
-
tipAttachment
,
center
.
y
+
tipAttachment
)
..
lineTo
(
center
.
x
+
tipAttachment
,
center
.
y
+
tipAttachment
)
..
close
();
canvas
.
drawPath
(
path
,
primaryPaint
);
_labelPainter
.
layout
();
Offset
labelOffset
=
new
Offset
(
center
.
x
-
_labelPainter
.
width
/
2.0
,
center
.
y
-
_labelPainter
.
height
/
2.0
);
_labelPainter
.
paint
(
canvas
,
labelOffset
);
return
;
}
else
{
Paint
reactionPaint
=
new
Paint
()..
color
=
_activeColor
.
withAlpha
(
kRadialReactionAlpha
);
canvas
.
drawCircle
(
thumbCenter
,
_kReactionRadiusTween
.
evaluate
(
_reaction
),
reactionPaint
);
}
}
canvas
.
drawCircle
(
activeLocation
,
thumbRadius
,
primaryPaint
);
canvas
.
drawCircle
(
thumbCenter
,
thumbRadius
,
primaryPaint
);
}
}
packages/flutter/lib/src/material/time_picker.dart
View file @
767ce826
...
...
@@ -259,16 +259,9 @@ List<TextPainter> _initPainters(List<String> labels) {
List
<
TextPainter
>
painters
=
new
List
<
TextPainter
>(
labels
.
length
);
for
(
int
i
=
0
;
i
<
painters
.
length
;
++
i
)
{
String
label
=
labels
[
i
];
TextPainter
painter
=
new
TextPainter
(
painters
[
i
]
=
new
TextPainter
(
new
TextSpan
(
style:
style
,
text:
label
)
);
painter
..
maxWidth
=
double
.
INFINITY
..
maxHeight
=
double
.
INFINITY
..
layout
()
..
maxWidth
=
painter
.
maxIntrinsicWidth
..
layout
();
painters
[
i
]
=
painter
;
)..
layoutToMaxIntrinsicWidth
();
}
return
painters
;
}
...
...
packages/flutter/lib/src/painting/text_painter.dart
View file @
767ce826
...
...
@@ -243,7 +243,7 @@ class TextPainter {
}
ui
.
Paragraph
_paragraph
;
bool
_needsLayout
=
tru
e
;
bool
_needsLayout
=
fals
e
;
TextSpan
_text
;
/// The (potentially styled) text to paint.
...
...
@@ -253,10 +253,15 @@ class TextPainter {
if
(
_text
==
value
)
return
;
_text
=
value
;
ui
.
ParagraphBuilder
builder
=
new
ui
.
ParagraphBuilder
();
_text
.
build
(
builder
);
_paragraph
=
builder
.
build
(
_text
.
style
?.
paragraphStyle
??
new
ui
.
ParagraphStyle
());
_needsLayout
=
true
;
if
(
_text
!=
null
)
{
ui
.
ParagraphBuilder
builder
=
new
ui
.
ParagraphBuilder
();
_text
.
build
(
builder
);
_paragraph
=
builder
.
build
(
_text
.
style
?.
paragraphStyle
??
new
ui
.
ParagraphStyle
());
_needsLayout
=
true
;
}
else
{
_paragraph
=
null
;
_needsLayout
=
false
;
}
}
/// The minimum width at which to layout the text.
...
...
@@ -343,12 +348,33 @@ class TextPainter {
}
}
bool
_lastLayoutWasToMaxIntrinsicWidth
=
false
;
/// Computes the visual position of the glyphs for painting the text.
void
layout
()
{
if
(!
_needsLayout
)
return
;
_paragraph
.
layout
();
_needsLayout
=
false
;
_lastLayoutWasToMaxIntrinsicWidth
=
false
;
}
/// Computes the visual position of the glyphs using the unconstrainted max intrinsic width.
void
layoutToMaxIntrinsicWidth
()
{
if
(!
_needsLayout
&&
_lastLayoutWasToMaxIntrinsicWidth
&&
width
==
maxIntrinsicWidth
)
return
;
_needsLayout
=
false
;
_lastLayoutWasToMaxIntrinsicWidth
=
true
;
_paragraph
..
minWidth
=
0.0
..
maxWidth
=
double
.
INFINITY
..
layout
();
final
double
newMaxIntrinsicWidth
=
maxIntrinsicWidth
;
_paragraph
..
minWidth
=
newMaxIntrinsicWidth
..
maxWidth
=
newMaxIntrinsicWidth
..
layout
();
assert
(
width
==
maxIntrinsicWidth
);
}
/// Paints the text onto the given canvas at the given offset.
...
...
packages/flutter/test/material/slider_test.dart
0 → 100644
View file @
767ce826
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/material.dart'
;
import
'package:flutter/scheduler.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'package:test/test.dart'
;
void
main
(
)
{
test
(
'Slider can move when tapped'
,
()
{
testWidgets
((
WidgetTester
tester
)
{
Key
sliderKey
=
new
UniqueKey
();
double
value
=
0.0
;
tester
.
pumpWidget
(
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
new
Material
(
child:
new
Center
(
child:
new
Slider
(
key:
sliderKey
,
value:
value
,
onChanged:
(
double
newValue
)
{
setState
(()
{
value
=
newValue
;
});
}
)
)
);
}
)
);
expect
(
value
,
equals
(
0.0
));
tester
.
tap
(
tester
.
findElementByKey
(
sliderKey
));
expect
(
value
,
equals
(
0.5
));
tester
.
pump
();
// No animation should start.
expect
(
Scheduler
.
instance
.
transientCallbackCount
,
equals
(
0
));
});
});
test
(
'Slider take on discrete values'
,
()
{
testWidgets
((
WidgetTester
tester
)
{
Key
sliderKey
=
new
UniqueKey
();
double
value
=
0.0
;
tester
.
pumpWidget
(
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
new
Material
(
child:
new
Center
(
child:
new
Slider
(
key:
sliderKey
,
min:
0.0
,
max:
100.0
,
divisions:
10
,
value:
value
,
onChanged:
(
double
newValue
)
{
setState
(()
{
value
=
newValue
;
});
}
)
)
);
}
)
);
expect
(
value
,
equals
(
0.0
));
tester
.
tap
(
tester
.
findElementByKey
(
sliderKey
));
expect
(
value
,
equals
(
50.0
));
tester
.
scroll
(
tester
.
findElementByKey
(
sliderKey
),
const
Offset
(
5.0
,
0.0
));
expect
(
value
,
equals
(
50.0
));
tester
.
scroll
(
tester
.
findElementByKey
(
sliderKey
),
const
Offset
(
40.0
,
0.0
));
expect
(
value
,
equals
(
80.0
));
tester
.
pump
();
// Starts animation.
expect
(
Scheduler
.
instance
.
transientCallbackCount
,
greaterThan
(
0
));
tester
.
pump
(
const
Duration
(
milliseconds:
200
));
tester
.
pump
(
const
Duration
(
milliseconds:
200
));
tester
.
pump
(
const
Duration
(
milliseconds:
200
));
tester
.
pump
(
const
Duration
(
milliseconds:
200
));
// Animation complete.
expect
(
Scheduler
.
instance
.
transientCallbackCount
,
equals
(
0
));
});
});
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment