BoxDecoration 解析

320 阅读3分钟

参考

Flutter 想要装饰组件的背景色,背景图,边框,圆角,阴影使用 Decoration 的子类去实现。

Option + Command + B 查看 Decoration 子类

image.png

本篇文章主要对 BoxDecoration 用法做记录。

const BoxDecoration({
  this.color, // 背景色
  this.image, // 背景图片 
  this.border, // 边框的颜色和宽度
  this.borderRadius, // 圆角
  this.boxShadow, // 阴影
  this.gradient, // 渐变色
  this.backgroundBlendMode, // 混合Mode
  this.shape = BoxShape.rectangle, // 形状,默认矩形
})

背景颜色 color

Center(
  child: Container(
    width: 100,
    height: 100,
    alignment: Alignment.center,
    child: const Text('切圆角', style: TextStyle(color: Colors.white, fontSize: 20),),
    decoration: const BoxDecoration(
      color: Colors.green,
    ),
  ),
),

image.png

背景图 image

背景图类型是 DecorationImage

image.png

DecorationImage 的 image 类型是 ImageProvider,且ImageProvider是抽象类

查看ImageProvider的子类

image.png

加载网络图片

Center(
  child: Container(
    width: 100,
    height: 100,
    alignment: Alignment.center,
    child: const Text(
      '切圆角',
      style: TextStyle(color: Colors.white, fontSize: 20),
    ),
    decoration: const BoxDecoration(
      color: Colors.green,
      image: DecorationImage(
          image: NetworkImage(
              'https://img1.baidu.com/it/u=663166337,1408723612&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281'),
          fit: BoxFit.cover),
    ),
  ),
),

image.png

本地图片

Center(
  child: Container(
    width: 300,
    height: 300,
    alignment: Alignment.center,
    child: const Text(
      '背景图-本地图片',
      style: TextStyle(color: Colors.white, fontSize: 20),
    ),
    decoration: const BoxDecoration(
      color: Colors.green,
      image: DecorationImage(
          image: AssetImage('asset/images/maidi.png'),
          fit: BoxFit.cover),
    ),
  ),
),

image.png

border 边框

final BoxBorder? border;

又是一个抽象类

abstract class BoxBorder extends ShapeBorder {

image.png

all

image.png

border: Border.all(color: Colors.yellow, width: 5),
border: Border.fromBorderSide(BorderSide(color: Colors.yellow, width: 10,)),

image.png

水平、垂直、单边 设置

水平、垂直

image.png

border: Border.symmetric(vertical: BorderSide(color: Colors.yellow, width: 5,)),

image.png

border: Border(
  top: BorderSide(color: Colors.yellow, width: 5,),
  right: BorderSide(color: Colors.purple, width: 5,),
  bottom: BorderSide(color: Colors.blue, width: 5,),
  left: BorderSide(color: Colors.red, width: 5,),
),

image.png

圆角 borderRadius

circular、

Center(
  child: Container(
    width: 300,
    height: 300,
    alignment: Alignment.center,
    child: const Text(
      '背景图-网络',
      style: TextStyle(color: Colors.white, fontSize: 20),
    ),
    decoration:  BoxDecoration(
      color: Colors.green,
      image: const DecorationImage(
          image: NetworkImage(
              'https://img1.baidu.com/it/u=663166337,1408723612&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281'),
          fit: BoxFit.cover),
      border: Border.all(width: 5, color: Colors.pink),
      borderRadius: BorderRadius.circular(150),
    ),
  ),
),

image.png

all、vertical、horizontal、only

borderRadius: BorderRadius.all(Radius.circular(150)),
borderRadius: BorderRadius.vertical(top: Radius.circular(150)),

image.png

borderRadius: BorderRadius.horizontal(right: Radius.circular(150)),

image.png

borderRadius: BorderRadius.only(bottomRight: Radius.circular(150)),

image.png

boxShadow 阴影

final List<BoxShadow>? boxShadow;

最简单的阴影

boxShadow: const [
  BoxShadow(
    color: Colors.yellow,
    blurRadius: 15,
  ),
]),

image.png

const BoxShadow({
  Color color = const Color(0xFF000000),// 阴影颜色
  Offset offset = Offset.zero,// 阴影的偏移量
  double blurRadius = 0.0,// 阴影模糊度的大小,值越大阴影范围越大,但也更透明
  this.spreadRadius = 0.0,// 阴影的大小
  this.blurStyle = BlurStyle.normal,// 阴影的类型
}) : super(color: color, offset: offset, blurRadius: blurRadius);

