Kotlin 中优化的棋盘图案 VectorDrawable_kotlin <vector >(1)

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

    append("M0,$y")
    for (x in 0 until size step 4) {
        append('H'); append(x + 2)
        append('V'); append(y + 4)
        append('H'); append(x + 4)
        append('V'); append(y)
    }
    append('V'); append(y + 2)
    append('H'); append(0)
    append('V'); append(y)
    append("z ")
}

}


当然,它引入了一个新的限制:大小现在必须是 4 的倍数。这对我来说很好,因为它不会面向客户。但是,我想我可以做得更好。


#### 完全删除移动命令


首先,我问自己:“我能用一条路径画出那个棋盘吗?”


在我的实验中,我发现小写h和v命令是相对位置的变体,这使得在 XML 中手动进行实验变得更加容易。


我尝试了最简单的版本来回答我的问题。


这是我得到的路径数据:`M0,0h2v4h2V2H0z`,这就是我在 IDE 中看到的:


![](https://img-blog.csdnimg.cn/2b858aed27174c8fb5633190f13beb8f.png)


然后,我想看看如果我删除前导会发生什么M0,0。预览没有任何变化。我试图打破这件事(成功地),当我恢复我刚刚做的坏事时:它再次显示了正确的事情。我刚刚意识到0,0默认情况下任何路径都会从这里开始,这正是我需要从我的用例开始的地方!


如果您想在实际的 Android Studio 项目中亲自尝试,这里是完整的 VectorDrawable。



<?xml version="1.0" encoding="utf-8"?>




2x2 网格(或技术上的 4x4)似乎是一种特殊情况,我想知道填充我想要空的盒子会被我想要填充的盒子包围会发生什么。它们也会被填满,还是像我想要的那样是空的?


我手动继续,一步一步地,我得到了以下路径数据:`h2v8h2V0h2v8h2 v-2H0v-2h8v-2H0z`,幸运的是,这正是我正在寻找的结果:


![](https://img-blog.csdnimg.cn/e801ff51c7a340bfab0d3137144f337a.png)


然后我去写代码,还设计了函数,让它支持可变的盒子大小,所以它可以进化为支持矩形板和矩形框。它缺少一些先决条件,例如拒绝boxSize大于 的a size,但它只在我的开发机器上本地运行,我不明白为什么我会尝试这样的事情。


它不是逐个绘制框,也不是使用嵌套的 for 循环绘制 2 行乘 2 行,而是绘制垂直线,然后在关闭路径之前绘制水平线。


![](https://img-blog.csdnimg.cn/c0883d88eaf94ac69b167cf08ef53913.png)


之前的实现具有二次复杂度,结果的大小会随着网格大小而增长很多,而下面的实现具有线性复杂度,结果也只会随着大小线性增长。


这是代码:



fun Int.isOdd() = this % 2 != 0 // It’s odd that this isn’t built into Kotlin, isn’t it?

fun generateChessboardPattern3(
size: Int,
boxSize: Int
): String = buildString {
val boxWidth = boxSize
val boxHeight = boxSize
val width = size
val height = size
for (x in 0 until width step boxWidth) {
append(“hKaTeX parse error: Expected 'EOF', got '}' at position 210: …calOffset) }̲ for (y in …{boxHeight}”)
if (y - boxHeight == 0) break // Don’t draw the last line.
val horizontalOffset = if ((y / boxHeight).isOdd()) height else 0
append(‘H’)
append(horizontalOffset)
}
append(‘z’)
}


### 最后的小优化


在我开始编写上面的第三个版本之前,我在想潜在的等价v-2物比 长V8,但同时v-2比 短V10。我并没有让这阻止我首先编写一个简单的工作版本,但是,我在第二个 for 循环中为第四次迭代更改了 3 行,允许我在结果中尽可能减少一些额外的字节:



fun generateChessboardPattern4(
size: Int,
boxSize: Int
): String = buildString {
val boxWidth = boxSize
val boxHeight = boxSize
val width = size
val height = size
for (x in 0 until width step boxWidth) {
append(“hKaTeX parse error: Expected 'EOF', got '}' at position 210: …calOffset) }̲ for (y in …{boxHeight}” else “V${targetY}”) // <- changed
if (targetY == 0) break // Don’t draw the last line. // <- changed
val horizontalOffset = if ((y / boxHeight).isOdd()) height else 0
append(‘H’)
append(horizontalOffset)
}
append(‘z’)
}


使用以下代码:



println(“approach number 3:”)
println(generateChessboardPattern3(size = 28, boxSize = 2))
println(“approach number 4:”)
println(generateChessboardPattern4(size = 28, boxSize = 2))


我检查了他们的比较:



approach number 3:
h2V28h2V0h2V28h2V0h2V28h2V0h2V28h2V0h2V28h2V0h2V28h2V0h2V28h2v-2H0v-2H28v-2H0v-2H28v-2H0v-2H28v-2H0v-2H28v-2H0v-2H28v-2H0v-2H28v-2H0v-2z
approach number 4:
h2V28h2V0h2V28h2V0h2V28h2V0h2V28h2V0h2V28h2V0h2V28h2V0h2V28h2v-2H0v-2H28v-2H0v-2H28v-2H0v-2H28v-2H0v-2H28v-2H0V8H28V6H0V4H28V2H0V0z


只保存了 5 个字符,很明显,我们看到了收益递减法则的影响,但我还是接受了它。已经花时间了,没有明显的缺点……


最后两个可能的优化(我没有检查aapt2是否在做)是将androidxml 命名空间重命名为a,并删除所有非强制空格和换行符。无论如何,我在那里节省了 81 个字节(与上一次迭代相比减少了 20% 以上)。


### 计算节省


那真是一段旅程!老实说,我的速度很快,但是写文章让它变得更长了……😅分享是关怀!


如果你考虑整个文件大小,我们从 1812 字节开始,现在最优化的版本是 318 字节,缩小了 5.7 倍!


![](https://img-blog.csdnimg.cn/e3cd6fd9d89744e5bba9650ed2836980.png)


如果你只取路径数据,我们从 1504 字节/字符开始下降到 131 字节/字符,或者更小 11.4 倍!


#### 1、如何绘制既不水平也不垂直的线条?


这非常简单,就像我们在开始时一直在Mx,y移动到一个位置一样,使用Lx,y,它会在给定的绝对位置画一条线,或者使用小写变体作为相对位置(lx,y)。现在我想学习如何绘制曲线……也许以后再说吧。


#### 2、如何将 VectorDrawable 转换为像素完美的 PNG?


对于这篇文章,我一直在寻找一种从我的 VectorDrawables 中获取 png 的方法。


我一开始没能找到合适的方法,所以我使用截图并粗略地裁剪。然后,在我提取 PNG 之前,我找不到将它们转换为 SVG 的工作工具。然后我成功地手动进行了转换,在那里我很高兴地了解了更多关于 SVG 的知识。因此,我添加了依赖项,并且使用以下代码,我现在可以从任何 Android VectorDrawable 中获取一个漂亮的 PNG 文件:


**深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

![](https://img-blog.csdnimg.cn/direct/743b668910224b259a5ffe804fa6d0db.png)
![img](https://img-blog.csdnimg.cn/img_convert/26156dd6a4357e7e8761d1af65b37cba.png)
![img](https://img-blog.csdnimg.cn/img_convert/41ded3b9203a00384b48267f94a9c174.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618636735)**

Kf-1715893678083)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618636735)**

  • 11
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值