type
status
date
slug
summary
tags
category
icon
带着问题先看了下 RippleDrawable 的源码,恩!很好,完全没看出啥东西 (╯°□°)╯︵┻━┻ 。。。
网上搜了一波,恩!nice,没找到答案 (╯°□°)╯︵┻━┻
正当我漏气时,突然想到会不会是硬件加速搞的鬼?写了一个简单的 demo,关掉硬件加速的时候,波纹就画不出去了,启用硬件加速的时候,就画出去了
沿着这个思路重新看了下 RippleDrawable 的源码,发现一个没看懂的 override 函数,而且还是 @hide 的:
这是啥?网上搜了一波这函数,终于在老罗这篇文章中搜到了答案:
... 本来DisplayListRenderer类的成员函数addRenderNodeOp执行到这里,就已经完成任务了。但是在Android 5.0中,增加了一个新的API——RippleDrawable。RippleDrawable有一个属性,当它没有包含任何的Layer时,它将被投影到当前视图的设置有Background的最近的一个父视图的Background去。这一点可以参考官方文档
为了达到上述目的,每一个Render Node都具有三个属性:Projection Receive Index、Projection Receiver和Projection Backwards。其中,Projection Receive Index是一个整型变量,而Projection Receiver和Projection Backwards是两个布尔变量。注意,在一个应用程序窗口的视图结构中,每一个View及其设置的Background都对应一个Render Node。上述三个属性构成了Render Node里面的一个Projection Nodes的概念,如图3所示 ...
摘自老罗的文章
如果你想详细了解硬件加速的原理的话,看老罗的文章,我下面就对 RippleDrawable 做一下简单的解释

硬件加速的情况下,Android 5.0 以后的应用程序 UI 绘制是分为两步的
第一步构建 DisplayList,里面记录了 View 的绘制命令集合,发生在主进程 MainThread
第二步是渲染 DisplayList,把这些绘制命令转为 Open GL 的命令,然后交给 GPU 执行
Android 中的 View 都被抽象成一个 RenderNode(一个 RenderNode包含了自己和儿子的DisplayList,除了TextureView和软件渲染的子视图不包含DisplayList如果这个 View 有背景的话,也会被抽象成一个 RenderNode
也就是说,硬件加速最后绘制的东西全部都存在 DisplayList 中,那么就来看看 View 是怎么更新背景的 DisplayList
先看 ViewdrawBackground(Canvas) 方法
上面的代码是 View 被调用 draw(Canvas) 的时候,绘制背景的函数,如果启用了硬件加速,背景被转换成一个 RenderNode,然后被绘制到 Canvas
看一下 DisplayListCanvas 内部的 drawRenderNode 函数
调用了 native 方法,需要查看 framework 方法才看得到了,查找了一波后,找到了实现的地方
谢天谢地的终于找到了这个函数的用处 isProjectionReceiver(),让我稍微讲解下吧
drawRenderNode() 函数是把 RenderNode 封装成一个 DrawRenderNodeOp 然后丢给 addRenderNodeOp() 函数
RenderNode 包含了绘制命令
addRenderNodeOp() 中首先把 op 加入到了 CanvasmDisplayList 中,opIndex 就是当前的 opmDisplayList 中的位置。
然后在最后,那个 if 判断,判断当前的 RenderNode 是否是isProjectionReceiver 的,如果是的,那么把当前 opindex 赋值给 mDisplayList->projectReceiveIndex 这有什么用呢?这样 mDisplayList 不就知道了我那个需要特殊待遇的 RenderNode 是谁了吗?
前面说了 Backgound 自成一个 RenderNode,所以 RippleDrawable 自成一个 RenderNode,既然 DisplayList 都知道了这个特殊的 RenderNode,那么绘制的时候优先绘制这个 RenderNode,就可以画到外面了

硬件加速涉及的东西有点多,建议还是看下老罗的文章,虽然长篇大论,不过源码分析透彻
Android Bitmap density 解析在Android上使用FFmpeg压缩视频
Loading...