BlurStyle

enum BlurStyle {
  // These mirror SkBlurStyle and must be kept in sync.

  /// Fuzzy inside and outside. This is useful for painting shadows that are
  /// offset from the shape that ostensibly is casting the shadow.
  normal,

  /// Solid inside, fuzzy outside. This corresponds to drawing the shape, and
  /// additionally drawing the blur. This can make objects appear brighter,
  /// maybe even as if they were fluorescent.
  solid,

  /// Nothing inside, fuzzy outside. This is useful for painting shadows for
  /// partially transparent shapes, when they are painted separately but without
  /// an offset, so that the shadow doesn't paint below the shape.
  outer,

  /// Fuzzy inside, nothing outside. This can make shapes appear to be lit from
  /// within.
  inner,
}
  • solid:内部亮,外部模糊

image.png

  • outer:

image.png

  • inner

image.png

  • normal

image.png

offset

offset: Offset(10, 0),

image.png

offset: Offset(-10, 0),

image.png

offset: Offset(0, 30),

image.png

gradient 渐变色

final Gradient? gradient;

image.png

LinearGradient 线性渐变

const LinearGradient({
  this.begin = Alignment.centerLeft,// 渐变开始位置
  this.end = Alignment.centerRight,// 渐变结束位置
  required List<Color> colors,// 渐变颜色
  List<double>? stops,// 颜色值梯度,取值范围[0,1],长度要和 colors 的长度一样
  this.tileMode = TileMode.clamp,
  GradientTransform? transform,
}) : assert(begin != null),
     assert(end != null),
     assert(tileMode != null),
     super(colors: colors, stops: stops, transform: transform);
gradient: const LinearGradient(
  colors: [Colors.black, Colors.white],
  begin: Alignment.topCenter,
  end: Alignment.bottomCenter,
)),

image.png

gradient: const LinearGradient(
  colors: [Colors.black, Colors.white, Colors.red],
  stops: [0, 0.5, 1],
)),

stops和 colors对应

image.png

SweepGradient 扫描渐变

gradient: const SweepGradient(
  colors: [Colors.black, Colors.white],
),

image.png

RadialGradient 环形渐变

gradient: RadialGradient(colors: [Colors.black, Colors.white]),

image.png

shape

enum BoxShape {
  /// An axis-aligned, 2D rectangle. May have rounded corners (described by a
  /// [BorderRadius]). The edges of the rectangle will match the edges of the box
  /// into which the [Border] or [BoxDecoration] is painted.
  ///
  /// See also:
  ///
  ///  * [RoundedRectangleBorder], the equivalent [ShapeBorder].
  rectangle,

  /// A circle centered in the middle of the box into which the [Border] or
  /// [BoxDecoration] is painted. The diameter of the circle is the shortest
  /// dimension of the box, either the width or the height, such that the circle
  /// touches the edges of the box.
  ///
  /// See also:
  ///
  ///  * [CircleBorder], the equivalent [ShapeBorder].
  circle,

  // Don't add more, instead create a new ShapeBorder.
}
  • 当设置 shape 为圆形时,不能再对 borderRadius 属性进行操作,否则会报错。
  • 虽然可以设置 shape 的值为圆形,但这并不是说可以用这个参数来裁剪组件,因为这会以性能为代价,如果需要裁剪,可以用组件 ClipRect、ClipRRect,、ClipPath 。

扩展 ShapeDecoration、UnderlineTabIndicator

decoration: ShapeDecoration(
  shape: Border.all(color: Colors.yellow, width: 5),
  image: const DecorationImage(
      image: AssetImage('asset/images/maidi.png'),
      fit: BoxFit.cover),
),

image.png

其实还有其他的 Decoration 子类,慢慢摸索吧。

UnderlineTabIndicator,标签指示器 标签指示器,这个可以认为是添加下划线的,如 TabBar 底部的指示器,参数就两个,构造函数如下

Center(
  child: Container(
    width: 300,
    height: 300,
    alignment: Alignment.center,
    child: const Text(
      '背景图-本地图片-Shape',
      style: TextStyle(color: Colors.black, fontSize: 20),
    ),
    decoration: const UnderlineTabIndicator(
      borderSide: BorderSide(color: Colors.purple, width: 5.0),
      insets: EdgeInsets.zero,
    ),
  ),
),

image.png

image.png

image.png