前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >自定义View案例【LabelView】

自定义View案例【LabelView】

作者头像
flyou
发布2018-11-29 18:24:35
9260
发布2018-11-29 18:24:35
举报
文章被收录于专栏:flutter开发者flutter开发者

上期回顾

在前面的几篇文章中我们介绍了Flutter中自定义view的用法,学习了canvas中常用的绘制方法,在这篇及以后的几篇文章中我会给大家写几个自定义View的例子。

标签(我们给它命名LabelView)


提起标签相信大家都不会陌生,在平时使用应用或者网页中会经常看到这种效果

比如这种

或者这种?

今天我们就使用前面学过的知识来完成这个效果如何?

自定义LabelView


LabelViewPainter

首先我们还是先建立类继承于CustomPainter

代码语言:javascript
复制

这个时候我们先不着急去绘制图形,我们先来你想下canvas的哪个方法绘制比较方便。

由于这个LabelView是一个不算很规则的图形,所以我们用 canvas.drawPath()方法来实现比较合适。

接下来我们先来完成一个简单的绘制,先实现左上角的三角形效果

在这里我们先假设这个label的边长为100

代码语言:javascript
复制

可以看到我们使用Path构建了一个三角形的区域,并设置画笔的绘制风格为fill

当然,我们也可以改变这个label显示位置

比如右上角:

代码语言:javascript
复制

比如左下角:

代码语言:javascript
复制

比如右下角:

处理参数传入

当然这个时候我们绘制的label的颜色和大小都是我们写死在自定义的View里面的,包括标签显示的位置也都是我们默认写在左上角的。

接下来我们尝试把这些属性由外部传入进来。

首先我们新建类LabelAlignment来标注Label的方向

常量名

作用

leftTop

显示在左上角

leftBottom

显示在左下角

rightTop

显示在右上角

rightBottom

显示在右下角

代码语言:javascript
复制

然后我们让我们自定义的LabelViewPainter的构造方法传入这个参数。

同样的我们让LabelViewPainter的构造方法中传入label的颜色,方便我们绘制

@override void paint(Canvas canvas, Size size) { }

我们使用paint传入的size属性来获取label的尺寸。

在这里我们取size的宽和高最小值的二分之一为我们label的边长。

var drawSize = size.height > size.width ? size.width / 2 : size.height / 2;

然后我们根据传入的LabelAlignment类型来绘制不同方向的label即可。

下面看下改过的代码:

代码语言:javascript
复制

可以看到,我们只需要在调用的地方传入Size、color以及label方向即可调用LabelView,为了方便看出效果,我们给外层加了一个灰色的背景。

当然,我们依然可以把Size、color以及label设置为可选参数

LabelView({this.size=Size.infinite, this.labelColor = Colors.blue, this.labelAlignment=LabelAlignment.leftTop});

设置LabelView的默认尺寸为充满屏幕、默认颜色为蓝色、默认位置在左上角。这样一来我们使用起来就会简单很多了

“去角”的Label

在上面的文章中我们实现了带角的LabelView的效果,但是在平时的使用中我们也会常常使用哪种没有角的Label效果。

下面我们就来看下如何实现:

其实在上面代码的基础上实现起来就显得非常的简单,我们只需要根据显示的位置控制绘制的path即可。

为了方便使用,同样的我们给它新增了一个属性叫做“useAngle”默认我们让它是true,当它为false时显示去角的label效果。

看下实现的代码:

代码语言:javascript
复制

给LabelView加上文字

说了这么多,我们上面也仅仅是画出来了一个Label图形,文字没有显示啊,怎么让它显示文字呢?

但是,根据我们前面学过的东西我们知道,在CustomPainter中canvas是没有办法绘制文字的,那怎么办?总不能不显示文字吧?

方法当然是有的,大家都知道CustomPainter的使用时需要借助于CustomPaint,而CustomPaint可以传入child哦。

所以我们就可以从这里出发,把我们想要的文字放在这个child里。

但是我们并不能简简单单的就直接把我们要绘制的文字放在child里,因为我们的Label是倾斜且在一定的位置显示的。

所以我们需要控制文字的切斜和位置在我们绘制的label上才行。

在这里我们需要借助 Transform.rotate()来实现这个效果

Transform.rotate

代码语言:javascript
复制

构造方法非常的简单,我们只需要计算出旋转的角度和起始位置的坐标即可,数学计算就不再具体讲了,由于这里我没有计算文字的宽高所以可能会有一点的误差(原谅我比较懒)

当然,这个计算肯定也是要根据你label显示的位置来算的。

所以,我们需要在爱我们LabelView的构造方法中再增加几个关于文字的属性,文字内容、文字风格

改动比较多,所以把LabelView部分的代码都放了出来

代码语言:javascript
复制

在调用的地方我们只需要更改labelView的颜色、位置、文字即可。

包含其他child

你以为实现到上面的效果就结束了吗?不是这个样子的,因为我们LabView作为一个Widget只能显示不能组合其他Widget就不符合Flutter Widget设计的理念(组合大于继承)啊,所以我们的LabelView肯定也要支持组合其他的Widget的。

但是,看上面的代码可以发现我们CustomPaint的child已经被文字给占用了,但是我们现在还是需要在这个child里去放子Widget,怎么办?

肯定是要在这个child放置一个支持多child的Widget啊,想想也就那个几个

Widget

说明

ROW

横向显示

Colum

纵向显示

ListView

列表显示

Expanded

子Widget按照比例分布

Table

表格布局显示

Stack

堆栈布局

IndexedStack

可控制堆栈布局

根据我们以前学过的知识不难发现,我们这里使用Stack时最好的,位于栈定的Widget会覆盖位于栈底的Widget。

所以,我们把用于组合的子child放在栈底(第一个位置,优先入栈),把我们自定义的LabelView放在第二个位置,这样我们就实现了LabelView覆盖在子child上的效果。

代码语言:javascript
复制

在调用的地方:

代码语言:javascript
复制

效果如下:

小结

  • 使用drawPath绘制不规则图形
  • 掌握CustomPaint的用法
  • 结合其他Widget完成目标widget效果

当然,这个labelView实现的还是比较粗糙的,感兴趣的小伙伴可以继续去完善,如如labelView半透明效果,文字的测量等等。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-10-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 flutter开发者 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 上期回顾
  • 标签(我们给它命名LabelView)
  • 自定义LabelView
    • LabelViewPainter
      • 处理参数传入
        • “去角”的Label
          • 给LabelView加上文字
            • 包含其他child
            • 小结
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档