Flutter centerSlice 详解

1,319 阅读1分钟

在container中使用

container(
  padding: EdgeInsetsDirectional.fromSTEB(10, 2, 10, 2),
  decoration: BoxDecoration(
    image: DecorationImage(
      centerSlice: Rect.fromLTRB(10, 5, 75, 10),
      image: AssetImage(
        'resource/xxxx.png',
      ),
    ),
  ),
  constraints: BoxConstraints(minWidth: 40, minHeight: 20, maxWidth: 200),
  child:Text("Near Expiry Near Expiry Near Expiry", maxLines: 1),
)

centerSlice核心代码解析

// outputSize为输出的宽高,在上面的使用情形中就是container的宽高,在上述文字长度下为[200,20]
Size outputSize = rect.size;
// inputSize为需要slice的图片大小,如果没有指定则为图片自身大小
// 在上述情形下未指定,图片自身大小为[80,20]
Size inputSize = Size(image.width.toDouble(), image.height.toDouble());
Offset? sliceBorder;
// 所以在设定了centerSlice的情形下会对slice区域做处理
// centerSlice为中间可以拉伸的区域 Rect.fromLTRB(10, 5, 75, 10) 分别是左上x,y和右下x,y
// 在上述情形下宽高分别为[65,5]
if (centerSlice != null) {
  // sliceBorder为图片大小 减去 中间可以拉伸的区域大小
  sliceBorder = inputSize / scale - centerSlice.size as Offset;
  // 再将原本的输入 输出size都除去不可拉伸的区域大小 
  // 此处重点:得出的size不可有负数,所以在未指定图片大小时候要注意图片原本的大小
  outputSize = outputSize - sliceBorder as Size;
  inputSize = inputSize - sliceBorder * scale as Size;
}
fit ??= centerSlice == null ? BoxFit.scaleDown : BoxFit.fill;
assert(centerSlice == null || (fit != BoxFit.none && fit != BoxFit.cover));
// 根据fit情况返回size
final FittedSizes fittedSizes = applyBoxFit(fit, inputSize / scale, outputSize);
final Size sourceSize = fittedSizes.source * scale;
Size destinationSize = fittedSizes.destination;
if (centerSlice != null) {
  // 再将size加上中间的拉伸区域
  // 此处得出的目标的size 需要和输入size相同
  outputSize += sliceBorder!;
  destinationSize += sliceBorder;
  // We don't have the ability to draw a subset of the image at the same time
  // as we apply a nine-patch stretch.
  assert(sourceSize == inputSize, 'centerSlice was used with a BoxFit that does not guarantee that the image is fully visible.');
}