可能有点狂了,阿里的offer
还没拿到手就已经拒了抖音的offer
了,想一想音视频可能得先放一段落,只能间歇性来更新了,由于最近确实对这方面有点迷茫,交叉面淘系大佬给我列出的知识体系确实过于庞大,我如今仍是得先学着前辈们先把Java
层作好,再进阶也不迟。先把精力主战Java
和Flutter
了。不过以后项目可能尽量会用Kotlin
来作,毕竟这是阿里如今的内部可能主流语言了,毕竟再云栖大会上登场就是Kotlin
而不是Java
。git
Gtihub传送门 |
---|
在以前的文章Android自定义View,你摸的透透的了?之中,咱们知道过了View
的绘制流程、过分绘制啊之类的东西。这是基础,可是如今说的Paint
和Canvas
也是一种很是重要的基础了,他们用通俗的话来讲,就是笔和画布,而这么多的绘制哪个任务不是经过他们来完成的呢?github
以前咱们讲过音视频开发,那视频的概念,其实咱们应该也已经有所了解了,就是一帧帧的图片嘛,绘制的速度超过人眼,那么就可以演变成视频了。 面试
上面给出一个贝塞尔曲线的绘制过程,固然这个我已经用代码实现了。有兴趣的读者能够直接的去源码中的
PathView
类中进行查看。canvas
其实我就是模拟了100次而已,可是你就会感受整个图片他在动,这其实也是动画实现的一种原理了。ide
这个贝塞尔曲线的模拟,其实能够分为几个部分,两个相同的部分就是贝塞尔曲线他一条线和一个点的模拟,还有就是中间点,也就是贝塞尔曲线的位置变换模拟了。函数
那在这里咱们须要注意的地方就来了,如何获取当前点的位置,显然咱们只会使用Paint
和Canvas
是远远不够的,由于,咱们的小点显然须要经过位置变换计算得来的。这里咱们就要引入咱们一个类Path
了。布局
Path
Path
,从字面意思咱们就知道,这是一个路径的意思了。post
先来观摩一下他的的函数有什么,和Canvas
可能不同的地方就是,从draw
变到了add
,可是这样的区别,就能让Canvas
绘制更加复杂的图形了,由于draw
的对象都是已经封装好的圆形、长方形啊等等,而经过add
你就能绘制出各类奇形怪状的形状了,而贝塞尔曲线就是他们其中的一份子。学习
PathMeasure
什么是PathMeasure
呢?其实你关注上方,咱们讲过了Path
,可是终究仍是没讲到如何去进行一个位置的计算。而其实这个任务,就是交给咱们的这个PathMeasure
来交接完成的。动画
fun init(){
pathMeasure = PathMeasure(path, false)
pathMeasure?.length.let {
pathLength = it
mStep = it?.div(INVALIDATE_TIMES)
}
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
if (pathLength!! >= mDistance!!) {
mDistance?.let { pathMeasure?.getPosTan(it, mPos, mTan) }
mDistance = mStep?.let { mDistance?.plus(it) }
canvas?.drawPoint(mPos?.get(0)!!, mPos?.get(1)!!, paintPoint!!)
invalidate()
}
}
复制代码
具体代码仍是须要看我已经完成的PathView
,这里作一个简单的介绍,其实这个PathMeasure
经过Path
来计算长度,而后在经过咱们传入的Distance
来返回当前的Postion
和Tan
值,会有读者问了Tan
有什么用,其实通常比较多数的用法就是就是一个角度的调整,若是使用一个点来显示,确实没什么效果,可是若是是一个Bitmap
来现实的,没有Tan
值,那么咱们的图片就不会取转头了。
而后经过获取的Postion
和Tan
值来重绘,咱们就能够完成咱们的贝塞尔曲线绘制了
以前已经知道了咱们的这个图片如何去进行绘制,那这个时候咱们就继续深化了。
首先第一个问题,什么是刮刮卡?
小二上图!!!
读者: cool!!想知道想知道,这个咋实现呀。
小易: 我如今还不想告诉你,嘿嘿。
第二个问题,他有什么组成部分?
你可能会说,蒙版和底层图片呗。可是这个答案是,也不是。为何呢?若是只有蒙版和底层图片,其实这个不可以彻底实现的,你可能只能实现到下面的步骤。
一个只能看,不能刮的刮刮卡,哈哈哈哈哈哈哈哈!!!
既然咱们已经说了,这两个不够,那确定还有其余组成成分是须要咱们去进行考虑的了。其实他就是一支笔,这个刮的部分其实他是经过一支笔来完成的。
这里咱们须要补充几个知识点了。
经过写法以下:
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
val layerId = canvas?.saveLayer(
null, null
)
canvas?.let { canvasIt ->
paint?.let {paintIt->
rectBitmap?.let { canvas.drawBitmap(it,0f,0f, paintIt) }
paintIt.xfermode = xfermode
circleBitmap?.let { canvas.drawBitmap(it, 50f, 50f,paintIt) }
paintIt.xfermode = null
}
}
layerId?.let { canvas.restoreToCount(it) }
}
复制代码
经过一个短时的离屏缓冲,来完成两个图层的复合来实现。而这个复合就是经过一个layerId
来完成断定谁和谁是一家人。
这里又来一个知识点了!!!复合是怎么实现的???
下面给出一张图片来解释,这是Android
内置的Xfermode
,也就是复合模式是如何的,理解图片的意思便可,也不用专门去学怎么算的,归根结底,就是对RGB
某一个色块的突出或者隐藏。
好了,知道了这几个知识点,咱们回归正题,刮刮卡怎么实现的问题?咱们知道了复合,知道了离屏绘制,怎么用呢?
其实最后要讨论的就是蒙版是什么?底层图片作什么?
底层图片天然是给咱们看的,咱们总不能手画一下,而后被咱们抹掉吧,那这个图层显然是不能被咱们的覆盖掉的。而蒙版呢,咱们须要经过离屏绘制,把图片和咱们走过的路径进行重叠消除,来完成看到图片的效果。那这个效果应该是那种模式来完成呢?咱们看看上面给出的图片,那个最合适。
刮的过程就是咱们的Dst
和蒙版就是咱们的Src
,这个是应该就是XOR
这个模式是最符合咱们的要求的,咱们绘制过的和Src
重叠的地方所有消去了。
可是看过了源码的读者估计会问一个问题,为何我要建立一个DBitmap
来完成这个任务?其实不实现也能够的,可是你会出现下图的状况了,刮刮卡下方的图层一片乌漆麻黑,其实这个DBitmap
起到的是一个限制的做用了,给了Paint
的一个做用范围,那么实现的就更加舒服了,固然若是你限制了View
在整合布局中的大小,正好占满也是能够解决这个问题的,可是并不推荐。
最后就是一个简单的也比较重要的点了,这是Android
的事件分发机制都会问到的一个点,咱们应该重写什么方法,来完成绘制路径的添加。建议仍是在OnTouch
中完成,由于OnTouch
的响应实际上是先于OnTouchEvent
的。
以上就是个人学习成果,若是有什么我没有思考到的地方或是文章内存在错误,欢迎与我分享。
相关文章推荐: