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
74489206
Unverified
Commit
74489206
authored
Jun 30, 2021
by
Anas35
Committed by
GitHub
Jun 30, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Extend Toggle Button's fill color with MaterialState (#82026)
parent
f76b2926
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
247 additions
and
6 deletions
+247
-6
toggle_buttons.dart
packages/flutter/lib/src/material/toggle_buttons.dart
+59
-6
toggle_buttons_test.dart
packages/flutter/test/material/toggle_buttons_test.dart
+120
-0
toggle_buttons_theme_test.dart
...ages/flutter/test/material/toggle_buttons_theme_test.dart
+68
-0
No files found.
packages/flutter/lib/src/material/toggle_buttons.dart
View file @
74489206
...
...
@@ -9,8 +9,10 @@ import 'package:flutter/rendering.dart';
import
'package:flutter/widgets.dart'
;
import
'button.dart'
;
import
'color_scheme.dart'
;
import
'constants.dart'
;
import
'debug.dart'
;
import
'material_state.dart'
;
import
'theme.dart'
;
import
'theme_data.dart'
;
import
'toggle_buttons_theme.dart'
;
...
...
@@ -284,6 +286,13 @@ class ToggleButtons extends StatelessWidget {
/// ToggleButtonTheme.of(context).fillColor is used. If
/// [ToggleButtonsThemeData.fillColor] is also null, then
/// the fill color is null.
///
/// If fillColor is a [MaterialStateProperty<Color>], then [MaterialStateProperty.resolve]
/// is used for the following [MaterialState]s:
///
/// * [MaterialState.disabled]
/// * [MaterialState.selected]
///
final
Color
?
fillColor
;
/// The color to use for filling the button when the button has input focus.
...
...
@@ -654,7 +663,7 @@ class ToggleButtons extends StatelessWidget {
color:
color
,
selectedColor:
selectedColor
,
disabledColor:
disabledColor
,
fillColor:
fillColor
??
toggleButtonsTheme
.
fillColor
,
fillColor:
fillColor
,
focusColor:
focusColor
??
toggleButtonsTheme
.
focusColor
,
highlightColor:
highlightColor
??
toggleButtonsTheme
.
highlightColor
,
hoverColor:
hoverColor
??
toggleButtonsTheme
.
hoverColor
,
...
...
@@ -852,23 +861,39 @@ class _ToggleButton extends StatelessWidget {
/// The button's label, which is usually an [Icon] or a [Text] widget.
final
Widget
child
;
Color
_resolveColor
(
Set
<
MaterialState
>
states
,
MaterialStateProperty
<
Color
?>
widgetColor
,
MaterialStateProperty
<
Color
?>
themeColor
,
MaterialStateProperty
<
Color
>
defaultColor
)
{
return
widgetColor
.
resolve
(
states
)
??
themeColor
.
resolve
(
states
)
??
defaultColor
.
resolve
(
states
);
}
@override
Widget
build
(
BuildContext
context
)
{
assert
(
debugCheckHasMaterial
(
context
));
final
Color
currentColor
;
final
Color
currentFillColor
;
Color
?
currentFocusColor
;
Color
?
currentHoverColor
;
Color
?
currentSplashColor
;
final
ThemeData
theme
=
Theme
.
of
(
context
);
final
ToggleButtonsThemeData
toggleButtonsTheme
=
ToggleButtonsTheme
.
of
(
context
);
final
Set
<
MaterialState
>
states
=
<
MaterialState
>{
if
(
selected
&&
onPressed
!=
null
)
MaterialState
.
selected
,
if
(
onPressed
==
null
)
MaterialState
.
disabled
,
};
final
Color
currentFillColor
=
_resolveColor
(
states
,
_ResolveFillColor
(
fillColor
),
_ResolveFillColor
(
toggleButtonsTheme
.
fillColor
),
_DefaultFillColor
(
theme
.
colorScheme
),
);
if
(
onPressed
!=
null
&&
selected
)
{
currentColor
=
selectedColor
??
toggleButtonsTheme
.
selectedColor
??
theme
.
colorScheme
.
primary
;
currentFillColor
=
fillColor
??
theme
.
colorScheme
.
primary
.
withOpacity
(
0.12
);
currentFocusColor
=
focusColor
??
toggleButtonsTheme
.
focusColor
??
theme
.
colorScheme
.
primary
.
withOpacity
(
0.12
);
...
...
@@ -882,7 +907,6 @@ class _ToggleButton extends StatelessWidget {
currentColor
=
color
??
toggleButtonsTheme
.
color
??
theme
.
colorScheme
.
onSurface
.
withOpacity
(
0.87
);
currentFillColor
=
theme
.
colorScheme
.
surface
.
withOpacity
(
0.0
);
currentFocusColor
=
focusColor
??
toggleButtonsTheme
.
focusColor
??
theme
.
colorScheme
.
onSurface
.
withOpacity
(
0.12
);
...
...
@@ -896,7 +920,6 @@ class _ToggleButton extends StatelessWidget {
currentColor
=
disabledColor
??
toggleButtonsTheme
.
disabledColor
??
theme
.
colorScheme
.
onSurface
.
withOpacity
(
0.38
);
currentFillColor
=
theme
.
colorScheme
.
surface
.
withOpacity
(
0.0
);
}
final
TextStyle
currentTextStyle
=
textStyle
??
toggleButtonsTheme
.
textStyle
??
theme
.
textTheme
.
bodyText2
!;
...
...
@@ -951,6 +974,36 @@ class _ToggleButton extends StatelessWidget {
}
}
@immutable
class
_ResolveFillColor
extends
MaterialStateProperty
<
Color
?>
with
Diagnosticable
{
_ResolveFillColor
(
this
.
primary
);
final
Color
?
primary
;
@override
Color
?
resolve
(
Set
<
MaterialState
>
states
)
{
if
(
primary
is
MaterialStateProperty
<
Color
>)
{
return
MaterialStateProperty
.
resolveAs
<
Color
?>(
primary
,
states
);
}
return
states
.
contains
(
MaterialState
.
selected
)
?
primary
:
null
;
}
}
@immutable
class
_DefaultFillColor
extends
MaterialStateProperty
<
Color
>
with
Diagnosticable
{
_DefaultFillColor
(
this
.
colorScheme
);
final
ColorScheme
colorScheme
;
@override
Color
resolve
(
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
return
colorScheme
.
primary
.
withOpacity
(
0.12
);
}
return
colorScheme
.
surface
.
withOpacity
(
0.0
);
}
}
class
_SelectToggleButton
extends
SingleChildRenderObjectWidget
{
const
_SelectToggleButton
({
Key
?
key
,
...
...
packages/flutter/test/material/toggle_buttons_test.dart
View file @
74489206
...
...
@@ -665,6 +665,126 @@ void main() {
expect
(
material
.
type
,
MaterialType
.
button
);
});
testWidgets
(
'Custom button fillColor - Non MaterialState'
,
(
WidgetTester
tester
)
async
{
Material
buttonColor
(
String
text
)
{
return
tester
.
widget
<
Material
>(
find
.
descendant
(
of:
find
.
byType
(
RawMaterialButton
),
matching:
find
.
widgetWithText
(
Material
,
text
),
),
);
}
final
ThemeData
theme
=
ThemeData
();
const
Color
selectedFillColor
=
Colors
.
yellow
;
await
tester
.
pumpWidget
(
Material
(
child:
boilerplate
(
child:
ToggleButtons
(
fillColor:
selectedFillColor
,
isSelected:
const
<
bool
>[
false
,
true
],
onPressed:
(
int
index
)
{},
children:
const
<
Widget
>[
Text
(
'First child'
),
Text
(
'Second child'
),
],
),
),
),
);
await
tester
.
pumpAndSettle
();
expect
(
buttonColor
(
'First child'
).
color
,
theme
.
colorScheme
.
surface
.
withOpacity
(
0.0
));
expect
(
buttonColor
(
'Second child'
).
color
,
selectedFillColor
);
await
tester
.
pumpWidget
(
Material
(
child:
boilerplate
(
child:
ToggleButtons
(
fillColor:
selectedFillColor
,
isSelected:
const
<
bool
>[
false
,
true
],
onPressed:
null
,
children:
const
<
Widget
>[
Text
(
'First child'
),
Text
(
'Second child'
),
],
),
),
),
);
await
tester
.
pumpAndSettle
();
expect
(
buttonColor
(
'First child'
).
color
,
theme
.
colorScheme
.
surface
.
withOpacity
(
0.0
));
expect
(
buttonColor
(
'Second child'
).
color
,
theme
.
colorScheme
.
surface
.
withOpacity
(
0.0
));
});
testWidgets
(
'Custom button fillColor - MaterialState'
,
(
WidgetTester
tester
)
async
{
Material
buttonColor
(
String
text
)
{
return
tester
.
widget
<
Material
>(
find
.
descendant
(
of:
find
.
byType
(
RawMaterialButton
),
matching:
find
.
widgetWithText
(
Material
,
text
),
),
);
}
const
Color
selectedFillColor
=
Colors
.
orange
;
const
Color
defaultFillColor
=
Colors
.
blue
;
Color
getFillColor
(
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
return
selectedFillColor
;
}
return
defaultFillColor
;
}
await
tester
.
pumpWidget
(
Material
(
child:
boilerplate
(
child:
ToggleButtons
(
fillColor:
MaterialStateColor
.
resolveWith
(
getFillColor
),
isSelected:
const
<
bool
>[
false
,
true
],
onPressed:
(
int
index
)
{},
children:
const
<
Widget
>[
Text
(
'First child'
),
Text
(
'Second child'
),
],
),
),
),
);
await
tester
.
pumpAndSettle
();
expect
(
buttonColor
(
'First child'
).
color
,
defaultFillColor
);
expect
(
buttonColor
(
'Second child'
).
color
,
selectedFillColor
);
// disabled
await
tester
.
pumpWidget
(
Material
(
child:
boilerplate
(
child:
ToggleButtons
(
fillColor:
MaterialStateColor
.
resolveWith
(
getFillColor
),
isSelected:
const
<
bool
>[
false
,
true
],
onPressed:
null
,
children:
const
<
Widget
>[
Text
(
'First child'
),
Text
(
'Second child'
),
],
),
),
),
);
await
tester
.
pumpAndSettle
();
expect
(
buttonColor
(
'First child'
).
color
,
defaultFillColor
);
expect
(
buttonColor
(
'Second child'
).
color
,
defaultFillColor
);
});
testWidgets
(
'Default InkWell colors - unselected'
,
(
WidgetTester
tester
)
async
{
final
ThemeData
theme
=
ThemeData
();
final
FocusNode
focusNode
=
FocusNode
();
...
...
packages/flutter/test/material/toggle_buttons_theme_test.dart
View file @
74489206
...
...
@@ -363,6 +363,74 @@ void main() {
expect
(
material
.
type
,
MaterialType
.
button
);
});
testWidgets
(
'Custom Theme button fillColor in different states'
,
(
WidgetTester
tester
)
async
{
Material
buttonColor
(
String
text
)
{
return
tester
.
widget
<
Material
>(
find
.
descendant
(
of:
find
.
byType
(
RawMaterialButton
),
matching:
find
.
widgetWithText
(
Material
,
text
),
),
);
}
const
Color
enabledFillColor
=
Colors
.
green
;
const
Color
selectedFillColor
=
Colors
.
blue
;
const
Color
disabledFillColor
=
Colors
.
yellow
;
Color
getColor
(
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
return
selectedFillColor
;
}
else
if
(
states
.
contains
(
MaterialState
.
disabled
))
{
return
disabledFillColor
;
}
return
enabledFillColor
;
}
await
tester
.
pumpWidget
(
Material
(
child:
boilerplate
(
child:
ToggleButtonsTheme
(
data:
ToggleButtonsThemeData
(
fillColor:
MaterialStateColor
.
resolveWith
(
getColor
)),
child:
ToggleButtons
(
isSelected:
const
<
bool
>[
true
,
false
],
onPressed:
(
int
index
)
{},
children:
const
<
Widget
>
[
Text
(
'First child'
),
Text
(
'Second child'
),
],
),
),
),
),
);
await
tester
.
pumpAndSettle
();
expect
(
buttonColor
(
'First child'
).
color
,
selectedFillColor
);
expect
(
buttonColor
(
'Second child'
).
color
,
enabledFillColor
);
await
tester
.
pumpWidget
(
Material
(
child:
boilerplate
(
child:
ToggleButtonsTheme
(
data:
ToggleButtonsThemeData
(
fillColor:
MaterialStateColor
.
resolveWith
(
getColor
)),
child:
ToggleButtons
(
isSelected:
const
<
bool
>[
true
,
false
],
onPressed:
null
,
children:
const
<
Widget
>[
Text
(
'First child'
),
Text
(
'Second child'
),
],
),
),
),
),
);
expect
(
buttonColor
(
'First child'
).
color
,
disabledFillColor
);
expect
(
buttonColor
(
'Second child'
).
color
,
disabledFillColor
);
});
testWidgets
(
'Theme InkWell colors'
,
(
WidgetTester
tester
)
async
{
const
Color
splashColor
=
Color
(
0xff4caf50
);
const
Color
highlightColor
=
Color
(
0xffcddc39
);
...
...
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