mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
[Material] Theme data type for cards (#26796)
This change adds a CardTheme and tests for it. Golden is here:ec26eeebb4/packages/flutter/test/material/card_theme.custom_shape.png
From commit:ec26eeebb4 (diff-7564b206413654283ddc5cb59ecd64d4)
This commit is contained in:
parent
f8e5b9c4ef
commit
c362d8da07
@ -1 +1 @@
|
||||
24e9ab38cea4fd85f11ee5a3a491576037294bb9
|
||||
6fc7ec65d51116c3f83acb5251e57e779af2ebbb
|
||||
|
@ -29,6 +29,7 @@ export 'src/material/button.dart';
|
||||
export 'src/material/button_bar.dart';
|
||||
export 'src/material/button_theme.dart';
|
||||
export 'src/material/card.dart';
|
||||
export 'src/material/card_theme.dart';
|
||||
export 'src/material/checkbox.dart';
|
||||
export 'src/material/checkbox_list_tile.dart';
|
||||
export 'src/material/chip.dart';
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'card_theme.dart';
|
||||
import 'material.dart';
|
||||
import 'theme.dart';
|
||||
|
||||
@ -65,25 +66,25 @@ import 'theme.dart';
|
||||
class Card extends StatelessWidget {
|
||||
/// Creates a material design card.
|
||||
///
|
||||
/// The [clipBehavior] and [elevation] arguments must not be null.
|
||||
/// Additionally, the [elevation] must be non-negative.
|
||||
/// The [elevation] must be null or non-negative.
|
||||
const Card({
|
||||
Key key,
|
||||
this.color,
|
||||
this.elevation = 1.0,
|
||||
this.elevation,
|
||||
this.shape,
|
||||
this.margin = const EdgeInsets.all(4.0),
|
||||
this.clipBehavior = Clip.none,
|
||||
this.margin,
|
||||
this.clipBehavior,
|
||||
this.child,
|
||||
this.semanticContainer = true,
|
||||
}) : assert(elevation != null && elevation >= 0.0),
|
||||
}) : assert(elevation == null || elevation >= 0.0),
|
||||
super(key: key);
|
||||
|
||||
/// The card's background color.
|
||||
///
|
||||
/// Defines the card's [Material.color].
|
||||
///
|
||||
/// The default color is defined by the ambient [Theme]: [ThemeData.cardColor].
|
||||
/// If this property is null then [ThemeData.cardTheme.color] is used,
|
||||
/// if that's null then [ThemeData.cardColor] is used.
|
||||
final Color color;
|
||||
|
||||
/// The z-coordinate at which to place this card. This controls the size of
|
||||
@ -91,25 +92,30 @@ class Card extends StatelessWidget {
|
||||
///
|
||||
/// Defines the card's [Material.elevation].
|
||||
///
|
||||
/// The default elevation is 1.0. The value is always non-negative.
|
||||
/// If this property is null then [ThemeData.cardTheme.elevation] is used,
|
||||
/// if that's null, the default value is 1.0.
|
||||
final double elevation;
|
||||
|
||||
/// The shape of the card's [Material].
|
||||
///
|
||||
/// Defines the card's [Material.shape].
|
||||
///
|
||||
/// The default shape is a [RoundedRectangleBorder] with a circular corner
|
||||
/// radius of 4.0.
|
||||
/// If this property is null then [ThemeData.cardTheme.shape] is used.
|
||||
/// If that's null then the shape will be a [RoundedRectangleBorder] with a
|
||||
/// circular corner radius of 4.0.
|
||||
final ShapeBorder shape;
|
||||
|
||||
/// {@macro flutter.widgets.Clip}
|
||||
/// If this property is null then [ThemeData.cardTheme.clipBehavior] is used.
|
||||
/// If that's null then the behavior will be [Clip.none].
|
||||
final Clip clipBehavior;
|
||||
|
||||
/// The empty space that surrounds the card.
|
||||
///
|
||||
/// Defines the card's outer [Container.margin].
|
||||
///
|
||||
/// The default margin is 4.0 logical pixels on all sides:
|
||||
/// If this property is null then [ThemeData.cardTheme.margin] is used,
|
||||
/// if that's null, the default margin is 4.0 logical pixels on all sides:
|
||||
/// `EdgeInsets.all(4.0)`.
|
||||
final EdgeInsetsGeometry margin;
|
||||
|
||||
@ -131,20 +137,25 @@ class Card extends StatelessWidget {
|
||||
/// {@macro flutter.widgets.child}
|
||||
final Widget child;
|
||||
|
||||
static const double _defaultElevation = 1.0;
|
||||
static const Clip _defaultClipBehavior = Clip.none;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final CardTheme cardTheme = CardTheme.of(context);
|
||||
|
||||
return Semantics(
|
||||
container: semanticContainer,
|
||||
child: Container(
|
||||
margin: margin ?? const EdgeInsets.all(4.0),
|
||||
margin: margin ?? cardTheme.margin ?? const EdgeInsets.all(4.0),
|
||||
child: Material(
|
||||
type: MaterialType.card,
|
||||
color: color ?? Theme.of(context).cardColor,
|
||||
elevation: elevation,
|
||||
shape: shape ?? const RoundedRectangleBorder(
|
||||
color: color ?? cardTheme.color ?? Theme.of(context).cardColor,
|
||||
elevation: elevation ?? cardTheme.elevation ?? _defaultElevation,
|
||||
shape: shape ?? cardTheme.shape ?? const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(4.0)),
|
||||
),
|
||||
clipBehavior: clipBehavior,
|
||||
clipBehavior: clipBehavior ?? cardTheme.clipBehavior ?? _defaultClipBehavior,
|
||||
child: Semantics(
|
||||
explicitChildNodes: !semanticContainer,
|
||||
child: child,
|
||||
|
142
packages/flutter/lib/src/material/card_theme.dart
Normal file
142
packages/flutter/lib/src/material/card_theme.dart
Normal file
@ -0,0 +1,142 @@
|
||||
// Copyright 2019 The Chromium 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 'theme.dart';
|
||||
|
||||
/// Defines default property values for descendant [Card] widgets.
|
||||
///
|
||||
/// Descendant widgets obtain the current [CardTheme] object using
|
||||
/// `CardTheme.of(context)`. Instances of [CardTheme] can be
|
||||
/// customized with [CardTheme.copyWith].
|
||||
///
|
||||
/// Typically a [CardTheme] is specified as part of the overall [Theme]
|
||||
/// with [ThemeData.cardTheme].
|
||||
///
|
||||
/// All [CardTheme] properties are `null` by default. When null, the [Card]
|
||||
/// will use the values from [ThemeData] if they exist, otherwise it will
|
||||
/// provide its own defaults.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [ThemeData], which describes the overall theme information for the
|
||||
/// application.
|
||||
class CardTheme extends Diagnosticable {
|
||||
|
||||
/// Creates a theme that can be used for [ThemeData.cardTheme].
|
||||
///
|
||||
/// The [elevation] must be null or non-negative.
|
||||
const CardTheme({
|
||||
this.clipBehavior,
|
||||
this.color,
|
||||
this.elevation,
|
||||
this.margin,
|
||||
this.shape,
|
||||
}) : assert(elevation == null || elevation >= 0.0);
|
||||
|
||||
/// Default value for [Card.clipBehavior].
|
||||
///
|
||||
/// If null, [Card] uses [Clip.none].
|
||||
final Clip clipBehavior;
|
||||
|
||||
/// Default value for [Card.color].
|
||||
///
|
||||
/// If null, [Card] uses [ThemeData.cardColor].
|
||||
final Color color;
|
||||
|
||||
/// Default value for [Card.elevation].
|
||||
///
|
||||
/// If null, [Card] uses a default of 1.0.
|
||||
final double elevation;
|
||||
|
||||
/// Default value for [Card.margin].
|
||||
///
|
||||
/// If null, [Card] uses a default margin of 4.0 logical pixels on all sides:
|
||||
/// `EdgeInsets.all(4.0)`.
|
||||
final EdgeInsetsGeometry margin;
|
||||
|
||||
/// Default value for [Card.shape].
|
||||
///
|
||||
/// If null, [Card] then uses a [RoundedRectangleBorder] with a circular
|
||||
/// corner radius of 4.0.
|
||||
final ShapeBorder shape;
|
||||
|
||||
/// Creates a copy of this object with the given fields replaced with the
|
||||
/// new values.
|
||||
CardTheme copyWith({
|
||||
Clip clipBehavior,
|
||||
Color color,
|
||||
double elevation,
|
||||
EdgeInsetsGeometry margin,
|
||||
ShapeBorder shape,
|
||||
}) {
|
||||
return CardTheme(
|
||||
clipBehavior: clipBehavior ?? this.clipBehavior,
|
||||
color: color ?? this.color,
|
||||
elevation: elevation ?? this.elevation,
|
||||
margin: margin ?? this.margin,
|
||||
shape: shape ?? this.shape,
|
||||
);
|
||||
}
|
||||
|
||||
/// The [ThemeData.cardTheme] property of the ambient [Theme].
|
||||
static CardTheme of(BuildContext context) {
|
||||
return Theme.of(context).cardTheme;
|
||||
}
|
||||
|
||||
/// Linearly interpolate between two Card themes.
|
||||
///
|
||||
/// The argument `t` must not be null.
|
||||
///
|
||||
/// {@macro dart.ui.shadow.lerp}
|
||||
static CardTheme lerp(CardTheme a, CardTheme b, double t) {
|
||||
assert(t != null);
|
||||
return CardTheme(
|
||||
clipBehavior: t < 0.5 ? a?.clipBehavior : b?.clipBehavior,
|
||||
color: Color.lerp(a?.color, b?.color, t),
|
||||
elevation: lerpDouble(a?.elevation, b?.elevation, t),
|
||||
margin: EdgeInsetsGeometry.lerp(a?.margin, b?.margin, t),
|
||||
shape: ShapeBorder.lerp(a?.shape, b?.shape, t),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return hashValues(
|
||||
clipBehavior,
|
||||
color,
|
||||
elevation,
|
||||
margin,
|
||||
shape,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
if (identical(this, other))
|
||||
return true;
|
||||
if (other.runtimeType != runtimeType)
|
||||
return false;
|
||||
final CardTheme typedOther = other;
|
||||
return typedOther.clipBehavior == clipBehavior
|
||||
&& typedOther.color == color
|
||||
&& typedOther.elevation == elevation
|
||||
&& typedOther.margin == margin
|
||||
&& typedOther.shape == shape;
|
||||
}
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(DiagnosticsProperty<Clip>('clipBehavior', clipBehavior, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<Color>('color', color, 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));
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ import 'package:flutter/widgets.dart';
|
||||
import 'app_bar_theme.dart';
|
||||
import 'bottom_app_bar_theme.dart';
|
||||
import 'button_theme.dart';
|
||||
import 'card_theme.dart';
|
||||
import 'chip_theme.dart';
|
||||
import 'color_scheme.dart';
|
||||
import 'colors.dart';
|
||||
@ -149,6 +150,7 @@ class ThemeData extends Diagnosticable {
|
||||
IconThemeData accentIconTheme,
|
||||
SliderThemeData sliderTheme,
|
||||
TabBarTheme tabBarTheme,
|
||||
CardTheme cardTheme,
|
||||
ChipThemeData chipTheme,
|
||||
TargetPlatform platform,
|
||||
MaterialTapTargetSize materialTapTargetSize,
|
||||
@ -248,6 +250,7 @@ class ThemeData extends Diagnosticable {
|
||||
tabBarTheme ??= const TabBarTheme();
|
||||
appBarTheme ??= const AppBarTheme();
|
||||
bottomAppBarTheme ??= const BottomAppBarTheme();
|
||||
cardTheme ??= const CardTheme();
|
||||
chipTheme ??= ChipThemeData.fromDefaults(
|
||||
secondaryColor: primaryColor,
|
||||
brightness: brightness,
|
||||
@ -296,6 +299,7 @@ class ThemeData extends Diagnosticable {
|
||||
accentIconTheme: accentIconTheme,
|
||||
sliderTheme: sliderTheme,
|
||||
tabBarTheme: tabBarTheme,
|
||||
cardTheme: cardTheme,
|
||||
chipTheme: chipTheme,
|
||||
platform: platform,
|
||||
materialTapTargetSize: materialTapTargetSize,
|
||||
@ -359,6 +363,7 @@ class ThemeData extends Diagnosticable {
|
||||
@required this.accentIconTheme,
|
||||
@required this.sliderTheme,
|
||||
@required this.tabBarTheme,
|
||||
@required this.cardTheme,
|
||||
@required this.chipTheme,
|
||||
@required this.platform,
|
||||
@required this.materialTapTargetSize,
|
||||
@ -407,6 +412,7 @@ class ThemeData extends Diagnosticable {
|
||||
assert(accentIconTheme != null),
|
||||
assert(sliderTheme != null),
|
||||
assert(tabBarTheme != null),
|
||||
assert(cardTheme != null),
|
||||
assert(chipTheme != null),
|
||||
assert(platform != null),
|
||||
assert(materialTapTargetSize != null),
|
||||
@ -604,6 +610,11 @@ class ThemeData extends Diagnosticable {
|
||||
/// A theme for customizing the size, shape, and color of the tab bar indicator.
|
||||
final TabBarTheme tabBarTheme;
|
||||
|
||||
/// The colors and styles used to render [Card].
|
||||
///
|
||||
/// This is the value returned from [CardTheme.of].
|
||||
final CardTheme cardTheme;
|
||||
|
||||
/// The colors and styles used to render [Chip], [
|
||||
///
|
||||
/// This is the value returned from [ChipTheme.of].
|
||||
@ -708,6 +719,7 @@ class ThemeData extends Diagnosticable {
|
||||
IconThemeData accentIconTheme,
|
||||
SliderThemeData sliderTheme,
|
||||
TabBarTheme tabBarTheme,
|
||||
CardTheme cardTheme,
|
||||
ChipThemeData chipTheme,
|
||||
TargetPlatform platform,
|
||||
MaterialTapTargetSize materialTapTargetSize,
|
||||
@ -760,6 +772,7 @@ class ThemeData extends Diagnosticable {
|
||||
accentIconTheme: accentIconTheme ?? this.accentIconTheme,
|
||||
sliderTheme: sliderTheme ?? this.sliderTheme,
|
||||
tabBarTheme: tabBarTheme ?? this.tabBarTheme,
|
||||
cardTheme: cardTheme ?? this.cardTheme,
|
||||
chipTheme: chipTheme ?? this.chipTheme,
|
||||
platform: platform ?? this.platform,
|
||||
materialTapTargetSize: materialTapTargetSize ?? this.materialTapTargetSize,
|
||||
@ -890,6 +903,7 @@ class ThemeData extends Diagnosticable {
|
||||
accentIconTheme: IconThemeData.lerp(a.accentIconTheme, b.accentIconTheme, t),
|
||||
sliderTheme: SliderThemeData.lerp(a.sliderTheme, b.sliderTheme, t),
|
||||
tabBarTheme: TabBarTheme.lerp(a.tabBarTheme, b.tabBarTheme, t),
|
||||
cardTheme: CardTheme.lerp(a.cardTheme, b.cardTheme, t),
|
||||
chipTheme: ChipThemeData.lerp(a.chipTheme, b.chipTheme, t),
|
||||
platform: t < 0.5 ? a.platform : b.platform,
|
||||
materialTapTargetSize: t < 0.5 ? a.materialTapTargetSize : b.materialTapTargetSize,
|
||||
@ -950,6 +964,7 @@ class ThemeData extends Diagnosticable {
|
||||
(otherData.accentIconTheme == accentIconTheme) &&
|
||||
(otherData.sliderTheme == sliderTheme) &&
|
||||
(otherData.tabBarTheme == tabBarTheme) &&
|
||||
(otherData.cardTheme == cardTheme) &&
|
||||
(otherData.chipTheme == chipTheme) &&
|
||||
(otherData.platform == platform) &&
|
||||
(otherData.materialTapTargetSize == materialTapTargetSize) &&
|
||||
@ -1010,6 +1025,7 @@ class ThemeData extends Diagnosticable {
|
||||
sliderTheme,
|
||||
hashValues(
|
||||
tabBarTheme,
|
||||
cardTheme,
|
||||
chipTheme,
|
||||
platform,
|
||||
materialTapTargetSize,
|
||||
@ -1066,6 +1082,7 @@ class ThemeData extends Diagnosticable {
|
||||
properties.add(DiagnosticsProperty<IconThemeData>('accentIconTheme', accentIconTheme));
|
||||
properties.add(DiagnosticsProperty<SliderThemeData>('sliderTheme', sliderTheme));
|
||||
properties.add(DiagnosticsProperty<TabBarTheme>('tabBarTheme', tabBarTheme));
|
||||
properties.add(DiagnosticsProperty<CardTheme>('cardTheme', cardTheme));
|
||||
properties.add(DiagnosticsProperty<ChipThemeData>('chipTheme', chipTheme));
|
||||
properties.add(DiagnosticsProperty<MaterialTapTargetSize>('materialTapTargetSize', materialTapTargetSize));
|
||||
properties.add(DiagnosticsProperty<PageTransitionsTheme>('pageTransitionsTheme', pageTransitionsTheme));
|
||||
|
182
packages/flutter/test/material/card_theme_test.dart
Normal file
182
packages/flutter/test/material/card_theme_test.dart
Normal file
@ -0,0 +1,182 @@
|
||||
// Copyright 2019 The Chromium 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:io' show Platform;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
test('CardTheme copyWith, ==, hashCode basics', () {
|
||||
expect(const CardTheme(), const CardTheme().copyWith());
|
||||
expect(const CardTheme().hashCode, const CardTheme().copyWith().hashCode);
|
||||
});
|
||||
|
||||
testWidgets('Passing no CardTheme returns defaults', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(const MaterialApp(
|
||||
home: 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.elevation, 1.0);
|
||||
expect(container.margin, const EdgeInsets.all(4.0));
|
||||
expect(material.shape, const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(4.0)),
|
||||
));
|
||||
});
|
||||
|
||||
testWidgets('Card uses values from CardTheme', (WidgetTester tester) async {
|
||||
final CardTheme cardTheme = _cardTheme();
|
||||
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
theme: ThemeData(cardTheme: cardTheme),
|
||||
home: const Scaffold(
|
||||
body: Card()
|
||||
),
|
||||
));
|
||||
|
||||
final Container container = _getCardContainer(tester);
|
||||
final Material material = _getCardMaterial(tester);
|
||||
|
||||
expect(material.clipBehavior, cardTheme.clipBehavior);
|
||||
expect(material.color, cardTheme.color);
|
||||
expect(material.elevation, cardTheme.elevation);
|
||||
expect(container.margin, cardTheme.margin);
|
||||
expect(material.shape, cardTheme.shape);
|
||||
});
|
||||
|
||||
testWidgets('Card widget properties take priority over theme', (WidgetTester tester) async {
|
||||
const Clip clip = Clip.hardEdge;
|
||||
const Color color = Colors.orange;
|
||||
const double elevation = 7.0;
|
||||
const EdgeInsets margin = EdgeInsets.all(3.0);
|
||||
const ShapeBorder shape = RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(9.0)),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
theme: _themeData().copyWith(cardTheme: _cardTheme()),
|
||||
home: const Scaffold(
|
||||
body: Card(
|
||||
clipBehavior: clip,
|
||||
color: color,
|
||||
elevation: elevation,
|
||||
margin: margin,
|
||||
shape: shape,
|
||||
)
|
||||
),
|
||||
));
|
||||
|
||||
final Container container = _getCardContainer(tester);
|
||||
final Material material = _getCardMaterial(tester);
|
||||
|
||||
expect(material.clipBehavior, clip);
|
||||
expect(material.color, color);
|
||||
expect(material.elevation, elevation);
|
||||
expect(container.margin, margin);
|
||||
expect(material.shape, shape);
|
||||
});
|
||||
|
||||
testWidgets('CardTheme properties take priority over ThemeData properties', (WidgetTester tester) async {
|
||||
final CardTheme cardTheme = _cardTheme();
|
||||
final ThemeData themeData = _themeData().copyWith(cardTheme: cardTheme);
|
||||
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
theme: themeData,
|
||||
home: const Scaffold(
|
||||
body: Card()
|
||||
),
|
||||
));
|
||||
|
||||
final Material material = _getCardMaterial(tester);
|
||||
expect(material.color, cardTheme.color);
|
||||
});
|
||||
|
||||
testWidgets('ThemeData properties are used when no CardTheme is set', (WidgetTester tester) async {
|
||||
final ThemeData themeData = _themeData();
|
||||
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
theme: themeData,
|
||||
home: const Scaffold(
|
||||
body: Card()
|
||||
),
|
||||
));
|
||||
|
||||
final Material material = _getCardMaterial(tester);
|
||||
expect(material.color, themeData.cardColor);
|
||||
});
|
||||
|
||||
testWidgets('CardTheme customizes shape', (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),
|
||||
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.png'),
|
||||
skip: !Platform.isLinux,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
CardTheme _cardTheme() {
|
||||
return const CardTheme(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
color: Colors.green,
|
||||
elevation: 6.0,
|
||||
margin: EdgeInsets.all(7.0),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(5.0)),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
ThemeData _themeData() {
|
||||
return ThemeData(
|
||||
cardColor: Colors.pink,
|
||||
);
|
||||
}
|
||||
|
||||
Material _getCardMaterial(WidgetTester tester) {
|
||||
return tester.widget<Material>(
|
||||
find.descendant(
|
||||
of: find.byType(Card),
|
||||
matching: find.byType(Material),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Container _getCardContainer(WidgetTester tester) {
|
||||
return tester.widget<Container>(
|
||||
find.descendant(
|
||||
of: find.byType(Card),
|
||||
matching: find.byType(Container),
|
||||
),
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user