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
Show 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';
...
@@ -115,6 +115,7 @@ export 'src/material/refresh_indicator.dart';
export
'src/material/reorderable_list.dart'
;
export
'src/material/reorderable_list.dart'
;
export
'src/material/scaffold.dart'
;
export
'src/material/scaffold.dart'
;
export
'src/material/scrollbar.dart'
;
export
'src/material/scrollbar.dart'
;
export
'src/material/scrollbar_theme.dart'
;
export
'src/material/search.dart'
;
export
'src/material/search.dart'
;
export
'src/material/selectable_text.dart'
;
export
'src/material/selectable_text.dart'
;
export
'src/material/shadows.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';
...
@@ -8,6 +8,7 @@ import 'package:flutter/widgets.dart';
import
'color_scheme.dart'
;
import
'color_scheme.dart'
;
import
'material_state.dart'
;
import
'material_state.dart'
;
import
'scrollbar_theme.dart'
;
import
'theme.dart'
;
import
'theme.dart'
;
const
double
_kScrollbarThickness
=
8.0
;
const
double
_kScrollbarThickness
=
8.0
;
...
@@ -37,6 +38,7 @@ const Duration _kScrollbarTimeToFade = Duration(milliseconds: 600);
...
@@ -37,6 +38,7 @@ const Duration _kScrollbarTimeToFade = Duration(milliseconds: 600);
///
///
/// * [RawScrollbar], a basic scrollbar that fades in and out, extended
/// * [RawScrollbar], a basic scrollbar that fades in and out, extended
/// by this class to add more animations and behaviors.
/// by this class to add more animations and behaviors.
/// * [ScrollbarTheme], which configures the Scrollbar's appearance.
/// * [CupertinoScrollbar], an iOS style scrollbar.
/// * [CupertinoScrollbar], an iOS style scrollbar.
/// * [ListView], which displays a linear, scrollable list of children.
/// * [ListView], which displays a linear, scrollable list of children.
/// * [GridView], which displays a 2 dimensional, scrollable array of children.
/// * [GridView], which displays a 2 dimensional, scrollable array of children.
...
@@ -59,8 +61,8 @@ class Scrollbar extends RawScrollbar {
...
@@ -59,8 +61,8 @@ class Scrollbar extends RawScrollbar {
Key
?
key
,
Key
?
key
,
required
Widget
child
,
required
Widget
child
,
ScrollController
?
controller
,
ScrollController
?
controller
,
bool
isAlwaysShown
=
false
,
bool
?
isAlwaysShown
,
this
.
showTrackOnHover
=
false
,
this
.
showTrackOnHover
,
this
.
hoverThickness
,
this
.
hoverThickness
,
double
?
thickness
,
double
?
thickness
,
Radius
?
radius
,
Radius
?
radius
,
...
@@ -78,13 +80,17 @@ class Scrollbar extends RawScrollbar {
...
@@ -78,13 +80,17 @@ class Scrollbar extends RawScrollbar {
/// Controls if the track will show on hover and remain, including during drag.
/// Controls if the track will show on hover and remain, including during drag.
///
///
/// Defaults to false, cannot be null.
/// If this property is null, then [ScrollbarThemeData.showTrackOnHover] of
final
bool
showTrackOnHover
;
/// [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
/// The thickness of the scrollbar when a hover state is active and
/// [showTrackOnHover] is true.
/// [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
;
final
double
?
hoverThickness
;
@override
@override
...
@@ -96,9 +102,15 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
...
@@ -96,9 +102,15 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
bool
_dragIsActive
=
false
;
bool
_dragIsActive
=
false
;
bool
_hoverIsActive
=
false
;
bool
_hoverIsActive
=
false
;
late
ColorScheme
_colorScheme
;
late
ColorScheme
_colorScheme
;
late
ScrollbarThemeData
_scrollbarTheme
;
// On Android, scrollbars should match native appearance.
// On Android, scrollbars should match native appearance.
late
bool
_useAndroidScrollbar
;
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
>{
Set
<
MaterialState
>
get
_states
=>
<
MaterialState
>{
if
(
_dragIsActive
)
MaterialState
.
dragged
,
if
(
_dragIsActive
)
MaterialState
.
dragged
,
if
(
_hoverIsActive
)
MaterialState
.
hovered
,
if
(
_hoverIsActive
)
MaterialState
.
hovered
,
...
@@ -125,16 +137,16 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
...
@@ -125,16 +137,16 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
return
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
return
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
dragged
))
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
// If the track is visible, the thumb color hover animation is ignored and
// changes immediately.
// changes immediately.
if
(
states
.
contains
(
MaterialState
.
hovered
)
&&
widget
.
showTrackOnHover
)
if
(
states
.
contains
(
MaterialState
.
hovered
)
&&
_
showTrackOnHover
)
return
hoverColor
;
return
_scrollbarTheme
.
thumbColor
?.
resolve
(
states
)
??
hoverColor
;
return
Color
.
lerp
(
return
Color
.
lerp
(
idleColor
,
_scrollbarTheme
.
thumbColor
?.
resolve
(
states
)
??
idleColor
,
hoverColor
,
_scrollbarTheme
.
thumbColor
?.
resolve
(
states
)
??
hoverColor
,
_hoverAnimationController
.
value
,
_hoverAnimationController
.
value
,
)!;
)!;
});
});
...
@@ -144,10 +156,11 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
...
@@ -144,10 +156,11 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
final
Color
onSurface
=
_colorScheme
.
onSurface
;
final
Color
onSurface
=
_colorScheme
.
onSurface
;
final
Brightness
brightness
=
_colorScheme
.
brightness
;
final
Brightness
brightness
=
_colorScheme
.
brightness
;
return
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
return
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
hovered
)
&&
widget
.
showTrackOnHover
)
{
if
(
states
.
contains
(
MaterialState
.
hovered
)
&&
_showTrackOnHover
)
{
return
brightness
==
Brightness
.
light
return
_scrollbarTheme
.
trackColor
?.
resolve
(
states
)
??
(
brightness
==
Brightness
.
light
?
onSurface
.
withOpacity
(
0.03
)
?
onSurface
.
withOpacity
(
0.03
)
:
onSurface
.
withOpacity
(
0.05
);
:
onSurface
.
withOpacity
(
0.05
)
);
}
}
return
const
Color
(
0x00000000
);
return
const
Color
(
0x00000000
);
});
});
...
@@ -157,10 +170,11 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
...
@@ -157,10 +170,11 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
final
Color
onSurface
=
_colorScheme
.
onSurface
;
final
Color
onSurface
=
_colorScheme
.
onSurface
;
final
Brightness
brightness
=
_colorScheme
.
brightness
;
final
Brightness
brightness
=
_colorScheme
.
brightness
;
return
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
return
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
hovered
)
&&
widget
.
showTrackOnHover
)
{
if
(
states
.
contains
(
MaterialState
.
hovered
)
&&
_showTrackOnHover
)
{
return
brightness
==
Brightness
.
light
return
_scrollbarTheme
.
trackBorderColor
?.
resolve
(
states
)
??
(
brightness
==
Brightness
.
light
?
onSurface
.
withOpacity
(
0.1
)
?
onSurface
.
withOpacity
(
0.1
)
:
onSurface
.
withOpacity
(
0.25
);
:
onSurface
.
withOpacity
(
0.25
)
);
}
}
return
const
Color
(
0x00000000
);
return
const
Color
(
0x00000000
);
});
});
...
@@ -168,10 +182,14 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
...
@@ -168,10 +182,14 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
MaterialStateProperty
<
double
>
get
_thickness
{
MaterialStateProperty
<
double
>
get
_thickness
{
return
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
return
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
hovered
)
&&
widget
.
showTrackOnHover
)
if
(
states
.
contains
(
MaterialState
.
hovered
)
&&
_showTrackOnHover
)
return
widget
.
hoverThickness
??
_kScrollbarThicknessWithTrack
;
return
widget
.
hoverThickness
??
_scrollbarTheme
.
thickness
?.
resolve
(
states
)
??
_kScrollbarThicknessWithTrack
;
// The default scrollbar thickness is smaller on mobile.
// 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> {
...
@@ -190,6 +208,8 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
@override
@override
void
didChangeDependencies
()
{
void
didChangeDependencies
()
{
final
ThemeData
theme
=
Theme
.
of
(
context
);
final
ThemeData
theme
=
Theme
.
of
(
context
);
_colorScheme
=
theme
.
colorScheme
;
_scrollbarTheme
=
theme
.
scrollbarTheme
;
switch
(
theme
.
platform
)
{
switch
(
theme
.
platform
)
{
case
TargetPlatform
.
android
:
case
TargetPlatform
.
android
:
_useAndroidScrollbar
=
true
;
_useAndroidScrollbar
=
true
;
...
@@ -207,16 +227,16 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
...
@@ -207,16 +227,16 @@ class _ScrollbarState extends RawScrollbarState<Scrollbar> {
@override
@override
void
updateScrollbarPainter
()
{
void
updateScrollbarPainter
()
{
_colorScheme
=
Theme
.
of
(
context
).
colorScheme
;
scrollbarPainter
scrollbarPainter
..
color
=
_thumbColor
.
resolve
(
_states
)
..
color
=
_thumbColor
.
resolve
(
_states
)
..
trackColor
=
_trackColor
.
resolve
(
_states
)
..
trackColor
=
_trackColor
.
resolve
(
_states
)
..
trackBorderColor
=
_trackBorderColor
.
resolve
(
_states
)
..
trackBorderColor
=
_trackBorderColor
.
resolve
(
_states
)
..
textDirection
=
Directionality
.
of
(
context
)
..
textDirection
=
Directionality
.
of
(
context
)
..
thickness
=
_thickness
.
resolve
(
_states
)
..
thickness
=
_thickness
.
resolve
(
_states
)
..
radius
=
widget
.
radius
??
(
_useAndroidScrollbar
?
null
:
_kScrollbarRadius
)
..
radius
=
widget
.
radius
??
_scrollbarTheme
.
radius
??
(
_useAndroidScrollbar
?
null
:
_kScrollbarRadius
)
..
crossAxisMargin
=
(
_useAndroidScrollbar
?
0.0
:
_kScrollbarMargin
)
..
crossAxisMargin
=
_scrollbarTheme
.
crossAxisMargin
??
(
_useAndroidScrollbar
?
0.0
:
_kScrollbarMargin
)
..
minLength
=
_kScrollbarMinLength
..
mainAxisMargin
=
_scrollbarTheme
.
mainAxisMargin
??
0.0
..
minLength
=
_scrollbarTheme
.
minThumbLength
??
_kScrollbarMinLength
..
padding
=
MediaQuery
.
of
(
context
).
padding
;
..
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';
...
@@ -34,6 +34,7 @@ import 'outlined_button_theme.dart';
import
'page_transitions_theme.dart'
;
import
'page_transitions_theme.dart'
;
import
'popup_menu_theme.dart'
;
import
'popup_menu_theme.dart'
;
import
'radio_theme.dart'
;
import
'radio_theme.dart'
;
import
'scrollbar_theme.dart'
;
import
'slider_theme.dart'
;
import
'slider_theme.dart'
;
import
'snack_bar_theme.dart'
;
import
'snack_bar_theme.dart'
;
import
'switch_theme.dart'
;
import
'switch_theme.dart'
;
...
@@ -278,6 +279,7 @@ class ThemeData with Diagnosticable {
...
@@ -278,6 +279,7 @@ class ThemeData with Diagnosticable {
bool
?
applyElevationOverlayColor
,
bool
?
applyElevationOverlayColor
,
PageTransitionsTheme
?
pageTransitionsTheme
,
PageTransitionsTheme
?
pageTransitionsTheme
,
AppBarTheme
?
appBarTheme
,
AppBarTheme
?
appBarTheme
,
ScrollbarThemeData
?
scrollbarTheme
,
BottomAppBarTheme
?
bottomAppBarTheme
,
BottomAppBarTheme
?
bottomAppBarTheme
,
ColorScheme
?
colorScheme
,
ColorScheme
?
colorScheme
,
DialogTheme
?
dialogTheme
,
DialogTheme
?
dialogTheme
,
...
@@ -410,6 +412,7 @@ class ThemeData with Diagnosticable {
...
@@ -410,6 +412,7 @@ class ThemeData with Diagnosticable {
tabBarTheme
??=
const
TabBarTheme
();
tabBarTheme
??=
const
TabBarTheme
();
tooltipTheme
??=
const
TooltipThemeData
();
tooltipTheme
??=
const
TooltipThemeData
();
appBarTheme
??=
const
AppBarTheme
();
appBarTheme
??=
const
AppBarTheme
();
scrollbarTheme
??=
const
ScrollbarThemeData
();
bottomAppBarTheme
??=
const
BottomAppBarTheme
();
bottomAppBarTheme
??=
const
BottomAppBarTheme
();
cardTheme
??=
const
CardTheme
();
cardTheme
??=
const
CardTheme
();
chipTheme
??=
ChipThemeData
.
fromDefaults
(
chipTheme
??=
ChipThemeData
.
fromDefaults
(
...
@@ -493,6 +496,7 @@ class ThemeData with Diagnosticable {
...
@@ -493,6 +496,7 @@ class ThemeData with Diagnosticable {
applyElevationOverlayColor:
applyElevationOverlayColor
,
applyElevationOverlayColor:
applyElevationOverlayColor
,
pageTransitionsTheme:
pageTransitionsTheme
,
pageTransitionsTheme:
pageTransitionsTheme
,
appBarTheme:
appBarTheme
,
appBarTheme:
appBarTheme
,
scrollbarTheme:
scrollbarTheme
,
bottomAppBarTheme:
bottomAppBarTheme
,
bottomAppBarTheme:
bottomAppBarTheme
,
colorScheme:
colorScheme
,
colorScheme:
colorScheme
,
dialogTheme:
dialogTheme
,
dialogTheme:
dialogTheme
,
...
@@ -583,6 +587,7 @@ class ThemeData with Diagnosticable {
...
@@ -583,6 +587,7 @@ class ThemeData with Diagnosticable {
required
this
.
applyElevationOverlayColor
,
required
this
.
applyElevationOverlayColor
,
required
this
.
pageTransitionsTheme
,
required
this
.
pageTransitionsTheme
,
required
this
.
appBarTheme
,
required
this
.
appBarTheme
,
required
this
.
scrollbarTheme
,
required
this
.
bottomAppBarTheme
,
required
this
.
bottomAppBarTheme
,
required
this
.
colorScheme
,
required
this
.
colorScheme
,
required
this
.
dialogTheme
,
required
this
.
dialogTheme
,
...
@@ -657,6 +662,7 @@ class ThemeData with Diagnosticable {
...
@@ -657,6 +662,7 @@ class ThemeData with Diagnosticable {
assert
(
materialTapTargetSize
!=
null
),
assert
(
materialTapTargetSize
!=
null
),
assert
(
pageTransitionsTheme
!=
null
),
assert
(
pageTransitionsTheme
!=
null
),
assert
(
appBarTheme
!=
null
),
assert
(
appBarTheme
!=
null
),
assert
(
scrollbarTheme
!=
null
),
assert
(
bottomAppBarTheme
!=
null
),
assert
(
bottomAppBarTheme
!=
null
),
assert
(
colorScheme
!=
null
),
assert
(
colorScheme
!=
null
),
assert
(
dialogTheme
!=
null
),
assert
(
dialogTheme
!=
null
),
...
@@ -1085,6 +1091,9 @@ class ThemeData with Diagnosticable {
...
@@ -1085,6 +1091,9 @@ class ThemeData with Diagnosticable {
/// textTheme of [AppBar]s.
/// textTheme of [AppBar]s.
final
AppBarTheme
appBarTheme
;
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].
/// A theme for customizing the shape, elevation, and color of a [BottomAppBar].
final
BottomAppBarTheme
bottomAppBarTheme
;
final
BottomAppBarTheme
bottomAppBarTheme
;
...
@@ -1270,6 +1279,7 @@ class ThemeData with Diagnosticable {
...
@@ -1270,6 +1279,7 @@ class ThemeData with Diagnosticable {
bool
?
applyElevationOverlayColor
,
bool
?
applyElevationOverlayColor
,
PageTransitionsTheme
?
pageTransitionsTheme
,
PageTransitionsTheme
?
pageTransitionsTheme
,
AppBarTheme
?
appBarTheme
,
AppBarTheme
?
appBarTheme
,
ScrollbarThemeData
?
scrollbarTheme
,
BottomAppBarTheme
?
bottomAppBarTheme
,
BottomAppBarTheme
?
bottomAppBarTheme
,
ColorScheme
?
colorScheme
,
ColorScheme
?
colorScheme
,
DialogTheme
?
dialogTheme
,
DialogTheme
?
dialogTheme
,
...
@@ -1353,6 +1363,7 @@ class ThemeData with Diagnosticable {
...
@@ -1353,6 +1363,7 @@ class ThemeData with Diagnosticable {
applyElevationOverlayColor:
applyElevationOverlayColor
??
this
.
applyElevationOverlayColor
,
applyElevationOverlayColor:
applyElevationOverlayColor
??
this
.
applyElevationOverlayColor
,
pageTransitionsTheme:
pageTransitionsTheme
??
this
.
pageTransitionsTheme
,
pageTransitionsTheme:
pageTransitionsTheme
??
this
.
pageTransitionsTheme
,
appBarTheme:
appBarTheme
??
this
.
appBarTheme
,
appBarTheme:
appBarTheme
??
this
.
appBarTheme
,
scrollbarTheme:
scrollbarTheme
??
this
.
scrollbarTheme
,
bottomAppBarTheme:
bottomAppBarTheme
??
this
.
bottomAppBarTheme
,
bottomAppBarTheme:
bottomAppBarTheme
??
this
.
bottomAppBarTheme
,
colorScheme:
(
colorScheme
??
this
.
colorScheme
).
copyWith
(
brightness:
brightness
),
colorScheme:
(
colorScheme
??
this
.
colorScheme
).
copyWith
(
brightness:
brightness
),
dialogTheme:
dialogTheme
??
this
.
dialogTheme
,
dialogTheme:
dialogTheme
??
this
.
dialogTheme
,
...
@@ -1510,6 +1521,7 @@ class ThemeData with Diagnosticable {
...
@@ -1510,6 +1521,7 @@ class ThemeData with Diagnosticable {
applyElevationOverlayColor:
t
<
0.5
?
a
.
applyElevationOverlayColor
:
b
.
applyElevationOverlayColor
,
applyElevationOverlayColor:
t
<
0.5
?
a
.
applyElevationOverlayColor
:
b
.
applyElevationOverlayColor
,
pageTransitionsTheme:
t
<
0.5
?
a
.
pageTransitionsTheme
:
b
.
pageTransitionsTheme
,
pageTransitionsTheme:
t
<
0.5
?
a
.
pageTransitionsTheme
:
b
.
pageTransitionsTheme
,
appBarTheme:
AppBarTheme
.
lerp
(
a
.
appBarTheme
,
b
.
appBarTheme
,
t
),
appBarTheme:
AppBarTheme
.
lerp
(
a
.
appBarTheme
,
b
.
appBarTheme
,
t
),
scrollbarTheme:
ScrollbarThemeData
.
lerp
(
a
.
scrollbarTheme
,
b
.
scrollbarTheme
,
t
),
bottomAppBarTheme:
BottomAppBarTheme
.
lerp
(
a
.
bottomAppBarTheme
,
b
.
bottomAppBarTheme
,
t
),
bottomAppBarTheme:
BottomAppBarTheme
.
lerp
(
a
.
bottomAppBarTheme
,
b
.
bottomAppBarTheme
,
t
),
colorScheme:
ColorScheme
.
lerp
(
a
.
colorScheme
,
b
.
colorScheme
,
t
),
colorScheme:
ColorScheme
.
lerp
(
a
.
colorScheme
,
b
.
colorScheme
,
t
),
dialogTheme:
DialogTheme
.
lerp
(
a
.
dialogTheme
,
b
.
dialogTheme
,
t
),
dialogTheme:
DialogTheme
.
lerp
(
a
.
dialogTheme
,
b
.
dialogTheme
,
t
),
...
@@ -1595,6 +1607,7 @@ class ThemeData with Diagnosticable {
...
@@ -1595,6 +1607,7 @@ class ThemeData with Diagnosticable {
&&
other
.
applyElevationOverlayColor
==
applyElevationOverlayColor
&&
other
.
applyElevationOverlayColor
==
applyElevationOverlayColor
&&
other
.
pageTransitionsTheme
==
pageTransitionsTheme
&&
other
.
pageTransitionsTheme
==
pageTransitionsTheme
&&
other
.
appBarTheme
==
appBarTheme
&&
other
.
appBarTheme
==
appBarTheme
&&
other
.
scrollbarTheme
==
scrollbarTheme
&&
other
.
bottomAppBarTheme
==
bottomAppBarTheme
&&
other
.
bottomAppBarTheme
==
bottomAppBarTheme
&&
other
.
colorScheme
==
colorScheme
&&
other
.
colorScheme
==
colorScheme
&&
other
.
dialogTheme
==
dialogTheme
&&
other
.
dialogTheme
==
dialogTheme
...
@@ -1679,6 +1692,7 @@ class ThemeData with Diagnosticable {
...
@@ -1679,6 +1692,7 @@ class ThemeData with Diagnosticable {
applyElevationOverlayColor
,
applyElevationOverlayColor
,
pageTransitionsTheme
,
pageTransitionsTheme
,
appBarTheme
,
appBarTheme
,
scrollbarTheme
,
bottomAppBarTheme
,
bottomAppBarTheme
,
colorScheme
,
colorScheme
,
dialogTheme
,
dialogTheme
,
...
@@ -1760,6 +1774,7 @@ class ThemeData with Diagnosticable {
...
@@ -1760,6 +1774,7 @@ class ThemeData with Diagnosticable {
properties
.
add
(
DiagnosticsProperty
<
bool
>(
'applyElevationOverlayColor'
,
applyElevationOverlayColor
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
bool
>(
'applyElevationOverlayColor'
,
applyElevationOverlayColor
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
PageTransitionsTheme
>(
'pageTransitionsTheme'
,
pageTransitionsTheme
,
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
<
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
<
BottomAppBarTheme
>(
'bottomAppBarTheme'
,
bottomAppBarTheme
,
defaultValue:
defaultData
.
bottomAppBarTheme
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
ColorScheme
>(
'colorScheme'
,
colorScheme
,
defaultValue:
defaultData
.
colorScheme
,
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
));
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 {
...
@@ -600,15 +600,14 @@ class RawScrollbar extends StatefulWidget {
Key
?
key
,
Key
?
key
,
required
this
.
child
,
required
this
.
child
,
this
.
controller
,
this
.
controller
,
this
.
isAlwaysShown
=
false
,
this
.
isAlwaysShown
,
this
.
radius
,
this
.
radius
,
this
.
thickness
,
this
.
thickness
,
this
.
thumbColor
,
this
.
thumbColor
,
this
.
fadeDuration
=
_kScrollbarFadeDuration
,
this
.
fadeDuration
=
_kScrollbarFadeDuration
,
this
.
timeToFade
=
_kScrollbarTimeToFade
,
this
.
timeToFade
=
_kScrollbarTimeToFade
,
this
.
pressDuration
=
Duration
.
zero
,
this
.
pressDuration
=
Duration
.
zero
,
})
:
assert
(
isAlwaysShown
!=
null
),
})
:
assert
(
child
!=
null
),
assert
(
child
!=
null
),
assert
(
fadeDuration
!=
null
),
assert
(
fadeDuration
!=
null
),
assert
(
timeToFade
!=
null
),
assert
(
timeToFade
!=
null
),
assert
(
pressDuration
!=
null
),
assert
(
pressDuration
!=
null
),
...
@@ -683,7 +682,7 @@ class RawScrollbar extends StatefulWidget {
...
@@ -683,7 +682,7 @@ class RawScrollbar extends StatefulWidget {
/// [controller] property has not been set, the [PrimaryScrollController] will
/// [controller] property has not been set, the [PrimaryScrollController] will
/// be used.
/// be used.
///
///
/// Defaults to false.
/// Defaults to false
when null
.
///
///
/// {@tool snippet}
/// {@tool snippet}
///
///
...
@@ -728,7 +727,7 @@ class RawScrollbar extends StatefulWidget {
...
@@ -728,7 +727,7 @@ class RawScrollbar extends StatefulWidget {
/// }
/// }
/// ```
/// ```
/// {@end-tool}
/// {@end-tool}
final
bool
isAlwaysShown
;
final
bool
?
isAlwaysShown
;
/// The [Radius] of the scrollbar thumb's rounded rectangle corners.
/// The [Radius] of the scrollbar thumb's rounded rectangle corners.
///
///
...
@@ -790,6 +789,14 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
...
@@ -790,6 +789,14 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
@protected
@protected
late
final
ScrollbarPainter
scrollbarPainter
;
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
@override
void
initState
()
{
void
initState
()
{
super
.
initState
();
super
.
initState
();
...
@@ -820,7 +827,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
...
@@ -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.
// A scroll event is required in order to paint the thumb.
void
_maybeTriggerScrollbar
()
{
void
_maybeTriggerScrollbar
()
{
WidgetsBinding
.
instance
!.
addPostFrameCallback
((
Duration
duration
)
{
WidgetsBinding
.
instance
!.
addPostFrameCallback
((
Duration
duration
)
{
if
(
widget
.
isAlwaysShown
)
{
if
(
showScrollbar
)
{
_fadeoutTimer
?.
cancel
();
_fadeoutTimer
?.
cancel
();
// Wait one frame and cause an empty scroll event. This allows the
// Wait one frame and cause an empty scroll event. This allows the
// thumb to show immediately when isAlwaysShown is true. A scroll
// thumb to show immediately when isAlwaysShown is true. A scroll
...
@@ -881,7 +888,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
...
@@ -881,7 +888,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
}
}
void
_maybeStartFadeoutTimer
()
{
void
_maybeStartFadeoutTimer
()
{
if
(!
widget
.
isAlwaysShown
)
{
if
(!
showScrollbar
)
{
_fadeoutTimer
?.
cancel
();
_fadeoutTimer
?.
cancel
();
_fadeoutTimer
=
Timer
(
widget
.
timeToFade
,
()
{
_fadeoutTimer
=
Timer
(
widget
.
timeToFade
,
()
{
_fadeoutAnimationController
.
reverse
();
_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() {
...
@@ -742,6 +742,7 @@ void main() {
applyElevationOverlayColor:
false
,
applyElevationOverlayColor:
false
,
pageTransitionsTheme:
pageTransitionTheme
,
pageTransitionsTheme:
pageTransitionTheme
,
appBarTheme:
const
AppBarTheme
(
color:
Colors
.
black
),
appBarTheme:
const
AppBarTheme
(
color:
Colors
.
black
),
scrollbarTheme:
const
ScrollbarThemeData
(
radius:
Radius
.
circular
(
10.0
)),
bottomAppBarTheme:
const
BottomAppBarTheme
(
color:
Colors
.
black
),
bottomAppBarTheme:
const
BottomAppBarTheme
(
color:
Colors
.
black
),
colorScheme:
const
ColorScheme
.
light
(),
colorScheme:
const
ColorScheme
.
light
(),
dialogTheme:
const
DialogTheme
(
backgroundColor:
Colors
.
black
),
dialogTheme:
const
DialogTheme
(
backgroundColor:
Colors
.
black
),
...
...
packages/flutter/test/material/theme_data_test.dart
View file @
09008e6f
...
@@ -292,6 +292,7 @@ void main() {
...
@@ -292,6 +292,7 @@ void main() {
applyElevationOverlayColor:
false
,
applyElevationOverlayColor:
false
,
pageTransitionsTheme:
pageTransitionTheme
,
pageTransitionsTheme:
pageTransitionTheme
,
appBarTheme:
const
AppBarTheme
(
color:
Colors
.
black
),
appBarTheme:
const
AppBarTheme
(
color:
Colors
.
black
),
scrollbarTheme:
const
ScrollbarThemeData
(
radius:
Radius
.
circular
(
10.0
)),
bottomAppBarTheme:
const
BottomAppBarTheme
(
color:
Colors
.
black
),
bottomAppBarTheme:
const
BottomAppBarTheme
(
color:
Colors
.
black
),
colorScheme:
const
ColorScheme
.
light
(),
colorScheme:
const
ColorScheme
.
light
(),
dialogTheme:
const
DialogTheme
(
backgroundColor:
Colors
.
black
),
dialogTheme:
const
DialogTheme
(
backgroundColor:
Colors
.
black
),
...
@@ -384,6 +385,7 @@ void main() {
...
@@ -384,6 +385,7 @@ void main() {
applyElevationOverlayColor:
true
,
applyElevationOverlayColor:
true
,
pageTransitionsTheme:
const
PageTransitionsTheme
(),
pageTransitionsTheme:
const
PageTransitionsTheme
(),
appBarTheme:
const
AppBarTheme
(
color:
Colors
.
white
),
appBarTheme:
const
AppBarTheme
(
color:
Colors
.
white
),
scrollbarTheme:
const
ScrollbarThemeData
(
radius:
Radius
.
circular
(
10.0
)),
bottomAppBarTheme:
const
BottomAppBarTheme
(
color:
Colors
.
white
),
bottomAppBarTheme:
const
BottomAppBarTheme
(
color:
Colors
.
white
),
colorScheme:
const
ColorScheme
.
light
(),
colorScheme:
const
ColorScheme
.
light
(),
dialogTheme:
const
DialogTheme
(
backgroundColor:
Colors
.
white
),
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