Flutter-----LabelView---文字自适应其大小

最近再写FlutterDemo,需要用到一个labelview,网上找了找,没有合适的,就对网上一位大神写的demoLabelDemo改了下,就有l了这么一个文字自适应大小的labelViewGithub

先看下效果图

说白了就是对CustomPainter 和对画布的操作(旋转和平移)

  • labelAlignment: LabelAlignment.leftTop,
    LabelAlignment.leftTop
  • labelAlignment: LabelAlignment.leftBottom
    leftBottom
  • labelAlignment: LabelAlignment.rightTop
     LabelAlignment.rightTop
  • LabelAlignment.rightBottom
    LabelAlignment.rightBottom
使用
@override
  Widget build(BuildContext context) {
    return LabelViewDecoration(
        size: Size(80.0, 80.0),//label size
        labelColor: Colors.red,//label color
        labelAlignment: LabelAlignment.leftTop,//The orientation of the label attached to the widget
        useAngle: true,//
        labelText: "Hot",
        labelTextColor: Colors.white,
        child: _builderItem()//Label attached widget
    );
  }
关键代码

其中最重要的就是对形状和文字的绘制,形状的绘制采用Path,就是以size尺寸绘制一个三角形,根据三角形的大小测量文字的大小,然后旋转画布的角度,然后平移。画布默认旋转中心为坐标轴原点,而且貌似不能更改,至少我没找到,所以需要旋转后再平移,对canvas的位置操作需要倒着写,所以实际代码是先写translate,再写rotate。其余的就是数学计算了。

