Android Skia图形库

lzyprime 博客 (github)
创建时间:2020.12.17
qq及邮箱:2383518170

kotlin & android 笔记


λ:

SkiaAndroidflutter底层的2D图形库。Skia 官网

2D页面无非就是 图形(点、线、面),文字, 所以Skia设计也很简单:

  1. 新建Canvas, 画布,所有内容画在这上面
  2. 通过Canvas相关方法画出内容。一般名为drawxxx(), 同时要传入一个Paint, 也就是画笔样式。
  3. 通过Canvas相关方法裁剪画布,一般名为clipxxx()
  4. 内容定位,以Canvas左上角为(0, 0)点,向右向下建立(x, y)坐标系。

在官网可以直接体验这些API的C++版本,androidflutter无非是做一层包装,API大差不差。

用处:

  1. 自定义View。 不管是Android还是flutter想要自定义程度高就离不开直接操作Render层。大多数情况的确可以用现有的组件拼凑出想要的效果,但坏处就是损失很多没必要的计算和渲染,而且有些东西生写不出来。flutter有很多组件原生设计简单,然后留出canvas用来自定义样式。

  2. 设计UI时,大概估计一下有多费。尤其是flutter, 之前团队项目写出来的列表肉眼可见的掉帧。 我翻看这部分代码,发现大量的无用的组件嵌套,然后频繁的rebuild, 宽高很多写死,没有自适应能力。很多UI长一样却不复用,出现ItemXXXView1, ItemXXXView2这种东西。所以有一段时间的工作就是删代码,git记录我一个月添加了几百行然后删了几千行。

Canvas

官网Canvas介绍

draw

  1. drawColor: 喷色,不需要传画笔。
  2. drawRect: 画矩形Rect,需要左上角点的坐标和矩形宽高,同时传入一个Paint画笔样式
  3. drawRoundRect: 类似drawRect, 不同是可以设置圆角,通过传入圆角的 x, y 偏移值
  4. drawOval: 椭圆Oval,类似drawRect
  5. drawCicle: 圆Circle, 类似drawRect
  6. drawPath: 画线,需要传入Path线的路径和Paint画笔。
  7. drawText: 渲染文字,需要传入文字,起始位置的坐标,Paint画笔(主要设置文字样式)。

clip

clipxxx: 裁剪画布,可以传 Path, Oval, Rect, Circle 等等

trans

  1. translate(x, y): 平移到x, y。 作为新的原点
  2. scale(x, y): 缩放
  3. rotate: 旋转
  4. save: 保存当前状态,一般在变换前调用
  5. restore: 恢复现场,必须保证之前有save操作

Path

官网Path介绍

除了规则图形外,其他 点,线,面 都可以通过Path画出来。然后就变成了数学题。

点动成线,线动成面,面动成体, 当直线长度与画笔粗细相同,就相当于画了一个 , 而 可以看作多根 线 并排的结果。

  1. moveTo(x, y): 移动到指定坐标
  2. lineTo(x, y): 从当前位置向 (x, y) 画直线。 获得线段(localX, localY) -> (x, y)
  3. quadTo(x1, y1, x2, y2): 贝塞尔曲线。从当前位置经过 (x1, y1) 向 (x2, y2) 画平滑曲线
  4. conicTo: 类似quadTo
  5. addCircleaddRect等等,添加现成图形
  6. close: 当前点与起始点连接,形成闭合图形。

Paint

官网Paint介绍

  1. color, width: 颜色,粗细
  2. style: 填充方式
    • fill: 实心
    • stroke: 镂空、描边
  3. fontStyle: 字号,字体,字宽,字重等等属性。 原生C++里通过构造可绘制字符串(sk_sp<SkTextBlob>)实现, android 封装进了Paint里。 flutter 封装进了 TextStyle
  4. filter|shader: colorFilter,maskFilter等等效果

BlendMode

官网BlendMode介绍

用于处理两个元素A, B 相交时显示方式。

(A在B上, A在B下, A与B同级) * (交集, 并集, 异或集)。

1.png

实践

利用Path画圆角长方形。

  1. 圆角值 topLeft == bottomRight == 20, topRight == bottomLeft == 40
  2. 起始位置(20, 20)
  3. 宽 200, 高 100
void draw(SkCanvas* canvas) {
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(8);
  
    SkPath path;
    double startX = 20, startY = 20; // (startX, startY) 左上角
    double endX = startX + 200, endY = startY + 100; // (endX, endY) 右下角
    double topLeftRadius = 20, topRightRadius = 40;
    
    // 移动起始点到左上角,并空出左上角圆角位置。 所以x坐标要+topLeftRadius
    path.moveTo(startX + topLeftRadius, startY);
    
    // 横向画线,同理空出右上角圆角位置
    path.lineTo(endX - topRightRadius, startY);
    // 右上角的圆角, 经过右上角(endX, startY) 向 (endX, startY + topRightRadius) 画曲线
    path.quadTo(endX, startY, endX, startY + topRightRadius);
  
    // 同理完成右边, 底边,左边的绘制,最后与起始点 (startX + topLeftRadius, startY) 闭合

    // 右边
    path.lineTo(endX, endY - topLeftRadius);
    // 右下圆角
    path.quadTo(endX, endY, endX - topLeftRadius, endY);
  
    // 底边
    path.lineTo(startX + topRightRadius, endY);
    // 底边圆角
    path.quadTo(startX, endY, startX, endY - topRightRadius);
    
    // 左边
    path.lineTo(startX, startY + topLeftRadius);
    // 左上圆角
    path.quadTo(startX, startY, startX + topLeftRadius, startY);
  
    canvas->drawPath(path, paint);
}
2.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容