Border

作者: NetWork小贱 | 来源:发表于2022-03-16 10:11 被阅读0次

    一、解读

    // 组件的边框,继承于抽象类 BoxBorder
    class Border extends BoxBorder {
      // 创建一个边框,参数不能为空
      const Border({
        this.top = BorderSide.none, // BorderSide.none 是无边框
        this.right = BorderSide.none,
        this.bottom = BorderSide.none,
        this.left = BorderSide.none,
      }) : assert(top != null), // 参数不能为空的断言
           assert(right != null),
           assert(bottom != null),
           assert(left != null);
    
      // 创建和一个边相同的边
      const Border.fromBorderSide(BorderSide side)
          : assert(side != null),
            top = side,
            right = side,
            bottom = side,
            left = side;
    
      /// 创建水平 (顶部和底部)和垂直(左边和右边)的边 
      const Border.symmetric({
        BorderSide vertical = BorderSide.none, // 垂直
        BorderSide horizontal = BorderSide.none, // 水平
      }) : assert(vertical != null),
           assert(horizontal != null),
           left = vertical,
           top = horizontal,
           right = vertical,
           bottom = horizontal;
    
      /// 所有颜色和宽度都相同的边框
      /// 调用 fromBorderSide 来实现
      factory Border.all({
        Color color = const Color(0xFF000000),
        double width = 1.0,
        BorderStyle style = BorderStyle.solid,// 边框的样式,实线
      }) {
        final BorderSide side = BorderSide(color: color, width: width, style: style);
        return Border.fromBorderSide(side);
      }
    
      ///  创建一个边框,有两个边框相加
      static Border merge(Border a, Border b) {
        assert(a != null);
        assert(b != null);
        assert(BorderSide.canMerge(a.top, b.top)); // canMerge 检查是否可以合并,判断的条件是边框的样式和颜色是否相同
        assert(BorderSide.canMerge(a.right, b.right));
        assert(BorderSide.canMerge(a.bottom, b.bottom));
        assert(BorderSide.canMerge(a.left, b.left));
        return Border(
          top: BorderSide.merge(a.top, b.top),
          right: BorderSide.merge(a.right, b.right),
          bottom: BorderSide.merge(a.bottom, b.bottom),
          left: BorderSide.merge(a.left, b.left),
        );
      }
    
      // 顶部边框
      @override
      final BorderSide top;
    
      // 右边边框
      final BorderSide right;
      
      // 底部边框
      @override
      final BorderSide bottom;
    
      // 左边边框
      final BorderSide left;
      
      // 获取尺度
      @override
      EdgeInsetsGeometry get dimensions {
        return EdgeInsets.fromLTRB(left.width, top.width, right.width, bottom.width);
      }
      
      // 判断边框的颜色、粗细、样式是否一致
      @override
      bool get isUniform => _colorIsUniform && _widthIsUniform && _styleIsUniform;
      
      // 判断所有边框颜色是否统一
      bool get _colorIsUniform {
        final Color topColor = top.color;
        return right.color == topColor && bottom.color == topColor && left.color == topColor;
      }
      
      // 判断边框粗细是否一致
      bool get _widthIsUniform {
        final double topWidth = top.width;
        return right.width == topWidth && bottom.width == topWidth && left.width == topWidth;
      }
      
      // 判断边框样式是否一致
      bool get _styleIsUniform {
        final BorderStyle topStyle = top.style;
        return right.style == topStyle && bottom.style == topStyle && left.style == topStyle;
      }
      
      //  重写 BoxBorder 的 add 方法,增加边框的数值
      @override
      Border? add(ShapeBorder other, { bool reversed = false }) {
        if (other is Border && // is 是类型判断
            BorderSide.canMerge(top, other.top) &&
            BorderSide.canMerge(right, other.right) &&
            BorderSide.canMerge(bottom, other.bottom) &&
            BorderSide.canMerge(left, other.left)) {
          return Border.merge(this, other);
        }
        return null;
      }
      
      // 重写 BoxBorder 的父类 ShapeBorder 的 scale 方法,比例增加边框的粗细
      @override 
      Border scale(double t) {
        return Border(
          top: top.scale(t),
          right: right.scale(t),
          bottom: bottom.scale(t),
          left: left.scale(t),
        );
      }
      
      // 
      @override
      ShapeBorder? lerpFrom(ShapeBorder? a, double t) { 
        if (a is Border)
          return Border.lerp(a, this, t);
        return super.lerpFrom(a, t);
      }
    
      @override
      ShapeBorder? lerpTo(ShapeBorder? b, double t) {
        if (b is Border)
          return Border.lerp(this, b, t);
        return super.lerpTo(b, t);
      }
    
      /// 生成两个边框之间的线性边框
      /// 注意: t ==0 ,a 生效;t == 1, b 生效
      /// 最后,边框的宽度为  a * (1.0 - t) + b * t
      static Border? lerp(Border? a, Border? b, double t) {
        assert(t != null);
        if (a == null && b == null)
          return null;
        if (a == null)
          return b!.scale(t);
        if (b == null)
          return a.scale(1.0 - t);
        return Border(
          top: BorderSide.lerp(a.top, b.top, t),
          right: BorderSide.lerp(a.right, b.right, t),
          bottom: BorderSide.lerp(a.bottom, b.bottom, t),
          left: BorderSide.lerp(a.left, b.left, t),
        );
      }
    
      /// 在给定大小画布上绘制边框
      @override
      void paint(
        Canvas canvas,
        Rect rect, {
        TextDirection? textDirection, // 文字方向
        BoxShape shape = BoxShape.rectangle, // 形状
        BorderRadius? borderRadius, // 圆角
      }) {
        // 判断是否统一
        if (isUniform) {
          // 判断边框样式
          switch (top.style) {
            // 无样式,不绘制
            case BorderStyle.none:
              return;
            // 实线
            case BorderStyle.solid:
              // 组件的样式
              switch (shape) {
                // 圆弧型
                case BoxShape.circle:
                  assert(borderRadius == null, 'A borderRadius can only be given for rectangular boxes.');
                  BoxBorder._paintUniformBorderWithCircle(canvas, rect, top);
                  break;
                // 长方型
                case BoxShape
                  BoxBorder._paintUniformBorderWithRectangle(canvas, rect, top);
                  break;
              }
              return;
          }
        }
    
        assert(() {
          // 判断圆角
          if (borderRadius != null) {
            throw FlutterError.fromParts(<DiagnosticsNode>[
              ErrorSummary('A borderRadius can only be given for a uniform Border.'),
              ErrorDescription('The following is not uniform:'),
              if (!_colorIsUniform) ErrorDescription('BorderSide.color'),
              if (!_widthIsUniform) ErrorDescription('BorderSide.width'),
              if (!_styleIsUniform) ErrorDescription('BorderSide.style'),
            ]);
          }
          return true;
        }());
        assert(() {
          // 判断形状
          if (shape != BoxShape.rectangle) {
            throw FlutterError.fromParts(<DiagnosticsNode>[
              ErrorSummary('A Border can only be drawn as a circle if it is uniform'),
              ErrorDescription('The following is not uniform:'),
              if (!_colorIsUniform) ErrorDescription('BorderSide.color'),
              if (!_widthIsUniform) ErrorDescription('BorderSide.width'),
     
     // 边框的运算
      @override
      bool operator ==(Object other) {
        if (identical(this, other))
          return true;
        if (other.runtimeType != runtimeType)
          return false;
        return other is Border
            && other.top == top
            && other.right == right
            && other.bottom == bottom
            && other.left == left;
      }
      
      // 获取组件的哈希吗
      @override
      int get hashCode => hashValues(top, right, bottom, left);
    
    //  获取对该类的描述
    @override
      String toString() {
        if (isUniform)
          return '${objectRuntimeType(this, 'Border')}.all($top)';
        final List<String> arguments = <String>[
          if (top != BorderSide.none) 'top: $top',
          if (right != BorderSide.none) 'right: $right',
          if (bottom != BorderSide.none) 'bottom: $bottom',
          if (left != BorderSide.none) 'left: $left',
        ];
        return '${objectRuntimeType(this, 'Border')}(${arguments.join(", ")})';
      }
    }
    

    二、总结

    • 继承于 Border ,而 Border 继承于 BoxBorder .
    • 边框的快捷创建方法以及运算

    三、实例

    // 颜色、边框样式、粗细
    Border.all(
      color: Colors.green,
      width: 3,
      style: BorderStyle.solid,
    )
    
    // 从一边生成相同的多边
    Border.fromBorderSide(
      BorderSide(
        color: Colors.green,
        width: 3,
        style: BorderStyle.solid,
      ),
    )
    
    // 合并两个边框,生成新的边框
    // 注意:合并的两个边框的颜色和样式要一样
    Border.merge(Border.all(width: 2), Border.all(width: 3))
    
    // 设置水平边框和垂直边框
    Border.symmetric(
      vertical: BorderSide(
        color: Colors.green,
        width: 5,
      ),
      horizontal: BorderSide(
        color: Colors.black,
        width: 5,
      ),
    )
    
    // 判断两个边框是否相等
    Border(top: BorderSide(color: Colors.green)) == Border(top: BorderSide(color: Colors.red))
    
    // 生成两个边框的线性插值边框
    Border.lerp(
      Border(top: BorderSide(color: Colors.green, width: 10)),
      Border(top: BorderSide(color: Colors.purple, width: 2)),
      2,
    )
    

    相关文章

      网友评论

        本文标题:Border

        本文链接:https://www.haomeiwen.com/subject/ukxydrtx.html