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
09008e6f
Unverified
Commit
09008e6f
authored
Jan 13, 2021
by
Kate Lovett
Committed by
GitHub
Jan 13, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add ScrollbarTheme/ScrollbarThemeData (#72308)
parent
cbe72db1
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
919 additions
and
32 deletions
+919
-32
material.dart
packages/flutter/lib/material.dart
+1
-0
scrollbar.dart
packages/flutter/lib/src/material/scrollbar.dart
+45
-25
scrollbar_theme.dart
packages/flutter/lib/src/material/scrollbar_theme.dart
+284
-0
theme_data.dart
packages/flutter/lib/src/material/theme_data.dart
+15
-0
scrollbar.dart
packages/flutter/lib/src/widgets/scrollbar.dart
+14
-7
scrollbar_theme_test.dart
packages/flutter/test/material/scrollbar_theme_test.dart
+557
-0
snack_bar_test.dart
packages/flutter/test/material/snack_bar_test.dart
+1
-0
theme_data_test.dart
packages/flutter/test/material/theme_data_test.dart
+2
-0
No files found.
packages/flutter/lib/material.dart
View file @
09008e6f
...
...
@@ -115,6 +115,7 @@ export 'src/material/refresh_indicator.dart';
export
'src/material/reorderable_list.dart'
;
export
'src/material/scaffold.dart'
;
export
'src/material/scrollbar.dart'
;
export
'src/material/scrollbar_theme.dart'
;
export
'src/material/search.dart'
;
export
'src/material/selectable_text.dart'
;
export
'src/material/shadows.dart'
;
...
...
packages/flutter/lib/src/material/scrollbar.dart
View file @
09008e6f
...
...
@@ -8,6 +8,7 @@ import 'package:flutter/widgets.dart';
import
'color_scheme.dart'
;
import
'material_state.dart'
;
import
'scrollbar_theme.dart'
;
import
'theme.dart'
;
const
double
_kScrollbarThickness
=
8.0
;
...
...
@@ -37,6 +38,7 @@ const Duration _kScrollbarTimeToFade = Duration(milliseconds: 600);
///
/// * [RawScrollbar], a basic scrollbar that fades in and out, extended
/// by this class to add more animations and behaviors.
/// * [ScrollbarTheme], which configures the Scrollbar's appearance.
/// * [CupertinoScrollbar], an iOS style scrollbar.
/// * [ListView], which displays a linear, scrollable list of children.
/// * [GridView], which displays a 2 dimensional, scrollable array of children.
...
...
@@ -59,8 +61,8 @@ class Scrollbar extends RawScrollbar {
Key
?
key
,
required
Widget
child
,
ScrollController
?
controller
,
bool
isAlwaysShown
=
false
,
this
.
showTrackOnHover
=
false
,
bool
?
isAlwaysShown
,
this
.
showTrackOnHover
,
this
.
hoverThickness
,
double
?
thickness
,
Radius
?
radius
,
...
...
@@ -78,13 +80,17 @@ class Scrollbar extends RawScrollbar {
/// Controls if the track will show on hover and remain, including during drag.
///
/// Defaults to false, cannot be null.
final
bool
showTrackOnHover
;
/// If this property is null, then [ScrollbarThemeData.showTrackOnHover] of
/// [ThemeData.scrollbarTheme] is used. If that is also null, the default value
/// is false.
final
bool
?
showTrackOnHover
;
/// The thickness of the scrollbar when a hover state is active and
/// [showTrackOnHover] is true.
///
/// Defaults to 12.0 dp when null.
/// If this property is null, then [ScrollbarThemeData.thickness] of
/// [ThemeData.scrollbarTheme] is used to resolve a thickness. If that is also
/// null, the default value is 12.0 pixels.
final
double
?
hoverThickness
;
@override
...
...
@@ -96,9 +102,15 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
bool
_dragIsActive
=
false
;
bool
_hoverIsActive
=
false
;
late
ColorScheme
_colorScheme
;
late
ScrollbarThemeData
_scrollbarTheme
;
// On Android, scrollbars should match native appearance.
late
bool
_useAndroidScrollbar
;
@override
bool
get
showScrollbar
=>
widget
.
isAlwaysShown
??
_scrollbarTheme
.
isAlwaysShown
??
false
;
bool
get
_showTrackOnHover
=>
widget
.
showTrackOnHover
??
_scrollbarTheme
.
showTrackOnHover
??
false
;
Set
<
MaterialState
>
get
_states
=>
<
MaterialState
>{
if
(
_dragIsActive
)
MaterialState
.
dragged
,
if
(
_hoverIsActive
)
MaterialState
.
hovered
,
...
...
@@ -125,16 +137,16 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
return
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
dragged
))
return
dragColor
;
return
_scrollbarTheme
.
thumbColor
?.
resolve
(
states
)
??
dragColor
;
// If the track is visible, the thumb color hover animation is ignored and
// changes immediately.
if
(
states
.
contains
(
MaterialState
.
hovered
)
&&
widget
.
showTrackOnHover
)
return
hoverColor
;
if
(
states
.
contains
(
MaterialState
.
hovered
)
&&
_
showTrackOnHover
)
return
_scrollbarTheme
.
thumbColor
?.
resolve
(
states
)
??
hoverColor
;
return
Color
.
lerp
(
idleColor
,
hoverColor
,
_scrollbarTheme
.
thumbColor
?.
resolve
(
states
)
??
idleColor
,
_scrollbarTheme
.
thumbColor
?.
resolve
(
states
)
??
hoverColor
,
_hoverAnimationController
.
value
,
)!;
});
...
...
@@ -144,10 +156,11 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
final
Color
onSurface
=
_colorScheme
.
onSurface
;
final
Brightness
brightness
=
_colorScheme
.
brightness
;
return
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
hovered
)
&&
widget
.
showTrackOnHover
)
{
return
brightness
==
Brightness
.
light
?
onSurface
.
withOpacity
(
0.03
)
:
onSurface
.
withOpacity
(
0.05
);
if
(
states
.
contains
(
MaterialState
.
hovered
)
&&
_showTrackOnHover
)
{
return
_scrollbarTheme
.
trackColor
?.
resolve
(
states
)
??
(
brightness
==
Brightness
.
light
?
onSurface
.
withOpacity
(
0.03
)
:
onSurface
.
withOpacity
(
0.05
));
}
return
const
Color
(
0x00000000
);
});
...
...
@@ -157,10 +170,11 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
final
Color
onSurface
=
_colorScheme
.
onSurface
;
final
Brightness
brightness
=
_colorScheme
.
brightness
;
return
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
hovered
)
&&
widget
.
showTrackOnHover
)
{
return
brightness
==
Brightness
.
light
?
onSurface
.
withOpacity
(
0.1
)
:
onSurface
.
withOpacity
(
0.25
);
if
(
states
.
contains
(
MaterialState
.
hovered
)
&&
_showTrackOnHover
)
{
return
_scrollbarTheme
.
trackBorderColor
?.
resolve
(
states
)
??
(
brightness
==
Brightness
.
light
?
onSurface
.
withOpacity
(
0.1
)
:
onSurface
.
withOpacity
(
0.25
));
}
return
const
Color
(
0x00000000
);
});
...
...
@@ -168,10 +182,14 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
MaterialStateProperty
<
double
>
get
_thickness
{
return
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
hovered
)
&&
widget
.
showTrackOnHover
)
return
widget
.
hoverThickness
??
_kScrollbarThicknessWithTrack
;
if
(
states
.
contains
(
MaterialState
.
hovered
)
&&
_showTrackOnHover
)
return
widget
.
hoverThickness
??
_scrollbarTheme
.
thickness
?.
resolve
(
states
)
??
_kScrollbarThicknessWithTrack
;
// The default scrollbar thickness is smaller on mobile.
return
widget
.
thickness
??
(
_kScrollbarThickness
/
(
_useAndroidScrollbar
?
2
:
1
));
return
widget
.
thickness
??
_scrollbarTheme
.
thickness
?.
resolve
(
states
)
??
(
_kScrollbarThickness
/
(
_useAndroidScrollbar
?
2
:
1
));
});
}
...
...
@@ -190,6 +208,8 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
@override
void
didChangeDependencies
()
{
final
ThemeData
theme
=
Theme
.
of
(
context
);
_colorScheme
=
theme
.
colorScheme
;
_scrollbarTheme
=
theme
.
scrollbarTheme
;
switch
(
theme
.
platform
)
{
case
TargetPlatform
.
android
:
_useAndroidScrollbar
=
true
;
...
...
@@ -207,16 +227,16 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
@override
void
updateScrollbarPainter
()
{
_colorScheme
=
Theme
.
of
(
context
).
colorScheme
;
scrollbarPainter
..
color
=
_thumbColor
.
resolve
(
_states
)
..
trackColor
=
_trackColor
.
resolve
(
_states
)
..
trackBorderColor
=
_trackBorderColor
.
resolve
(
_states
)
..
textDirection
=
Directionality
.
of
(
context
)
..
thickness
=
_thickness
.
resolve
(
_states
)
..
radius
=
widget
.
radius
??
(
_useAndroidScrollbar
?
null
:
_kScrollbarRadius
)
..
crossAxisMargin
=
(
_useAndroidScrollbar
?
0.0
:
_kScrollbarMargin
)
..
minLength
=
_kScrollbarMinLength
..
radius
=
widget
.
radius
??
_scrollbarTheme
.
radius
??
(
_useAndroidScrollbar
?
null
:
_kScrollbarRadius
)
..
crossAxisMargin
=
_scrollbarTheme
.
crossAxisMargin
??
(
_useAndroidScrollbar
?
0.0
:
_kScrollbarMargin
)
..
mainAxisMargin
=
_scrollbarTheme
.
mainAxisMargin
??
0.0
..
minLength
=
_scrollbarTheme
.
minThumbLength
??
_kScrollbarMinLength
..
padding
=
MediaQuery
.
of
(
context
).
padding
;
}
...
...
packages/flutter/lib/src/material/scrollbar_theme.dart
0 → 100644
View file @
09008e6f
// Copyright 2014 The Flutter 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
'dart:ui'
show
lerpDouble
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/widgets.dart'
;
import
'material_state.dart'
;
import
'theme.dart'
;
/// Defines default property values for descendant [Scrollbar] widgets.
///
/// Descendant widgets obtain the current [ScrollbarThemeData] object with
/// `ScrollbarTheme.of(context)`. Instances of [ScrollbarThemeData] can be customized
/// with [ScrollbarThemeData.copyWith].
///
/// Typically the [ScrollbarThemeData] of a [ScrollbarTheme] is specified as part of the overall
/// [Theme] with [ThemeData.scrollbarTheme].
///
/// All [ScrollbarThemeData] properties are `null` by default. When null, the [Scrollbar]
/// computes its own default values, typically based on the overall theme's
/// [ThemeData.colorScheme].
///
/// See also:
///
/// * [ThemeData], which describes the overall theme information for the
/// application.
@immutable
class
ScrollbarThemeData
with
Diagnosticable
{
/// Creates a theme that can be used for [ThemeData.scrollbarTheme].
const
ScrollbarThemeData
({
this
.
thickness
,
this
.
showTrackOnHover
,
this
.
isAlwaysShown
,
this
.
radius
,
this
.
thumbColor
,
this
.
trackColor
,
this
.
trackBorderColor
,
this
.
crossAxisMargin
,
this
.
mainAxisMargin
,
this
.
minThumbLength
,
});
/// Overrides the default value of [Scrollbar.thickness] in all
/// descendant [Scrollbar] widgets.
///
/// Resolves in the following states:
/// * [MaterialState.hovered] on web and desktop platforms.
final
MaterialStateProperty
<
double
?>?
thickness
;
/// Overrides the default value of [Scrollbar.showTrackOnHover] in all
/// descendant [Scrollbar] widgets.
final
bool
?
showTrackOnHover
;
/// Overrides the default value of [Scrollbar.isAlwaysShown] in all
/// descendant [Scrollbar] widgets.
final
bool
?
isAlwaysShown
;
/// Overrides the default value of [Scrollbar.radius] in all
/// descendant widgets.
final
Radius
?
radius
;
/// Overrides the default [Color] of the [Scrollbar] thumb in all descendant
/// [Scrollbar] widgets.
///
/// Resolves in the following states:
/// * [MaterialState.dragged].
/// * [MaterialState.hovered] on web and desktop platforms.
final
MaterialStateProperty
<
Color
?>?
thumbColor
;
/// Overrides the default [Color] of the [Scrollbar] track when
/// [showTrackOnHover] is true in all descendant [Scrollbar] widgets.
///
/// Resolves in the following states:
/// * [MaterialState.hovered] on web and desktop platforms.
final
MaterialStateProperty
<
Color
?>?
trackColor
;
/// Overrides the default [Color] of the [Scrollbar] track border when
/// [showTrackOnHover] is true in all descendant [Scrollbar] widgets.
///
/// Resolves in the following states:
/// * [MaterialState.hovered] on web and desktop platforms.
final
MaterialStateProperty
<
Color
?>?
trackBorderColor
;
/// Overrides the default value of the [ScrollbarPainter.crossAxisMargin]
/// property in all descendant [Scrollbar] widgets.
///
/// See also:
///
/// * [ScrollbarPainter.crossAxisMargin], which sets the distance from the
/// scrollbar's side to the nearest edge in logical pixels.
final
double
?
crossAxisMargin
;
/// Overrides the default value of the [ScrollbarPainter.mainAxisMargin]
/// property in all descendant [Scrollbar] widgets.
///
/// See also:
///
/// * [ScrollbarPainter.mainAxisMargin], which sets the distance from the
/// scrollbar's start and end to the edge of the viewport in logical pixels.
final
double
?
mainAxisMargin
;
/// Overrides the default value of the [ScrollbarPainter.minLength]
/// property in all descendant [Scrollbar] widgets.
///
/// See also:
///
/// * [ScrollbarPainter.minLength], which sets the preferred smallest size
/// the scrollbar can shrink to when the total scrollable extent is large,
/// the current visible viewport is small, and the viewport is not
/// overscrolled.
final
double
?
minThumbLength
;
/// Creates a copy of this object with the given fields replaced with the
/// new values.
ScrollbarThemeData
copyWith
({
MaterialStateProperty
<
double
?>?
thickness
,
bool
?
showTrackOnHover
,
bool
?
isAlwaysShown
,
Radius
?
radius
,
MaterialStateProperty
<
Color
?>?
thumbColor
,
MaterialStateProperty
<
Color
?>?
trackColor
,
MaterialStateProperty
<
Color
?>?
trackBorderColor
,
double
?
crossAxisMargin
,
double
?
mainAxisMargin
,
double
?
minThumbLength
,
})
{
return
ScrollbarThemeData
(
thickness:
thickness
??
this
.
thickness
,
showTrackOnHover:
showTrackOnHover
??
this
.
showTrackOnHover
,
isAlwaysShown:
isAlwaysShown
??
this
.
isAlwaysShown
,
radius:
radius
??
this
.
radius
,
thumbColor:
thumbColor
??
this
.
thumbColor
,
trackColor:
trackColor
??
this
.
trackColor
,
trackBorderColor:
trackBorderColor
??
this
.
trackBorderColor
,
crossAxisMargin:
crossAxisMargin
??
this
.
crossAxisMargin
,
mainAxisMargin:
mainAxisMargin
??
this
.
mainAxisMargin
,
minThumbLength:
minThumbLength
??
this
.
minThumbLength
,
);
}
/// Linearly interpolate between two Scrollbar themes.
///
/// The argument `t` must not be null.
///
/// {@macro dart.ui.shadow.lerp}
static
ScrollbarThemeData
lerp
(
ScrollbarThemeData
?
a
,
ScrollbarThemeData
?
b
,
double
t
)
{
assert
(
t
!=
null
);
return
ScrollbarThemeData
(
thickness:
_lerpProperties
<
double
?>(
a
?.
thickness
,
b
?.
thickness
,
t
,
lerpDouble
),
showTrackOnHover:
t
<
0.5
?
a
?.
showTrackOnHover
:
b
?.
showTrackOnHover
,
isAlwaysShown:
t
<
0.5
?
a
?.
isAlwaysShown
:
b
?.
isAlwaysShown
,
radius:
Radius
.
lerp
(
a
?.
radius
,
b
?.
radius
,
t
),
thumbColor:
_lerpProperties
<
Color
?>(
a
?.
thumbColor
,
b
?.
thumbColor
,
t
,
Color
.
lerp
),
trackColor:
_lerpProperties
<
Color
?>(
a
?.
trackColor
,
b
?.
trackColor
,
t
,
Color
.
lerp
),
trackBorderColor:
_lerpProperties
<
Color
?>(
a
?.
trackBorderColor
,
b
?.
trackBorderColor
,
t
,
Color
.
lerp
),
crossAxisMargin:
lerpDouble
(
a
?.
crossAxisMargin
,
b
?.
crossAxisMargin
,
t
),
mainAxisMargin:
lerpDouble
(
a
?.
mainAxisMargin
,
b
?.
mainAxisMargin
,
t
),
minThumbLength:
lerpDouble
(
a
?.
minThumbLength
,
b
?.
minThumbLength
,
t
),
);
}
@override
int
get
hashCode
{
return
hashValues
(
thickness
,
showTrackOnHover
,
isAlwaysShown
,
radius
,
thumbColor
,
trackColor
,
trackBorderColor
,
crossAxisMargin
,
mainAxisMargin
,
minThumbLength
,
);
}
@override
bool
operator
==(
Object
other
)
{
if
(
identical
(
this
,
other
))
return
true
;
if
(
other
.
runtimeType
!=
runtimeType
)
return
false
;
return
other
is
ScrollbarThemeData
&&
other
.
thickness
==
thickness
&&
other
.
showTrackOnHover
==
showTrackOnHover
&&
other
.
isAlwaysShown
==
isAlwaysShown
&&
other
.
radius
==
radius
&&
other
.
thumbColor
==
thumbColor
&&
other
.
trackColor
==
trackColor
&&
other
.
trackBorderColor
==
trackBorderColor
&&
other
.
crossAxisMargin
==
crossAxisMargin
&&
other
.
mainAxisMargin
==
mainAxisMargin
&&
other
.
minThumbLength
==
minThumbLength
;
}
@override
void
debugFillProperties
(
DiagnosticPropertiesBuilder
properties
)
{
super
.
debugFillProperties
(
properties
);
properties
.
add
(
DiagnosticsProperty
<
MaterialStateProperty
<
double
?>>(
'thickness'
,
thickness
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
bool
>(
'showTrackOnHover'
,
showTrackOnHover
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
bool
>(
'isAlwaysShown'
,
isAlwaysShown
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
Radius
>(
'radius'
,
radius
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
MaterialStateProperty
<
Color
?>>(
'thumbColor'
,
thumbColor
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
MaterialStateProperty
<
Color
?>>(
'trackColor'
,
trackColor
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
MaterialStateProperty
<
Color
?>>(
'trackBorderColor'
,
trackBorderColor
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
double
>(
'crossAxisMargin'
,
crossAxisMargin
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
double
>(
'mainAxisMargin'
,
mainAxisMargin
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
double
>(
'minThumbLength'
,
minThumbLength
,
defaultValue:
null
));
}
static
MaterialStateProperty
<
T
>?
_lerpProperties
<
T
>(
MaterialStateProperty
<
T
>?
a
,
MaterialStateProperty
<
T
>?
b
,
double
t
,
T
Function
(
T
?,
T
?,
double
)
lerpFunction
,
)
{
// Avoid creating a _LerpProperties object for a common case.
if
(
a
==
null
&&
b
==
null
)
return
null
;
return
_LerpProperties
<
T
>(
a
,
b
,
t
,
lerpFunction
);
}
}
class
_LerpProperties
<
T
>
implements
MaterialStateProperty
<
T
>
{
const
_LerpProperties
(
this
.
a
,
this
.
b
,
this
.
t
,
this
.
lerpFunction
);
final
MaterialStateProperty
<
T
>?
a
;
final
MaterialStateProperty
<
T
>?
b
;
final
double
t
;
final
T
Function
(
T
?,
T
?,
double
)
lerpFunction
;
@override
T
resolve
(
Set
<
MaterialState
>
states
)
{
final
T
?
resolvedA
=
a
?.
resolve
(
states
);
final
T
?
resolvedB
=
b
?.
resolve
(
states
);
return
lerpFunction
(
resolvedA
,
resolvedB
,
t
);
}
}
/// Applies a scrollbar theme to descendant [Scrollbar] widgets.
///
/// Descendant widgets obtain the current theme's [ScrollbarThemeData] using
/// [ScrollbarTheme.of]. When a widget uses [ScrollbarTheme.of], it is
/// automatically rebuilt if the theme later changes.
///
/// A scrollbar theme can be specified as part of the overall Material theme
/// using [ThemeData.scrollbarTheme].
///
/// See also:
///
/// * [ScrollbarThemeData], which describes the configuration of a
/// scrollbar theme.
class
ScrollbarTheme
extends
InheritedWidget
{
/// Constructs a scrollbar theme that configures all descendant [Scrollbar]
/// widgets.
const
ScrollbarTheme
({
Key
?
key
,
required
this
.
data
,
required
Widget
child
,
})
:
super
(
key:
key
,
child:
child
);
/// The properties used for all descendant [Scrollbar] widgets.
final
ScrollbarThemeData
data
;
/// Returns the configuration [data] from the closest [ScrollbarTheme]
/// ancestor. If there is no ancestor, it returns [ThemeData.scrollbarTheme].
///
/// Typical usage is as follows:
///
/// ```dart
/// ScrollbarThemeData theme = ScrollbarTheme.of(context);
/// ```
static
ScrollbarThemeData
of
(
BuildContext
context
)
{
final
ScrollbarTheme
?
scrollbarTheme
=
context
.
dependOnInheritedWidgetOfExactType
<
ScrollbarTheme
>();
return
scrollbarTheme
?.
data
??
Theme
.
of
(
context
).
scrollbarTheme
;
}
@override
bool
updateShouldNotify
(
ScrollbarTheme
oldWidget
)
=>
data
!=
oldWidget
.
data
;
}
packages/flutter/lib/src/material/theme_data.dart
View file @
09008e6f
...
...
@@ -34,6 +34,7 @@ import 'outlined_button_theme.dart';
import
'page_transitions_theme.dart'
;
import
'popup_menu_theme.dart'
;
import
'radio_theme.dart'
;
import
'scrollbar_theme.dart'
;
import
'slider_theme.dart'
;
import
'snack_bar_theme.dart'
;
import
'switch_theme.dart'
;
...
...
@@ -278,6 +279,7 @@ class ThemeData with Diagnosticable {
bool
?
applyElevationOverlayColor
,
PageTransitionsTheme
?
pageTransitionsTheme
,
AppBarTheme
?
appBarTheme
,
ScrollbarThemeData
?
scrollbarTheme
,
BottomAppBarTheme
?
bottomAppBarTheme
,
ColorScheme
?
colorScheme
,
DialogTheme
?
dialogTheme
,
...
...
@@ -410,6 +412,7 @@ class ThemeData with Diagnosticable {
tabBarTheme
??=
const
TabBarTheme
();
tooltipTheme
??=
const
TooltipThemeData
();
appBarTheme
??=
const
AppBarTheme
();
scrollbarTheme
??=
const
ScrollbarThemeData
();
bottomAppBarTheme
??=
const
BottomAppBarTheme
();
cardTheme
??=
const
CardTheme
();
chipTheme
??=
ChipThemeData
.
fromDefaults
(
...
...
@@ -493,6 +496,7 @@ class ThemeData with Diagnosticable {
applyElevationOverlayColor:
applyElevationOverlayColor
,
pageTransitionsTheme:
pageTransitionsTheme
,
appBarTheme:
appBarTheme
,
scrollbarTheme:
scrollbarTheme
,
bottomAppBarTheme:
bottomAppBarTheme
,
colorScheme:
colorScheme
,
dialogTheme:
dialogTheme
,
...
...
@@ -583,6 +587,7 @@ class ThemeData with Diagnosticable {
required
this
.
applyElevationOverlayColor
,
required
this
.
pageTransitionsTheme
,
required
this
.
appBarTheme
,
required
this
.
scrollbarTheme
,
required
this
.
bottomAppBarTheme
,
required
this
.
colorScheme
,
required
this
.
dialogTheme
,
...
...
@@ -657,6 +662,7 @@ class ThemeData with Diagnosticable {
assert
(
materialTapTargetSize
!=
null
),
assert
(
pageTransitionsTheme
!=
null
),
assert
(
appBarTheme
!=
null
),
assert
(
scrollbarTheme
!=
null
),
assert
(
bottomAppBarTheme
!=
null
),
assert
(
colorScheme
!=
null
),
assert
(
dialogTheme
!=
null
),
...
...
@@ -1085,6 +1091,9 @@ class ThemeData with Diagnosticable {
/// textTheme of [AppBar]s.
final
AppBarTheme
appBarTheme
;
/// A theme for customizing the colors, thickness, and shape of [Scrollbar]s.
final
ScrollbarThemeData
scrollbarTheme
;
/// A theme for customizing the shape, elevation, and color of a [BottomAppBar].
final
BottomAppBarTheme
bottomAppBarTheme
;
...
...
@@ -1270,6 +1279,7 @@ class ThemeData with Diagnosticable {
bool
?
applyElevationOverlayColor
,
PageTransitionsTheme
?
pageTransitionsTheme
,
AppBarTheme
?
appBarTheme
,
ScrollbarThemeData
?
scrollbarTheme
,
BottomAppBarTheme
?
bottomAppBarTheme
,
ColorScheme
?
colorScheme
,
DialogTheme
?
dialogTheme
,
...
...
@@ -1353,6 +1363,7 @@ class ThemeData with Diagnosticable {
applyElevationOverlayColor:
applyElevationOverlayColor
??
this
.
applyElevationOverlayColor
,
pageTransitionsTheme:
pageTransitionsTheme
??
this
.
pageTransitionsTheme
,
appBarTheme:
appBarTheme
??
this
.
appBarTheme
,
scrollbarTheme:
scrollbarTheme
??
this
.
scrollbarTheme
,
bottomAppBarTheme:
bottomAppBarTheme
??
this
.
bottomAppBarTheme
,
colorScheme:
(
colorScheme
??
this
.
colorScheme
).
copyWith
(
brightness:
brightness
),
dialogTheme:
dialogTheme
??
this
.
dialogTheme
,
...
...
@@ -1510,6 +1521,7 @@ class ThemeData with Diagnosticable {
applyElevationOverlayColor:
t
<
0.5
?
a
.
applyElevationOverlayColor
:
b
.
applyElevationOverlayColor
,
pageTransitionsTheme:
t
<
0.5
?
a
.
pageTransitionsTheme
:
b
.
pageTransitionsTheme
,
appBarTheme:
AppBarTheme
.
lerp
(
a
.
appBarTheme
,
b
.
appBarTheme
,
t
),
scrollbarTheme:
ScrollbarThemeData
.
lerp
(
a
.
scrollbarTheme
,
b
.
scrollbarTheme
,
t
),
bottomAppBarTheme:
BottomAppBarTheme
.
lerp
(
a
.
bottomAppBarTheme
,
b
.
bottomAppBarTheme
,
t
),
colorScheme:
ColorScheme
.
lerp
(
a
.
colorScheme
,
b
.
colorScheme
,
t
),
dialogTheme:
DialogTheme
.
lerp
(
a
.
dialogTheme
,
b
.
dialogTheme
,
t
),
...
...
@@ -1595,6 +1607,7 @@ class ThemeData with Diagnosticable {
&&
other
.
applyElevationOverlayColor
==
applyElevationOverlayColor
&&
other
.
pageTransitionsTheme
==
pageTransitionsTheme
&&
other
.
appBarTheme
==
appBarTheme
&&
other
.
scrollbarTheme
==
scrollbarTheme
&&
other
.
bottomAppBarTheme
==
bottomAppBarTheme
&&
other
.
colorScheme
==
colorScheme
&&
other
.
dialogTheme
==
dialogTheme
...
...
@@ -1679,6 +1692,7 @@ class ThemeData with Diagnosticable {
applyElevationOverlayColor
,
pageTransitionsTheme
,
appBarTheme
,
scrollbarTheme
,
bottomAppBarTheme
,
colorScheme
,
dialogTheme
,
...
...
@@ -1760,6 +1774,7 @@ class ThemeData with Diagnosticable {
properties
.
add
(
DiagnosticsProperty
<
bool
>(
'applyElevationOverlayColor'
,
applyElevationOverlayColor
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
PageTransitionsTheme
>(
'pageTransitionsTheme'
,
pageTransitionsTheme
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
AppBarTheme
>(
'appBarTheme'
,
appBarTheme
,
defaultValue:
defaultData
.
appBarTheme
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
ScrollbarThemeData
>(
'ScrollbarTheme'
,
scrollbarTheme
,
defaultValue:
defaultData
.
scrollbarTheme
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
BottomAppBarTheme
>(
'bottomAppBarTheme'
,
bottomAppBarTheme
,
defaultValue:
defaultData
.
bottomAppBarTheme
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
ColorScheme
>(
'colorScheme'
,
colorScheme
,
defaultValue:
defaultData
.
colorScheme
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
DialogTheme
>(
'dialogTheme'
,
dialogTheme
,
defaultValue:
defaultData
.
dialogTheme
,
level:
DiagnosticLevel
.
debug
));
...
...
packages/flutter/lib/src/widgets/scrollbar.dart
View file @
09008e6f
...
...
@@ -600,15 +600,14 @@ class RawScrollbar extends StatefulWidget {
Key
?
key
,
required
this
.
child
,
this
.
controller
,
this
.
isAlwaysShown
=
false
,
this
.
isAlwaysShown
,
this
.
radius
,
this
.
thickness
,
this
.
thumbColor
,
this
.
fadeDuration
=
_kScrollbarFadeDuration
,
this
.
timeToFade
=
_kScrollbarTimeToFade
,
this
.
pressDuration
=
Duration
.
zero
,
})
:
assert
(
isAlwaysShown
!=
null
),
assert
(
child
!=
null
),
})
:
assert
(
child
!=
null
),
assert
(
fadeDuration
!=
null
),
assert
(
timeToFade
!=
null
),
assert
(
pressDuration
!=
null
),
...
...
@@ -683,7 +682,7 @@ class RawScrollbar extends StatefulWidget {
/// [controller] property has not been set, the [PrimaryScrollController] will
/// be used.
///
/// Defaults to false.
/// Defaults to false
when null
.
///
/// {@tool snippet}
///
...
...
@@ -728,7 +727,7 @@ class RawScrollbar extends StatefulWidget {
/// }
/// ```
/// {@end-tool}
final
bool
isAlwaysShown
;
final
bool
?
isAlwaysShown
;
/// The [Radius] of the scrollbar thumb's rounded rectangle corners.
///
...
...
@@ -790,6 +789,14 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
@protected
late
final
ScrollbarPainter
scrollbarPainter
;
/// Overridable getter to indicate that the scrollbar should be visible, even
/// when a scroll is not underway.
///
/// Subclasses can override this getter to make its value depend on an inherited
/// theme.
@protected
bool
get
showScrollbar
=>
widget
.
isAlwaysShown
??
false
;
@override
void
initState
()
{
super
.
initState
();
...
...
@@ -820,7 +827,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
// A scroll event is required in order to paint the thumb.
void
_maybeTriggerScrollbar
()
{
WidgetsBinding
.
instance
!.
addPostFrameCallback
((
Duration
duration
)
{
if
(
widget
.
isAlwaysShown
)
{
if
(
showScrollbar
)
{
_fadeoutTimer
?.
cancel
();
// Wait one frame and cause an empty scroll event. This allows the
// thumb to show immediately when isAlwaysShown is true. A scroll
...
...
@@ -881,7 +888,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
}
void
_maybeStartFadeoutTimer
()
{
if
(!
widget
.
isAlwaysShown
)
{
if
(!
showScrollbar
)
{
_fadeoutTimer
?.
cancel
();
_fadeoutTimer
=
Timer
(
widget
.
timeToFade
,
()
{
_fadeoutAnimationController
.
reverse
();
...
...
packages/flutter/test/material/scrollbar_theme_test.dart
0 → 100644
View file @
09008e6f
// Copyright 2014 The Flutter 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
'dart:ui'
as
ui
;
import
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'../rendering/mock_canvas.dart'
;
void
main
(
)
{
test
(
'ScrollbarThemeData copyWith, ==, hashCode basics'
,
()
{
expect
(
const
ScrollbarThemeData
(),
const
ScrollbarThemeData
().
copyWith
());
expect
(
const
ScrollbarThemeData
().
hashCode
,
const
ScrollbarThemeData
().
copyWith
().
hashCode
);
});
testWidgets
(
'Passing no ScrollbarTheme returns defaults'
,
(
WidgetTester
tester
)
async
{
final
ScrollController
scrollController
=
ScrollController
();
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Scrollbar
(
isAlwaysShown:
true
,
showTrackOnHover:
true
,
controller:
scrollController
,
child:
SingleChildScrollView
(
controller:
scrollController
,
child:
const
SizedBox
(
width:
4000.0
,
height:
4000.0
)
),
),
),
);
await
tester
.
pumpAndSettle
();
// Idle scrollbar behavior
expect
(
find
.
byType
(
Scrollbar
),
paints
..
rrect
(
rrect:
RRect
.
fromRectAndRadius
(
const
Rect
.
fromLTRB
(
790.0
,
0.0
,
798.0
,
90.0
),
const
Radius
.
circular
(
8.0
),
),
color:
const
Color
(
0x1a000000
),
),
);
// Drag scrollbar behavior
const
double
scrollAmount
=
10.0
;
final
TestGesture
dragScrollbarGesture
=
await
tester
.
startGesture
(
const
Offset
(
797.0
,
45.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
Scrollbar
),
paints
..
rrect
(
rrect:
RRect
.
fromRectAndRadius
(
const
Rect
.
fromLTRB
(
790.0
,
0.0
,
798.0
,
90.0
),
const
Radius
.
circular
(
8.0
),
),
// Drag color
color:
const
Color
(
0x99000000
),
),
);
await
dragScrollbarGesture
.
moveBy
(
const
Offset
(
0.0
,
scrollAmount
));
await
tester
.
pumpAndSettle
();
await
dragScrollbarGesture
.
up
();
await
tester
.
pumpAndSettle
();
// Hover scrollbar behavior
final
TestGesture
gesture
=
await
tester
.
createGesture
(
kind:
ui
.
PointerDeviceKind
.
mouse
);
await
gesture
.
addPointer
();
addTearDown
(
gesture
.
removePointer
);
await
gesture
.
moveTo
(
const
Offset
(
794.0
,
5.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
Scrollbar
),
paints
..
rect
(
rect:
const
Rect
.
fromLTRB
(
784.0
,
0.0
,
800.0
,
600.0
),
color:
const
Color
(
0x08000000
),
)
..
line
(
p1:
const
Offset
(
784.0
,
0.0
),
p2:
const
Offset
(
784.0
,
600.0
),
strokeWidth:
1.0
,
color:
const
Color
(
0x1a000000
),
)
..
rrect
(
rrect:
RRect
.
fromRectAndRadius
(
// Scrollbar thumb is larger
const
Rect
.
fromLTRB
(
786.0
,
10.0
,
798.0
,
100.0
),
const
Radius
.
circular
(
8.0
),
),
// Hover color
color:
const
Color
(
0x80000000
),
),
);
},
variant:
const
TargetPlatformVariant
(<
TargetPlatform
>{
TargetPlatform
.
linux
,
TargetPlatform
.
macOS
,
TargetPlatform
.
windows
,
TargetPlatform
.
fuchsia
,
}),
);
testWidgets
(
'Scrollbar uses values from ScrollbarTheme'
,
(
WidgetTester
tester
)
async
{
final
ScrollbarThemeData
scrollbarTheme
=
_scrollbarTheme
();
final
ScrollController
scrollController
=
ScrollController
();
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
(
scrollbarTheme:
scrollbarTheme
),
home:
Scrollbar
(
isAlwaysShown:
true
,
controller:
scrollController
,
child:
SingleChildScrollView
(
controller:
scrollController
,
child:
const
SizedBox
(
width:
4000.0
,
height:
4000.0
)
),
),
));
await
tester
.
pumpAndSettle
();
// Idle scrollbar behavior
expect
(
find
.
byType
(
Scrollbar
),
paints
..
rrect
(
rrect:
RRect
.
fromRectAndRadius
(
const
Rect
.
fromLTRB
(
785.0
,
10.0
,
795.0
,
97.0
),
const
Radius
.
circular
(
6.0
),
),
color:
const
Color
(
0xff4caf50
),
),
);
// Drag scrollbar behavior
const
double
scrollAmount
=
10.0
;
final
TestGesture
dragScrollbarGesture
=
await
tester
.
startGesture
(
const
Offset
(
797.0
,
45.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
Scrollbar
),
paints
..
rrect
(
rrect:
RRect
.
fromRectAndRadius
(
const
Rect
.
fromLTRB
(
785.0
,
10.0
,
795.0
,
97.0
),
const
Radius
.
circular
(
6.0
),
),
// Drag color
color:
const
Color
(
0xfff44336
),
),
);
await
dragScrollbarGesture
.
moveBy
(
const
Offset
(
0.0
,
scrollAmount
));
await
tester
.
pumpAndSettle
();
await
dragScrollbarGesture
.
up
();
await
tester
.
pumpAndSettle
();
// Hover scrollbar behavior
final
TestGesture
gesture
=
await
tester
.
createGesture
(
kind:
ui
.
PointerDeviceKind
.
mouse
);
await
gesture
.
addPointer
();
addTearDown
(
gesture
.
removePointer
);
await
gesture
.
moveTo
(
const
Offset
(
794.0
,
5.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
Scrollbar
),
paints
..
rect
(
rect:
const
Rect
.
fromLTRB
(
770.0
,
0.0
,
800.0
,
580.0
),
color:
const
Color
(
0xff000000
),
)
..
line
(
p1:
const
Offset
(
770.0
,
0.0
),
p2:
const
Offset
(
770.0
,
580.0
),
strokeWidth:
1.0
,
color:
const
Color
(
0xffffeb3b
),
)
..
rrect
(
rrect:
RRect
.
fromRectAndRadius
(
// Scrollbar thumb is larger
const
Rect
.
fromLTRB
(
775.0
,
20.0
,
795.0
,
107.0
),
const
Radius
.
circular
(
6.0
),
),
// Hover color
color:
const
Color
(
0xff2196f3
),
),
);
},
variant:
const
TargetPlatformVariant
(<
TargetPlatform
>{
TargetPlatform
.
linux
,
TargetPlatform
.
macOS
,
TargetPlatform
.
windows
,
TargetPlatform
.
fuchsia
,
}),
);
testWidgets
(
'Scrollbar widget properties take priority over theme'
,
(
WidgetTester
tester
)
async
{
const
double
thickness
=
4.0
;
const
double
hoverThickness
=
4.0
;
const
bool
showTrackOnHover
=
true
;
const
Radius
radius
=
Radius
.
circular
(
3.0
);
final
ScrollController
scrollController
=
ScrollController
();
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
.
from
(
colorScheme:
const
ColorScheme
.
light
()),
home:
Scrollbar
(
thickness:
thickness
,
hoverThickness:
hoverThickness
,
isAlwaysShown:
true
,
showTrackOnHover:
showTrackOnHover
,
radius:
radius
,
controller:
scrollController
,
child:
SingleChildScrollView
(
controller:
scrollController
,
child:
const
SizedBox
(
width:
4000.0
,
height:
4000.0
)
),
),
),
);
await
tester
.
pumpAndSettle
();
// Idle scrollbar behavior
expect
(
find
.
byType
(
Scrollbar
),
paints
..
rrect
(
rrect:
RRect
.
fromRectAndRadius
(
const
Rect
.
fromLTRB
(
794.0
,
0.0
,
798.0
,
90.0
),
const
Radius
.
circular
(
3.0
),
),
color:
const
Color
(
0x1a000000
),
),
);
// Drag scrollbar behavior
const
double
scrollAmount
=
10.0
;
final
TestGesture
dragScrollbarGesture
=
await
tester
.
startGesture
(
const
Offset
(
797.0
,
45.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
Scrollbar
),
paints
..
rrect
(
rrect:
RRect
.
fromRectAndRadius
(
const
Rect
.
fromLTRB
(
794.0
,
0.0
,
798.0
,
90.0
),
const
Radius
.
circular
(
3.0
),
),
// Drag color
color:
const
Color
(
0x99000000
),
),
);
await
dragScrollbarGesture
.
moveBy
(
const
Offset
(
0.0
,
scrollAmount
));
await
tester
.
pumpAndSettle
();
await
dragScrollbarGesture
.
up
();
await
tester
.
pumpAndSettle
();
// Hover scrollbar behavior
final
TestGesture
gesture
=
await
tester
.
createGesture
(
kind:
ui
.
PointerDeviceKind
.
mouse
);
await
gesture
.
addPointer
();
addTearDown
(
gesture
.
removePointer
);
await
gesture
.
moveTo
(
const
Offset
(
794.0
,
5.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
Scrollbar
),
paints
..
rect
(
rect:
const
Rect
.
fromLTRB
(
792.0
,
0.0
,
800.0
,
600.0
),
color:
const
Color
(
0x08000000
),
)
..
line
(
p1:
const
Offset
(
792.0
,
0.0
),
p2:
const
Offset
(
792.0
,
600.0
),
strokeWidth:
1.0
,
color:
const
Color
(
0x1a000000
),
)
..
rrect
(
rrect:
RRect
.
fromRectAndRadius
(
// Scrollbar thumb is larger
const
Rect
.
fromLTRB
(
794.0
,
10.0
,
798.0
,
100.0
),
const
Radius
.
circular
(
3.0
),
),
// Hover color
color:
const
Color
(
0x80000000
),
),
);
},
variant:
const
TargetPlatformVariant
(<
TargetPlatform
>{
TargetPlatform
.
linux
,
TargetPlatform
.
macOS
,
TargetPlatform
.
windows
,
TargetPlatform
.
fuchsia
,
}),
);
testWidgets
(
'ThemeData colorScheme is used when no ScrollbarTheme is set'
,
(
WidgetTester
tester
)
async
{
Widget
buildFrame
(
ThemeData
appTheme
)
{
final
ScrollController
scrollController
=
ScrollController
();
return
MaterialApp
(
theme:
appTheme
,
home:
Scrollbar
(
isAlwaysShown:
true
,
showTrackOnHover:
true
,
controller:
scrollController
,
child:
SingleChildScrollView
(
controller:
scrollController
,
child:
const
SizedBox
(
width:
4000.0
,
height:
4000.0
)
),
)
);
}
// Scrollbar defaults for light themes:
// - coloring based on ColorScheme.onSurface
await
tester
.
pumpWidget
(
buildFrame
(
ThemeData
.
from
(
colorScheme:
const
ColorScheme
.
light
())));
await
tester
.
pumpAndSettle
();
// Idle scrollbar behavior
expect
(
find
.
byType
(
Scrollbar
),
paints
..
rrect
(
rrect:
RRect
.
fromRectAndRadius
(
const
Rect
.
fromLTRB
(
790.0
,
0.0
,
798.0
,
90.0
),
const
Radius
.
circular
(
8.0
),
),
color:
const
Color
(
0x1a000000
),
),
);
// Drag scrollbar behavior
const
double
scrollAmount
=
10.0
;
TestGesture
dragScrollbarGesture
=
await
tester
.
startGesture
(
const
Offset
(
797.0
,
45.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
Scrollbar
),
paints
..
rrect
(
rrect:
RRect
.
fromRectAndRadius
(
const
Rect
.
fromLTRB
(
790.0
,
0.0
,
798.0
,
90.0
),
const
Radius
.
circular
(
8.0
),
),
// Drag color
color:
const
Color
(
0x99000000
),
),
);
await
dragScrollbarGesture
.
moveBy
(
const
Offset
(
0.0
,
scrollAmount
));
await
tester
.
pumpAndSettle
();
await
dragScrollbarGesture
.
up
();
await
tester
.
pumpAndSettle
();
// Hover scrollbar behavior
final
TestGesture
hoverGesture
=
await
tester
.
createGesture
(
kind:
ui
.
PointerDeviceKind
.
mouse
);
await
hoverGesture
.
addPointer
();
addTearDown
(
hoverGesture
.
removePointer
);
await
hoverGesture
.
moveTo
(
const
Offset
(
794.0
,
5.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
Scrollbar
),
paints
..
rect
(
rect:
const
Rect
.
fromLTRB
(
784.0
,
0.0
,
800.0
,
600.0
),
color:
const
Color
(
0x08000000
),
)
..
line
(
p1:
const
Offset
(
784.0
,
0.0
),
p2:
const
Offset
(
784.0
,
600.0
),
strokeWidth:
1.0
,
color:
const
Color
(
0x1a000000
),
)
..
rrect
(
rrect:
RRect
.
fromRectAndRadius
(
// Scrollbar thumb is larger
const
Rect
.
fromLTRB
(
786.0
,
10.0
,
798.0
,
100.0
),
const
Radius
.
circular
(
8.0
),
),
// Hover color
color:
const
Color
(
0x80000000
),
),
);
await
hoverGesture
.
moveTo
(
const
Offset
(
0.0
,
0.0
));
// Scrollbar defaults for dark themes:
// - coloring slightly different based on ColorScheme.onSurface
await
tester
.
pumpWidget
(
buildFrame
(
ThemeData
.
from
(
colorScheme:
const
ColorScheme
.
dark
())));
await
tester
.
pumpAndSettle
();
// Theme change animation
// Idle scrollbar behavior
expect
(
find
.
byType
(
Scrollbar
),
paints
..
rrect
(
rrect:
RRect
.
fromRectAndRadius
(
const
Rect
.
fromLTRB
(
790.0
,
10.0
,
798.0
,
100.0
),
const
Radius
.
circular
(
8.0
),
),
color:
const
Color
(
0x4dffffff
),
),
);
// Drag scrollbar behavior
dragScrollbarGesture
=
await
tester
.
startGesture
(
const
Offset
(
797.0
,
45.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
Scrollbar
),
paints
..
rrect
(
rrect:
RRect
.
fromRectAndRadius
(
const
Rect
.
fromLTRB
(
790.0
,
10.0
,
798.0
,
100.0
),
const
Radius
.
circular
(
8.0
),
),
// Drag color
color:
const
Color
(
0xbfffffff
),
),
);
await
dragScrollbarGesture
.
moveBy
(
const
Offset
(
0.0
,
scrollAmount
));
await
tester
.
pumpAndSettle
();
await
dragScrollbarGesture
.
up
();
await
tester
.
pumpAndSettle
();
// Hover scrollbar behavior
await
hoverGesture
.
moveTo
(
const
Offset
(
794.0
,
5.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
Scrollbar
),
paints
..
rect
(
rect:
const
Rect
.
fromLTRB
(
784.0
,
0.0
,
800.0
,
600.0
),
color:
const
Color
(
0x0dffffff
),
)
..
line
(
p1:
const
Offset
(
784.0
,
0.0
),
p2:
const
Offset
(
784.0
,
600.0
),
strokeWidth:
1.0
,
color:
const
Color
(
0x40ffffff
),
)
..
rrect
(
rrect:
RRect
.
fromRectAndRadius
(
// Scrollbar thumb is larger
const
Rect
.
fromLTRB
(
786.0
,
20.0
,
798.0
,
110.0
),
const
Radius
.
circular
(
8.0
),
),
// Hover color
color:
const
Color
(
0xa6ffffff
),
),
);
},
variant:
const
TargetPlatformVariant
(<
TargetPlatform
>{
TargetPlatform
.
linux
,
TargetPlatform
.
macOS
,
TargetPlatform
.
windows
,
TargetPlatform
.
fuchsia
,
}),
);
testWidgets
(
'Default ScrollbarTheme debugFillProperties'
,
(
WidgetTester
tester
)
async
{
final
DiagnosticPropertiesBuilder
builder
=
DiagnosticPropertiesBuilder
();
const
ScrollbarThemeData
().
debugFillProperties
(
builder
);
final
List
<
String
>
description
=
builder
.
properties
.
where
((
DiagnosticsNode
node
)
=>
!
node
.
isFiltered
(
DiagnosticLevel
.
info
))
.
map
((
DiagnosticsNode
node
)
=>
node
.
toString
())
.
toList
();
expect
(
description
,
<
String
>[]);
});
testWidgets
(
'ScrollbarTheme implements debugFillProperties'
,
(
WidgetTester
tester
)
async
{
final
DiagnosticPropertiesBuilder
builder
=
DiagnosticPropertiesBuilder
();
ScrollbarThemeData
(
thickness:
MaterialStateProperty
.
resolveWith
(
_getThickness
),
showTrackOnHover:
true
,
isAlwaysShown:
true
,
radius:
const
Radius
.
circular
(
3.0
),
thumbColor:
MaterialStateProperty
.
resolveWith
(
_getThumbColor
),
trackColor:
MaterialStateProperty
.
resolveWith
(
_getTrackColor
),
trackBorderColor:
MaterialStateProperty
.
resolveWith
(
_getTrackBorderColor
),
crossAxisMargin:
3.0
,
mainAxisMargin:
6.0
,
minThumbLength:
120.0
,
).
debugFillProperties
(
builder
);
final
List
<
String
>
description
=
builder
.
properties
.
where
((
DiagnosticsNode
node
)
=>
!
node
.
isFiltered
(
DiagnosticLevel
.
info
))
.
map
((
DiagnosticsNode
node
)
=>
node
.
toString
())
.
toList
();
expect
(
description
,
<
String
>[
'thickness: Instance of
\'
_MaterialStatePropertyWith<double?>
\'
'
,
'showTrackOnHover: true'
,
'isAlwaysShown: true'
,
'radius: Radius.circular(3.0)'
,
'thumbColor: Instance of
\'
_MaterialStatePropertyWith<Color?>
\'
'
,
'trackColor: Instance of
\'
_MaterialStatePropertyWith<Color?>
\'
'
,
'trackBorderColor: Instance of
\'
_MaterialStatePropertyWith<Color?>
\'
'
,
'crossAxisMargin: 3.0'
,
'mainAxisMargin: 6.0'
,
'minThumbLength: 120.0'
]);
// On the web, Dart doubles and ints are backed by the same kind of object because
// JavaScript does not support integers. So, the Dart double "4.0" is identical
// to "4", which results in the web evaluating to the value "4" regardless of which
// one is used. This results in a difference for doubles in debugFillProperties between
// the web and the rest of Flutter's target platforms.
},
skip:
kIsWeb
);
}
ScrollbarThemeData
_scrollbarTheme
(
{
MaterialStateProperty
<
double
?>?
thickness
,
bool
showTrackOnHover
=
true
,
bool
isAlwaysShown
=
true
,
Radius
radius
=
const
Radius
.
circular
(
6.0
),
MaterialStateProperty
<
Color
?>?
thumbColor
,
MaterialStateProperty
<
Color
?>?
trackColor
,
MaterialStateProperty
<
Color
?>?
trackBorderColor
,
double
crossAxisMargin
=
5.0
,
double
mainAxisMargin
=
10.0
,
double
minThumbLength
=
50.0
,
})
{
return
ScrollbarThemeData
(
thickness:
thickness
??
MaterialStateProperty
.
resolveWith
(
_getThickness
),
showTrackOnHover:
showTrackOnHover
,
isAlwaysShown:
isAlwaysShown
,
radius:
radius
,
thumbColor:
thumbColor
??
MaterialStateProperty
.
resolveWith
(
_getThumbColor
),
trackColor:
trackColor
??
MaterialStateProperty
.
resolveWith
(
_getTrackColor
),
trackBorderColor:
trackBorderColor
??
MaterialStateProperty
.
resolveWith
(
_getTrackBorderColor
),
crossAxisMargin:
crossAxisMargin
,
mainAxisMargin:
mainAxisMargin
,
minThumbLength:
minThumbLength
,
);
}
double
?
_getThickness
(
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
hovered
))
return
20.0
;
return
10.0
;
}
Color
?
_getThumbColor
(
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
dragged
))
return
Colors
.
red
;
if
(
states
.
contains
(
MaterialState
.
hovered
))
return
Colors
.
blue
;
return
Colors
.
green
;
}
Color
?
_getTrackColor
(
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
hovered
))
return
Colors
.
black
;
return
null
;
}
Color
?
_getTrackBorderColor
(
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
hovered
))
return
Colors
.
yellow
;
return
null
;
}
packages/flutter/test/material/snack_bar_test.dart
View file @
09008e6f
...
...
@@ -742,6 +742,7 @@ void main() {
applyElevationOverlayColor:
false
,
pageTransitionsTheme:
pageTransitionTheme
,
appBarTheme:
const
AppBarTheme
(
color:
Colors
.
black
),
scrollbarTheme:
const
ScrollbarThemeData
(
radius:
Radius
.
circular
(
10.0
)),
bottomAppBarTheme:
const
BottomAppBarTheme
(
color:
Colors
.
black
),
colorScheme:
const
ColorScheme
.
light
(),
dialogTheme:
const
DialogTheme
(
backgroundColor:
Colors
.
black
),
...
...
packages/flutter/test/material/theme_data_test.dart
View file @
09008e6f
...
...
@@ -292,6 +292,7 @@ void main() {
applyElevationOverlayColor:
false
,
pageTransitionsTheme:
pageTransitionTheme
,
appBarTheme:
const
AppBarTheme
(
color:
Colors
.
black
),
scrollbarTheme:
const
ScrollbarThemeData
(
radius:
Radius
.
circular
(
10.0
)),
bottomAppBarTheme:
const
BottomAppBarTheme
(
color:
Colors
.
black
),
colorScheme:
const
ColorScheme
.
light
(),
dialogTheme:
const
DialogTheme
(
backgroundColor:
Colors
.
black
),
...
...
@@ -384,6 +385,7 @@ void main() {
applyElevationOverlayColor:
true
,
pageTransitionsTheme:
const
PageTransitionsTheme
(),
appBarTheme:
const
AppBarTheme
(
color:
Colors
.
white
),
scrollbarTheme:
const
ScrollbarThemeData
(
radius:
Radius
.
circular
(
10.0
)),
bottomAppBarTheme:
const
BottomAppBarTheme
(
color:
Colors
.
white
),
colorScheme:
const
ColorScheme
.
light
(),
dialogTheme:
const
DialogTheme
(
backgroundColor:
Colors
.
white
),
...
...
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