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
c24b2c3c
Unverified
Commit
c24b2c3c
authored
Jan 14, 2022
by
Hans Muller
Committed by
GitHub
Jan 14, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Slider: add themeable mouse cursor v2 (#96623)
parent
e78f135f
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
139 additions
and
16 deletions
+139
-16
slider.dart
packages/flutter/lib/src/material/slider.dart
+27
-15
slider_theme.dart
packages/flutter/lib/src/material/slider_theme.dart
+14
-1
slider_test.dart
packages/flutter/test/material/slider_test.dart
+80
-0
slider_theme_test.dart
packages/flutter/test/material/slider_theme_test.dart
+18
-0
No files found.
packages/flutter/lib/src/material/slider.dart
View file @
c24b2c3c
...
...
@@ -373,17 +373,26 @@ class Slider extends StatefulWidget {
/// (like the native default iOS slider).
final
Color
?
thumbColor
;
/// {@template flutter.material.slider.mouseCursor}
/// The cursor for a mouse pointer when it enters or is hovering over the
/// widget.
///
/// If [mouseCursor] is a [MaterialStateProperty<MouseCursor>],
/// [MaterialStateProperty.resolve] is used for the following [MaterialState]s:
///
/// * [MaterialState.dragged].
/// * [MaterialState.hovered].
/// * [MaterialState.focused].
/// * [MaterialState.disabled].
/// {@endtemplate}
///
/// If this property is null, [MaterialStateMouseCursor.clickable] will be used.
/// If null, then the value of [SliderThemeData.mouseCursor] is used. If that
/// is also null, then [MaterialStateMouseCursor.clickable] is used.
///
/// See also:
///
/// * [MaterialStateMouseCursor], which can be used to create a [MouseCursor]
/// that is also a [MaterialStateProperty<MouseCursor>].
final
MouseCursor
?
mouseCursor
;
/// The callback used to create a semantic value from a slider value.
...
...
@@ -481,6 +490,8 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
// Value Indicator Animation that appears on the Overlay.
PaintValueIndicator
?
paintValueIndicator
;
bool
_dragging
=
false
;
FocusNode
?
_focusNode
;
FocusNode
get
focusNode
=>
widget
.
focusNode
??
_focusNode
!;
...
...
@@ -540,13 +551,13 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
}
void
_handleDragStart
(
double
value
)
{
assert
(
widget
.
onChangeStart
!=
null
)
;
widget
.
onChangeStart
!
(
_lerp
(
value
));
_dragging
=
true
;
widget
.
onChangeStart
?.
call
(
_lerp
(
value
));
}
void
_handleDragEnd
(
double
value
)
{
assert
(
widget
.
onChangeEnd
!=
null
)
;
widget
.
onChangeEnd
!
(
_lerp
(
value
));
_dragging
=
false
;
widget
.
onChangeEnd
?.
call
(
_lerp
(
value
));
}
void
_actionHandler
(
_AdjustSliderIntent
intent
)
{
...
...
@@ -692,14 +703,15 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
color:
theme
.
colorScheme
.
onPrimary
,
),
);
final
MouseCursor
effectiveMouseCursor
=
MaterialStateProperty
.
resolveAs
<
MouseCursor
>(
widget
.
mouseCursor
??
MaterialStateMouseCursor
.
clickable
,
<
MaterialState
>{
if
(!
_enabled
)
MaterialState
.
disabled
,
if
(
_hovering
)
MaterialState
.
hovered
,
if
(
_focused
)
MaterialState
.
focused
,
},
);
final
Set
<
MaterialState
>
states
=
<
MaterialState
>{
if
(!
_enabled
)
MaterialState
.
disabled
,
if
(
_hovering
)
MaterialState
.
hovered
,
if
(
_focused
)
MaterialState
.
focused
,
if
(
_dragging
)
MaterialState
.
dragged
,
};
final
MouseCursor
effectiveMouseCursor
=
MaterialStateProperty
.
resolveAs
<
MouseCursor
?>(
widget
.
mouseCursor
,
states
)
??
sliderTheme
.
mouseCursor
?.
resolve
(
states
)
??
MaterialStateMouseCursor
.
clickable
.
resolve
(
states
);
// This size is used as the max bounds for the painting of the value
// indicators It must be kept in sync with the function with the same name
...
...
@@ -748,8 +760,8 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
textScaleFactor:
MediaQuery
.
of
(
context
).
textScaleFactor
,
screenSize:
_screenSize
(),
onChanged:
(
widget
.
onChanged
!=
null
)
&&
(
widget
.
max
>
widget
.
min
)
?
_handleChanged
:
null
,
onChangeStart:
widget
.
onChangeStart
!=
null
?
_handleDragStart
:
null
,
onChangeEnd:
widget
.
onChangeEnd
!=
null
?
_handleDragEnd
:
null
,
onChangeStart:
_handleDragStart
,
onChangeEnd:
_handleDragEnd
,
state:
this
,
semanticFormatterCallback:
widget
.
semanticFormatterCallback
,
hasFocus:
_focused
,
...
...
packages/flutter/lib/src/material/slider_theme.dart
View file @
c24b2c3c
...
...
@@ -10,6 +10,7 @@ import 'package:flutter/rendering.dart';
import
'package:flutter/widgets.dart'
;
import
'colors.dart'
;
import
'material_state.dart'
;
import
'theme.dart'
;
/// Applies a slider theme to descendant [Slider] widgets.
...
...
@@ -290,6 +291,7 @@ class SliderThemeData with Diagnosticable {
this
.
valueIndicatorTextStyle
,
this
.
minThumbSeparation
,
this
.
thumbSelector
,
this
.
mouseCursor
,
});
/// Generates a SliderThemeData from three main colors.
...
...
@@ -561,6 +563,11 @@ class SliderThemeData with Diagnosticable {
/// Override this for custom thumb selection.
final
RangeThumbSelector
?
thumbSelector
;
/// {@macro flutter.material.slider.mouseCursor}
///
/// If specified, overrides the default value of [Slider.mouseCursor].
final
MaterialStateProperty
<
MouseCursor
?>?
mouseCursor
;
/// Creates a copy of this object but with the given fields replaced with the
/// new values.
SliderThemeData
copyWith
({
...
...
@@ -591,6 +598,7 @@ class SliderThemeData with Diagnosticable {
TextStyle
?
valueIndicatorTextStyle
,
double
?
minThumbSeparation
,
RangeThumbSelector
?
thumbSelector
,
MaterialStateProperty
<
MouseCursor
?>?
mouseCursor
,
})
{
return
SliderThemeData
(
trackHeight:
trackHeight
??
this
.
trackHeight
,
...
...
@@ -620,6 +628,7 @@ class SliderThemeData with Diagnosticable {
valueIndicatorTextStyle:
valueIndicatorTextStyle
??
this
.
valueIndicatorTextStyle
,
minThumbSeparation:
minThumbSeparation
??
this
.
minThumbSeparation
,
thumbSelector:
thumbSelector
??
this
.
thumbSelector
,
mouseCursor:
mouseCursor
??
this
.
mouseCursor
,
);
}
...
...
@@ -660,6 +669,7 @@ class SliderThemeData with Diagnosticable {
valueIndicatorTextStyle:
TextStyle
.
lerp
(
a
.
valueIndicatorTextStyle
,
b
.
valueIndicatorTextStyle
,
t
),
minThumbSeparation:
lerpDouble
(
a
.
minThumbSeparation
,
b
.
minThumbSeparation
,
t
),
thumbSelector:
t
<
0.5
?
a
.
thumbSelector
:
b
.
thumbSelector
,
mouseCursor:
t
<
0.5
?
a
.
mouseCursor
:
b
.
mouseCursor
,
);
}
...
...
@@ -693,6 +703,7 @@ class SliderThemeData with Diagnosticable {
valueIndicatorTextStyle
,
minThumbSeparation
,
thumbSelector
,
mouseCursor
,
]);
}
...
...
@@ -731,7 +742,8 @@ class SliderThemeData with Diagnosticable {
&&
other
.
showValueIndicator
==
showValueIndicator
&&
other
.
valueIndicatorTextStyle
==
valueIndicatorTextStyle
&&
other
.
minThumbSeparation
==
minThumbSeparation
&&
other
.
thumbSelector
==
thumbSelector
;
&&
other
.
thumbSelector
==
thumbSelector
&&
other
.
mouseCursor
==
mouseCursor
;
}
@override
...
...
@@ -765,6 +777,7 @@ class SliderThemeData with Diagnosticable {
properties
.
add
(
DiagnosticsProperty
<
TextStyle
>(
'valueIndicatorTextStyle'
,
valueIndicatorTextStyle
,
defaultValue:
defaultData
.
valueIndicatorTextStyle
));
properties
.
add
(
DoubleProperty
(
'minThumbSeparation'
,
minThumbSeparation
,
defaultValue:
defaultData
.
minThumbSeparation
));
properties
.
add
(
DiagnosticsProperty
<
RangeThumbSelector
>(
'thumbSelector'
,
thumbSelector
,
defaultValue:
defaultData
.
thumbSelector
));
properties
.
add
(
DiagnosticsProperty
<
MaterialStateProperty
<
MouseCursor
?>>(
'mouseCursor'
,
mouseCursor
,
defaultValue:
defaultData
.
mouseCursor
));
}
}
...
...
packages/flutter/test/material/slider_test.dart
View file @
c24b2c3c
...
...
@@ -70,6 +70,35 @@ class TallSliderTickMarkShape extends SliderTickMarkShape {
}
}
class
_StateDependentMouseCursor
extends
MaterialStateMouseCursor
{
const
_StateDependentMouseCursor
({
this
.
disabled
=
SystemMouseCursors
.
none
,
this
.
dragged
=
SystemMouseCursors
.
none
,
this
.
hovered
=
SystemMouseCursors
.
none
,
});
final
MouseCursor
disabled
;
final
MouseCursor
hovered
;
final
MouseCursor
dragged
;
@override
MouseCursor
resolve
(
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
disabled
))
{
return
disabled
;
}
if
(
states
.
contains
(
MaterialState
.
dragged
))
{
return
dragged
;
}
if
(
states
.
contains
(
MaterialState
.
hovered
))
{
return
hovered
;
}
return
SystemMouseCursors
.
none
;
}
@override
String
get
debugDescription
=>
'_StateDependentMouseCursor'
;
}
void
main
(
)
{
testWidgets
(
'Slider can move when tapped (LTR)'
,
(
WidgetTester
tester
)
async
{
final
Key
sliderKey
=
UniqueKey
();
...
...
@@ -2521,6 +2550,57 @@ void main() {
expect
(
RendererBinding
.
instance
!.
mouseTracker
.
debugDeviceActiveCursor
(
1
),
SystemMouseCursors
.
click
);
});
testWidgets
(
'Slider MaterialStateMouseCursor resolves correctly'
,
(
WidgetTester
tester
)
async
{
const
MouseCursor
disabledCursor
=
SystemMouseCursors
.
basic
;
const
MouseCursor
hoveredCursor
=
SystemMouseCursors
.
grab
;
const
MouseCursor
draggedCursor
=
SystemMouseCursors
.
move
;
Widget
buildFrame
({
required
bool
enabled
})
{
return
MaterialApp
(
home:
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
Material
(
child:
Center
(
child:
MouseRegion
(
cursor:
SystemMouseCursors
.
forbidden
,
child:
Slider
(
mouseCursor:
const
_StateDependentMouseCursor
(
disabled:
disabledCursor
,
hovered:
hoveredCursor
,
dragged:
draggedCursor
,
),
value:
0.5
,
onChanged:
enabled
?
(
double
newValue
)
{
}
:
null
,
),
),
),
),
),
);
}
final
TestGesture
gesture
=
await
tester
.
createGesture
(
kind:
PointerDeviceKind
.
mouse
,
pointer:
1
);
await
gesture
.
addPointer
(
location:
Offset
.
zero
);
addTearDown
(
gesture
.
removePointer
);
await
tester
.
pumpWidget
(
buildFrame
(
enabled:
false
));
expect
(
RendererBinding
.
instance
!.
mouseTracker
.
debugDeviceActiveCursor
(
1
),
disabledCursor
);
await
tester
.
pumpWidget
(
buildFrame
(
enabled:
true
));
expect
(
RendererBinding
.
instance
!.
mouseTracker
.
debugDeviceActiveCursor
(
1
),
SystemMouseCursors
.
none
);
await
gesture
.
moveTo
(
tester
.
getCenter
(
find
.
byType
(
Slider
)));
// start hover
await
tester
.
pumpAndSettle
();
expect
(
RendererBinding
.
instance
!.
mouseTracker
.
debugDeviceActiveCursor
(
1
),
hoveredCursor
);
await
tester
.
timedDrag
(
find
.
byType
(
Slider
),
const
Offset
(
20.0
,
0.0
),
const
Duration
(
milliseconds:
100
),
);
expect
(
RendererBinding
.
instance
!.
mouseTracker
.
debugDeviceActiveCursor
(
1
),
SystemMouseCursors
.
move
);
});
testWidgets
(
'Slider implements debugFillProperties'
,
(
WidgetTester
tester
)
async
{
final
DiagnosticPropertiesBuilder
builder
=
DiagnosticPropertiesBuilder
();
...
...
packages/flutter/test/material/slider_theme_test.dart
View file @
c24b2c3c
...
...
@@ -4,6 +4,7 @@
import
'dart:ui'
show
window
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
...
...
@@ -57,6 +58,7 @@ void main() {
rangeValueIndicatorShape:
PaddleRangeSliderValueIndicatorShape
(),
showValueIndicator:
ShowValueIndicator
.
always
,
valueIndicatorTextStyle:
TextStyle
(
color:
Colors
.
black
),
mouseCursor:
MaterialStateMouseCursor
.
clickable
,
).
debugFillProperties
(
builder
);
final
List
<
String
>
description
=
builder
.
properties
...
...
@@ -90,6 +92,7 @@ void main() {
"rangeValueIndicatorShape: Instance of 'PaddleRangeSliderValueIndicatorShape'"
,
'showValueIndicator: always'
,
'valueIndicatorTextStyle: TextStyle(inherit: true, color: Color(0xff000000))'
,
'mouseCursor: MaterialStateMouseCursor(clickable)'
]);
});
...
...
@@ -1242,6 +1245,21 @@ void main() {
);
});
testWidgets
(
'The mouse cursor is themeable'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
_buildApp
(
ThemeData
().
sliderTheme
.
copyWith
(
mouseCursor:
MaterialStateProperty
.
all
(
SystemMouseCursors
.
text
),
)
));
await
tester
.
pumpAndSettle
();
final
TestGesture
gesture
=
await
tester
.
createGesture
(
kind:
PointerDeviceKind
.
mouse
);
await
gesture
.
addPointer
();
addTearDown
(
gesture
.
removePointer
);
await
gesture
.
moveTo
(
tester
.
getCenter
(
find
.
byType
(
Slider
)));
await
tester
.
pumpAndSettle
();
expect
(
RendererBinding
.
instance
!.
mouseTracker
.
debugDeviceActiveCursor
(
1
),
SystemMouseCursors
.
text
);
});
}
class
RoundedRectSliderTrackShapeWithCustomAdditionalActiveTrackHeight
extends
RoundedRectSliderTrackShape
{
...
...
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