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
86c02e99
Unverified
Commit
86c02e99
authored
3 years ago
by
Darren Austin
Committed by
GitHub
3 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Migrate Card widget to Material 3. (#100532)
parent
22a9ff74
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
307 additions
and
15 deletions
+307
-15
gen_defaults.dart
dev/tools/gen_defaults/bin/gen_defaults.dart
+2
-0
card_template.dart
dev/tools/gen_defaults/lib/card_template.dart
+34
-0
card.2.dart
examples/api/lib/material/card/card.2.dart
+110
-0
card.dart
packages/flutter/lib/src/material/card.dart
+81
-11
card_theme.dart
packages/flutter/lib/src/material/card_theme.dart
+14
-0
theme_data.dart
packages/flutter/lib/src/material/theme_data.dart
+1
-0
card_theme_test.dart
packages/flutter/test/material/card_theme_test.dart
+65
-4
No files found.
dev/tools/gen_defaults/bin/gen_defaults.dart
View file @
86c02e99
...
...
@@ -17,6 +17,7 @@
import
'dart:convert'
;
import
'dart:io'
;
import
'package:gen_defaults/card_template.dart'
;
import
'package:gen_defaults/dialog_template.dart'
;
import
'package:gen_defaults/fab_template.dart'
;
import
'package:gen_defaults/navigation_bar_template.dart'
;
...
...
@@ -71,6 +72,7 @@ Future<void> main(List<String> args) async {
tokens
[
'colorsLight'
]
=
_readTokenFile
(
'color_light.json'
);
tokens
[
'colorsDark'
]
=
_readTokenFile
(
'color_dark.json'
);
CardTemplate
(
'
$materialLib
/card.dart'
,
tokens
).
updateFile
();
DialogTemplate
(
'
$materialLib
/dialog.dart'
,
tokens
).
updateFile
();
FABTemplate
(
'
$materialLib
/floating_action_button.dart'
,
tokens
).
updateFile
();
NavigationBarTemplate
(
'
$materialLib
/navigation_bar.dart'
,
tokens
).
updateFile
();
...
...
This diff is collapsed.
Click to expand it.
dev/tools/gen_defaults/lib/card_template.dart
0 → 100644
View file @
86c02e99
// 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
'template.dart'
;
class
CardTemplate
extends
TokenTemplate
{
const
CardTemplate
(
String
fileName
,
Map
<
String
,
dynamic
>
tokens
)
:
super
(
fileName
,
tokens
);
@override
String
generate
()
=>
'''
// Generated version
${tokens["version"]}
class _TokenDefaultsM3 extends CardTheme {
const _TokenDefaultsM3(this.context)
: super(
clipBehavior: Clip.none,
elevation:
${elevation("md.comp.elevated-card.container")}
,
margin: const EdgeInsets.all(4.0),
shape:
${shape("md.comp.elevated-card.container")}
,
);
final BuildContext context;
@override
Color? get color => Theme.of(context).colorScheme.
${color("md.comp.elevated-card.container")}
;
@override
Color? get shadowColor => Theme.of(context).colorScheme.
${tokens["md.comp.elevated-card.container.shadow-color"]}
;
@override
Color? get surfaceTintColor => Theme.of(context).colorScheme.
${tokens["md.comp.elevated-card.container.surface-tint-layer.color"]}
;
}
'''
;
}
This diff is collapsed.
Click to expand it.
examples/api/lib/material/card/card.2.dart
0 → 100644
View file @
86c02e99
// 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.
// Flutter code sample for Card
import
'package:flutter/material.dart'
;
void
main
(
)
{
runApp
(
const
CardExamplesApp
());
}
class
CardExamplesApp
extends
StatelessWidget
{
const
CardExamplesApp
({
Key
?
key
})
:
super
(
key:
key
);
@override
Widget
build
(
BuildContext
context
)
{
return
MaterialApp
(
theme:
ThemeData
(
colorSchemeSeed:
const
Color
(
0xff6750a4
),
useMaterial3:
true
),
home:
Scaffold
(
appBar:
AppBar
(
title:
const
Text
(
'Card Examples'
)),
body:
Column
(
children:
const
<
Widget
>[
Spacer
(),
ElevatedCardExample
(),
FilledCardExample
(),
OutlinedCardExample
(),
Spacer
(),
],
),
),
);
}
}
/// An example of the elevated card type.
///
/// The default settings for [Card] will provide an elevated
/// card matching the spec:
///
/// https://m3.material.io/components/cards/specs#a012d40d-7a5c-4b07-8740-491dec79d58b
class
ElevatedCardExample
extends
StatelessWidget
{
const
ElevatedCardExample
({
Key
?
key
})
:
super
(
key:
key
);
@override
Widget
build
(
BuildContext
context
)
{
return
const
Center
(
child:
Card
(
child:
SizedBox
(
width:
300
,
height:
100
,
child:
Center
(
child:
Text
(
'Elevated Card'
)),
),
),
);
}
}
/// An example of the filled card type.
///
/// To make a [Card] match the filled type, the default elevation and color
/// need to be changed to the values from the spec:
///
/// https://m3.material.io/components/cards/specs#0f55bf62-edf2-4619-b00d-b9ed462f2c5a
class
FilledCardExample
extends
StatelessWidget
{
const
FilledCardExample
({
Key
?
key
})
:
super
(
key:
key
);
@override
Widget
build
(
BuildContext
context
)
{
return
Center
(
child:
Card
(
elevation:
0
,
color:
Theme
.
of
(
context
).
colorScheme
.
surfaceVariant
,
child:
const
SizedBox
(
width:
300
,
height:
100
,
child:
Center
(
child:
Text
(
'Filled Card'
)),
),
),
);
}
}
/// An example of the outlined card type.
///
/// To make a [Card] match the outlined type, the default elevation and shape
/// need to be changed to the values from the spec:
///
/// https://m3.material.io/components/cards/specs#0f55bf62-edf2-4619-b00d-b9ed462f2c5a
class
OutlinedCardExample
extends
StatelessWidget
{
const
OutlinedCardExample
({
Key
?
key
})
:
super
(
key:
key
);
@override
Widget
build
(
BuildContext
context
)
{
return
Center
(
child:
Card
(
elevation:
0
,
shape:
RoundedRectangleBorder
(
side:
BorderSide
(
color:
Theme
.
of
(
context
).
colorScheme
.
outline
,
),
borderRadius:
const
BorderRadius
.
all
(
Radius
.
circular
(
12
)),
),
child:
const
SizedBox
(
width:
300
,
height:
100
,
child:
Center
(
child:
Text
(
'Outlined Card'
)),
),
),
);
}
}
This diff is collapsed.
Click to expand it.
packages/flutter/lib/src/material/card.dart
View file @
86c02e99
...
...
@@ -38,6 +38,16 @@ import 'theme.dart';
/// ** See code in examples/api/lib/material/card/card.1.dart **
/// {@end-tool}
///
/// Material Design 3 introduced new types of cards. These can
/// be produced by configuring the [Card] widget's properties.
/// [Card] widget.
/// {@tool dartpad}
/// This sample shows creation of [Card] widgets for elevated, filled and
/// outlined types, as described in: https://m3.material.io/components/cards/overview
///
/// ** See code in examples/api/lib/material/card/card.2.dart **
/// {@end-tool}
///
/// See also:
///
/// * [ListTile], to display icons and text in a card.
...
...
@@ -52,6 +62,7 @@ class Card extends StatelessWidget {
Key
?
key
,
this
.
color
,
this
.
shadowColor
,
this
.
surfaceTintColor
,
this
.
elevation
,
this
.
shape
,
this
.
borderOnForeground
=
true
,
...
...
@@ -78,6 +89,18 @@ class Card extends StatelessWidget {
/// (default black) is used.
final
Color
?
shadowColor
;
/// The color used as an overlay on [color] to indicate elevation.
///
/// If this is null, no overlay will be applied. Otherwise the this
/// color will be composited on top of [color] with an opacity related
/// to [elevation] and used to paint the background of the card.
///
/// The default is null.
///
/// See [Material.surfaceTintColor] for more details on how this
/// overlay is applied.
final
Color
?
surfaceTintColor
;
/// The z-coordinate at which to place this card. This controls the size of
/// the shadow below the card.
///
...
...
@@ -135,27 +158,24 @@ class Card extends StatelessWidget {
/// {@macro flutter.widgets.ProxyWidget.child}
final
Widget
?
child
;
static
const
double
_defaultElevation
=
1.0
;
@override
Widget
build
(
BuildContext
context
)
{
final
ThemeData
theme
=
Theme
.
of
(
context
);
final
CardTheme
cardTheme
=
CardTheme
.
of
(
context
);
final
CardTheme
defaults
=
Theme
.
of
(
context
).
useMaterial3
?
_TokenDefaultsM3
(
context
)
:
_DefaultsM2
(
context
);
return
Semantics
(
container:
semanticContainer
,
child:
Container
(
margin:
margin
??
cardTheme
.
margin
??
const
EdgeInsets
.
all
(
4.0
)
,
margin:
margin
??
cardTheme
.
margin
??
defaults
.
margin
!
,
child:
Material
(
type:
MaterialType
.
card
,
shadowColor:
shadowColor
??
cardTheme
.
shadowColor
??
theme
.
shadowColor
,
color:
color
??
cardTheme
.
color
??
theme
.
cardColor
,
elevation:
elevation
??
cardTheme
.
elevation
??
_defaultElevation
,
shape:
shape
??
cardTheme
.
shape
??
const
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
4.0
)),
),
color:
color
??
cardTheme
.
color
??
defaults
.
color
,
shadowColor:
shadowColor
??
cardTheme
.
shadowColor
??
defaults
.
shadowColor
,
surfaceTintColor:
surfaceTintColor
??
cardTheme
.
surfaceTintColor
??
defaults
.
surfaceTintColor
,
elevation:
elevation
??
cardTheme
.
elevation
??
defaults
.
elevation
!,
shape:
shape
??
cardTheme
.
shape
??
defaults
.
shape
,
borderOnForeground:
borderOnForeground
,
clipBehavior:
clipBehavior
??
cardTheme
.
clipBehavior
??
Clip
.
none
,
clipBehavior:
clipBehavior
??
cardTheme
.
clipBehavior
??
defaults
.
clipBehavior
!
,
child:
Semantics
(
explicitChildNodes:
!
semanticContainer
,
child:
child
,
...
...
@@ -165,3 +185,53 @@ class Card extends StatelessWidget {
);
}
}
class
_DefaultsM2
extends
CardTheme
{
const
_DefaultsM2
(
this
.
context
)
:
super
(
clipBehavior:
Clip
.
none
,
elevation:
1.0
,
margin:
const
EdgeInsets
.
all
(
4.0
),
shape:
const
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
4.0
)),
)
);
final
BuildContext
context
;
@override
Color
?
get
color
=>
Theme
.
of
(
context
).
cardColor
;
@override
Color
?
get
shadowColor
=>
Theme
.
of
(
context
).
shadowColor
;
}
// BEGIN GENERATED TOKEN PROPERTIES
// Generated code to the end of this file. Do not edit by hand.
// These defaults are generated from the Material Design Token
// database by the script dev/tools/gen_defaults/bin/gen_defaults.dart.
// Generated version v0_90
class
_TokenDefaultsM3
extends
CardTheme
{
const
_TokenDefaultsM3
(
this
.
context
)
:
super
(
clipBehavior:
Clip
.
none
,
elevation:
1.0
,
margin:
const
EdgeInsets
.
all
(
4.0
),
shape:
const
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
only
(
topLeft:
Radius
.
circular
(
12.0
),
topRight:
Radius
.
circular
(
12.0
),
bottomLeft:
Radius
.
circular
(
12.0
),
bottomRight:
Radius
.
circular
(
12.0
))),
);
final
BuildContext
context
;
@override
Color
?
get
color
=>
Theme
.
of
(
context
).
colorScheme
.
surface
;
@override
Color
?
get
shadowColor
=>
Theme
.
of
(
context
).
colorScheme
.
shadow
;
@override
Color
?
get
surfaceTintColor
=>
Theme
.
of
(
context
).
colorScheme
.
surfaceTint
;
}
// END GENERATED TOKEN PROPERTIES
This diff is collapsed.
Click to expand it.
packages/flutter/lib/src/material/card_theme.dart
View file @
86c02e99
...
...
@@ -36,6 +36,7 @@ class CardTheme with Diagnosticable {
this
.
clipBehavior
,
this
.
color
,
this
.
shadowColor
,
this
.
surfaceTintColor
,
this
.
elevation
,
this
.
margin
,
this
.
shape
,
...
...
@@ -56,6 +57,13 @@ class CardTheme with Diagnosticable {
/// If null, [Card] defaults to fully opaque black.
final
Color
?
shadowColor
;
/// Default value for [Card.surfaceTintColor].
///
/// If null, [Card] will not display an overlay color.
///
/// See [Material.surfaceTintColor] for more details.
final
Color
?
surfaceTintColor
;
/// Default value for [Card.elevation].
///
/// If null, [Card] uses a default of 1.0.
...
...
@@ -79,6 +87,7 @@ class CardTheme with Diagnosticable {
Clip
?
clipBehavior
,
Color
?
color
,
Color
?
shadowColor
,
Color
?
surfaceTintColor
,
double
?
elevation
,
EdgeInsetsGeometry
?
margin
,
ShapeBorder
?
shape
,
...
...
@@ -87,6 +96,7 @@ class CardTheme with Diagnosticable {
clipBehavior:
clipBehavior
??
this
.
clipBehavior
,
color:
color
??
this
.
color
,
shadowColor:
shadowColor
??
this
.
shadowColor
,
surfaceTintColor:
surfaceTintColor
??
this
.
surfaceTintColor
,
elevation:
elevation
??
this
.
elevation
,
margin:
margin
??
this
.
margin
,
shape:
shape
??
this
.
shape
,
...
...
@@ -109,6 +119,7 @@ class CardTheme with Diagnosticable {
clipBehavior:
t
<
0.5
?
a
?.
clipBehavior
:
b
?.
clipBehavior
,
color:
Color
.
lerp
(
a
?.
color
,
b
?.
color
,
t
),
shadowColor:
Color
.
lerp
(
a
?.
shadowColor
,
b
?.
shadowColor
,
t
),
surfaceTintColor:
Color
.
lerp
(
a
?.
surfaceTintColor
,
b
?.
surfaceTintColor
,
t
),
elevation:
lerpDouble
(
a
?.
elevation
,
b
?.
elevation
,
t
),
margin:
EdgeInsetsGeometry
.
lerp
(
a
?.
margin
,
b
?.
margin
,
t
),
shape:
ShapeBorder
.
lerp
(
a
?.
shape
,
b
?.
shape
,
t
),
...
...
@@ -120,6 +131,7 @@ class CardTheme with Diagnosticable {
clipBehavior
,
color
,
shadowColor
,
surfaceTintColor
,
elevation
,
margin
,
shape
,
...
...
@@ -135,6 +147,7 @@ class CardTheme with Diagnosticable {
&&
other
.
clipBehavior
==
clipBehavior
&&
other
.
color
==
color
&&
other
.
shadowColor
==
shadowColor
&&
other
.
surfaceTintColor
==
surfaceTintColor
&&
other
.
elevation
==
elevation
&&
other
.
margin
==
margin
&&
other
.
shape
==
shape
;
...
...
@@ -146,6 +159,7 @@ class CardTheme with Diagnosticable {
properties
.
add
(
DiagnosticsProperty
<
Clip
>(
'clipBehavior'
,
clipBehavior
,
defaultValue:
null
));
properties
.
add
(
ColorProperty
(
'color'
,
color
,
defaultValue:
null
));
properties
.
add
(
ColorProperty
(
'shadowColor'
,
shadowColor
,
defaultValue:
null
));
properties
.
add
(
ColorProperty
(
'surfaceTintColor'
,
surfaceTintColor
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
double
>(
'elevation'
,
elevation
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
EdgeInsetsGeometry
>(
'margin'
,
margin
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
ShapeBorder
>(
'shape'
,
shape
,
defaultValue:
null
));
...
...
This diff is collapsed.
Click to expand it.
packages/flutter/lib/src/material/theme_data.dart
View file @
86c02e99
...
...
@@ -1249,6 +1249,7 @@ class ThemeData with Diagnosticable {
/// Components that have been migrated to Material 3 are:
///
/// * [AlertDialog]
/// * [Card]
/// * [Dialog]
/// * [FloatingActionButton]
/// * [Material]
...
...
This diff is collapsed.
Click to expand it.
packages/flutter/test/material/card_theme_test.dart
View file @
86c02e99
...
...
@@ -16,8 +16,9 @@ void main() {
});
testWidgets
(
'Passing no CardTheme returns defaults'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
MaterialApp
(
home:
Scaffold
(
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
(
useMaterial3:
true
),
home:
const
Scaffold
(
body:
Card
(),
),
));
...
...
@@ -27,10 +28,12 @@ void main() {
expect
(
material
.
clipBehavior
,
Clip
.
none
);
expect
(
material
.
color
,
Colors
.
white
);
expect
(
material
.
shadowColor
,
Colors
.
black
);
expect
(
material
.
surfaceTintColor
,
Colors
.
blue
);
// Default primary color
expect
(
material
.
elevation
,
1.0
);
expect
(
container
.
margin
,
const
EdgeInsets
.
all
(
4.0
));
expect
(
material
.
shape
,
const
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
4
.0
)),
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
12
.0
)),
));
});
...
...
@@ -50,6 +53,7 @@ void main() {
expect
(
material
.
clipBehavior
,
cardTheme
.
clipBehavior
);
expect
(
material
.
color
,
cardTheme
.
color
);
expect
(
material
.
shadowColor
,
cardTheme
.
shadowColor
);
expect
(
material
.
surfaceTintColor
,
cardTheme
.
surfaceTintColor
);
expect
(
material
.
elevation
,
cardTheme
.
elevation
);
expect
(
container
.
margin
,
cardTheme
.
margin
);
expect
(
material
.
shape
,
cardTheme
.
shape
);
...
...
@@ -129,7 +133,7 @@ void main() {
final
Key
painterKey
=
UniqueKey
();
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
(
cardTheme:
cardTheme
),
theme:
ThemeData
(
cardTheme:
cardTheme
,
useMaterial3:
true
),
home:
Scaffold
(
body:
RepaintBoundary
(
key:
painterKey
,
...
...
@@ -147,6 +151,62 @@ void main() {
matchesGoldenFile
(
'card_theme.custom_shape.png'
),
);
});
group
(
'Material 2'
,
()
{
// Tests that are only relevant for Material 2. Once ThemeData.useMaterial3
// is turned on by default, these tests can be removed.
testWidgets
(
'Passing no CardTheme returns defaults - M2'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
(
useMaterial3:
false
),
home:
const
Scaffold
(
body:
Card
(),
),
));
final
Container
container
=
_getCardContainer
(
tester
);
final
Material
material
=
_getCardMaterial
(
tester
);
expect
(
material
.
clipBehavior
,
Clip
.
none
);
expect
(
material
.
color
,
Colors
.
white
);
expect
(
material
.
shadowColor
,
Colors
.
black
);
expect
(
material
.
surfaceTintColor
,
null
);
expect
(
material
.
elevation
,
1.0
);
expect
(
container
.
margin
,
const
EdgeInsets
.
all
(
4.0
));
expect
(
material
.
shape
,
const
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
4.0
)),
));
});
testWidgets
(
'CardTheme customizes shape - M2'
,
(
WidgetTester
tester
)
async
{
const
CardTheme
cardTheme
=
CardTheme
(
color:
Colors
.
white
,
shape:
BeveledRectangleBorder
(
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
7
))),
elevation:
1.0
,
);
final
Key
painterKey
=
UniqueKey
();
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
(
cardTheme:
cardTheme
,
useMaterial3:
false
),
home:
Scaffold
(
body:
RepaintBoundary
(
key:
painterKey
,
child:
Center
(
child:
Card
(
child:
SizedBox
.
fromSize
(
size:
const
Size
(
200
,
300
)),
),
),
),
),
));
await
expectLater
(
find
.
byKey
(
painterKey
),
matchesGoldenFile
(
'card_theme.custom_shape_m2.png'
),
);
});
});
}
CardTheme
_cardTheme
(
)
{
...
...
@@ -154,6 +214,7 @@ CardTheme _cardTheme() {
clipBehavior:
Clip
.
antiAlias
,
color:
Colors
.
green
,
shadowColor:
Colors
.
red
,
surfaceTintColor:
Colors
.
purple
,
elevation:
6.0
,
margin:
EdgeInsets
.
all
(
7.0
),
shape:
RoundedRectangleBorder
(
...
...
This diff is collapsed.
Click to expand it.
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