一、源码解读
/// 生成一个圆角卡片并带有阴影
/// 常用于,电话、地理位置、卡片等
class Card extends StatelessWidget {
const Card({
Key? key,
this.color,
this.shadowColor,
this.elevation,
this.shape,
this.borderOnForeground = true,
this.margin,
this.clipBehavior,
this.child,
this.semanticContainer = true,
}) : assert(elevation == null || elevation >= 0.0),
assert(borderOnForeground != null),
super(key: key);
/// 卡片背景色
final Color? color;
/// 卡片的阴影色
final Color? shadowColor;
/// Z 坐标控制阴影大小
final double? elevation;
/// 设置卡片的样式,默认圆角为 4
/// RoundedRectangleBorder 圆角矩形的矩形边框
/// BeveledRectangleBorder 有倾斜面的矩形边框
/// ContinuousRectangleBorder 连续的矩形边框
/// CircleBorder 圆角边框
final ShapeBorder? shape;
/// 设置边框在子组件的位置
/// true: 边框在前;否则反之
final bool borderOnForeground;
/// 剪辑小部件的方法
/// none: 没有裁剪
/// hardEdge: 裁剪,但不抗锯齿
/// antiAlias: 带抗锯齿裁剪
/// antiAliasWithSaveLayer: 在剪辑之后立即使用抗锯齿和 saveLayer 剪辑
final Clip? clipBehavior;
/// 卡片周围的空白区域,默认 4 .
final EdgeInsetsGeometry? margin;
/// 将所有的语义标签汇聚到此小部件
final bool semanticContainer;
/// 卡片组件的子组件
final Widget? child;
/// 控制阴影 z 轴大小,参数默认值
static const double _defaultElevation = 1.0;
@override
Widget build(BuildContext context) {
/// 获取主题
final ThemeData theme = Theme.of(context);
/// 获取卡片主题
final CardTheme cardTheme = CardTheme.of(context);
/// 创建语义注释
return Semantics(
// 是否集合语义标签
container: semanticContainer,
child: Container(
// 卡片外空白,如果 margin 没有值,则使用卡片主题的 margin ,如果卡片主题的 margin 也不存在,则默认为 4 的边距
margin: margin ?? cardTheme.margin ?? const EdgeInsets.all(4.0),
child: Material(
// 卡片类型
type: MaterialType.card,
// 阴影颜色,如果没有,则使用卡片主题的阴影颜色;如果卡片主题阴影颜色也没有,则使用系统主题阴影色
shadowColor: shadowColor ?? cardTheme.shadowColor ?? theme.shadowColor,
// 背景颜色,如果没有,则使用卡片主题的背景颜色;如果卡片主题背景颜色也没有,则使用系统主题背景色
color: color ?? cardTheme.color ?? theme.cardColor,
// 卡片 Z 轴阴影大小
elevation: elevation ?? cardTheme.elevation ?? _defaultElevation,
// 卡片的形状,如果没设置,就取卡片主题的形状;如果卡片主题形状也没设置,则使用默认为 4 的圆角矩形形状
shape: shape ?? cardTheme.shape ?? const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
// 控制形状是在子组件前还是在后,默认在前(true)
borderOnForeground: borderOnForeground,
// 卡片的裁剪模式,如果没有设置,就取卡片主题的裁剪模式;如果卡片主题裁剪样式没有设置,则使用不做任何裁剪
clipBehavior: clipBehavior ?? cardTheme.clipBehavior ?? Clip.none,
child: Semantics(
/// 是否允许该widget的后代向该widget注解的[SemanticsNode]添加语义信息。
explicitChildNodes: !semanticContainer,
child: child,
),
),
),
);
}
}
二、总结
- Card 是继承于 StatelessWidget
- Card 样式设置,首先获取当前的设置,如果当前没有设置,则获取卡片主题的样式;如果卡片主题的样式也没设置,则使用默认的或者系统的样式
- Card的层级是: Semantics -> Container -> Material -> Semantics -> child
三、实例
Card(
elevation: 1,
shape: RoundedRectangleBorder(
side: BorderSide(
color: Colors.green,
width: 3,
),
),
borderOnForeground: false,
clipBehavior: Clip.antiAlias,
margin: EdgeInsets.all(20),
shadowColor: Colors.green,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Text('Card 测试'),
),
)