@override
  void paint(Canvas canvas, Size size) {
    var drawSize = size.height > size.width ? size.width / 2 : size.height / 2;
    Path path = new Path();
    switch (labelAlignment) {
      case LabelAlignment.leftTop:
        if (!useAngle) {
          path.moveTo(drawSize / 2, 0);
          path.lineTo(0, drawSize / 2);
        }
        path.lineTo(0, drawSize);
        path.lineTo(drawSize, 0);
        break;
      case LabelAlignment.leftBottom:
        path.moveTo(0, size.height - drawSize);

        if (useAngle) {
          path.lineTo(drawSize, size.height);
          path.lineTo(0, size.height);
        } else {
          path.lineTo(0, size.height - drawSize / 2);
          path.lineTo(drawSize / 2, size.height);
          path.lineTo(drawSize, size.height);
        }
        break;
      case LabelAlignment.rightTop:
        path.moveTo(size.width - drawSize, 0);
        if (useAngle) {
          path.lineTo(size.width, 0);
        } else {
          path.lineTo(size.width - drawSize / 2, 0);
          path.lineTo(size.width, drawSize / 2);
        }

        path.lineTo(size.width, drawSize);
        break;
      case LabelAlignment.rightBottom:
        if (useAngle) {
          path.moveTo(size.width, size.height);

          path.lineTo(size.width - drawSize, size.height);
          path.lineTo(size.width, size.height - drawSize);
        } else {
          path.moveTo(size.width - drawSize, size.height);
          path.lineTo(size.width - drawSize / 2, size.height);
          path.lineTo(size.width, size.height - drawSize / 2);
          path.lineTo(size.width, size.height - drawSize);
        }
        break;
      default:
        if (!useAngle) {
          path.moveTo(drawSize / 2, 0);
          path.lineTo(0, drawSize / 2);
        }
        path.lineTo(0, drawSize);
        path.lineTo(drawSize, 0);
        break;
    }
    path.close();
    canvas.drawPath(path, _paint);

    canvas.save();

    //计算字体size
    double minWidth = 0;
    switch(labelAlignment){
      case LabelAlignment.leftTop:
      //旋转画布并平移  代码上是先做平移在旋转操作,反着来
        canvas.translate(0.0, drawSize);
        canvas.rotate(angleToRadian(-45.0));
        if (useAngle) {
          double x = ((drawSize / 2) * (drawSize / 2) / 2);
          minWidth = sqrt(x);
          //方法一:使用drawParagraph绘制文字,Paragraph是ui包内的
          Paragraph paragraph = buildParagraph(labelText, minWidth, drawSize);
          canvas.drawParagraph(paragraph, Offset(0, -drawSize / 2));
        } else {
          double x = ((drawSize / 3) * (drawSize / 3) / 2);
          minWidth = sqrt(x);
          //方法一:使用drawParagraph绘制文字,Paragraph是ui包内的
          Paragraph paragraph = buildParagraph(labelText, minWidth, drawSize / 2);
          canvas.drawParagraph(paragraph, Offset(drawSize / 3, -drawSize / 3));
        }
        break;
      case LabelAlignment.leftBottom:
        canvas.translate(0.0, drawSize);
        canvas.rotate(angleToRadian(45.0));
        if (useAngle) {
          double x = ((drawSize / 2) * (drawSize / 2) / 2);
          minWidth = sqrt(x);
          //方法一:使用drawParagraph绘制文字,Paragraph是ui包内的
          Paragraph paragraph = buildParagraph(labelText, minWidth, drawSize);
          canvas.drawParagraph(paragraph, Offset(0, 0));
        } else {
          double x = ((drawSize / 3) * (drawSize / 3) / 2);
          minWidth = sqrt(x);
          //方法一:使用drawParagraph绘制文字,Paragraph是ui包内的
          Paragraph paragraph = buildParagraph(labelText, minWidth, drawSize / 2);
          canvas.drawParagraph(paragraph, Offset(drawSize / 3, drawSize /27));
        }
        break;
      case LabelAlignment.rightTop:
      //旋转画布并平移  代码上是先做平移在旋转操作,反着来
        canvas.translate(0.0, drawSize);
        canvas.rotate(angleToRadian(45.0));
        if (useAngle) {
          double x = ((drawSize / 2) * (drawSize / 2) / 2);
          minWidth = sqrt(x);
          //方法一:使用drawParagraph绘制文字,Paragraph是ui包内的
          Paragraph paragraph = buildParagraph(labelText, minWidth, drawSize);
          canvas.drawParagraph(paragraph, Offset(drawSize/8,-drawSize*2));
        } else {
          double x = ((drawSize / 3) * (drawSize / 3) / 2);
          minWidth = sqrt(x);
          //方法一:使用drawParagraph绘制文字,Paragraph是ui包内的
          Paragraph paragraph = buildParagraph(labelText, minWidth, drawSize / 2);
          canvas.drawParagraph(paragraph, Offset(drawSize/2 , -drawSize*7/4 ));
        }
        break;
      case LabelAlignment.rightBottom:
      //旋转画布并平移  代码上是先做平移在旋转操作,反着来
        canvas.translate(0.0, drawSize);
        canvas.rotate(angleToRadian(-45.0));
        if (useAngle) {
          double x = ((drawSize / 2) * (drawSize / 2) / 2);
          minWidth = sqrt(x);
          //方法一:使用drawParagraph绘制文字,Paragraph是ui包内的
          Paragraph paragraph = buildParagraph(labelText, minWidth, drawSize);
          canvas.drawParagraph(paragraph, Offset(drawSize*8/5, -drawSize/4));
        } else {
          double x = ((drawSize / 3) * (drawSize / 3) / 2);
          minWidth = sqrt(x);
          //方法一:使用drawParagraph绘制文字,Paragraph是ui包内的
          Paragraph paragraph = buildParagraph(labelText, minWidth, drawSize / 2);
          canvas.drawParagraph(paragraph, Offset(drawSize*2, -drawSize/5));
        }
        break;
      default:

        break;
    }
    canvas.restore();
  }
//根据文本内容和字体大小等构建一段文本
  Paragraph buildParagraph(String text, double textSize, double constWidth) {
    ParagraphBuilder builder = ParagraphBuilder(
      ParagraphStyle(
        textAlign: TextAlign.right,
        fontSize: textSize,
        fontWeight: FontWeight.normal,
      ),
    );
    builder.pushStyle(ui.TextStyle(color: labelTextColor));
    builder.addText(text);
    ParagraphConstraints constraints = ParagraphConstraints(width: constWidth);
    return builder.build()..layout(constraints);
  }

拼搏在技术道路上的一只小白And成长之路

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值