Android 深色模式适配原理分析( 七 )

(renderNodePtr)->setPropertyFieldsDirty(dirtyFlag), true) \: false)最后这个是否允许深色模式的allow变量被设置到RenderProperties.h 中
frameworks/base/libs/hwui/RenderProperties.h
/* * Data structure that holds the properties for a RenderNode */class ANDROID_API RenderProperties {public:// ...// 设置View是否允许强制深色模式bool setAllowForceDark(bool allow) {return RP_SET(mPrimitiveFields.mAllowForceDark, allow);}// 获取View是否允许强制深色模式bool getAllowForceDark() const {return mPrimitiveFields.mAllowForceDark;}// ...private:// Rendering propertiesstruct PrimitiveFields {// ...// 默认值为truebool mAllowForceDark = true;// ...} mPrimitiveFields;我们回头看下上面分析过的RenderNode.cpp的prepareTreeImpl流程
frameworks/base/libs/hwui/RenderNode.cpp
// 经过了简化处理的prepareTreeImpl逻辑void RenderNode::prepareTreeImpl(TreeObserver}// 同步正在处理的Render Node的Display List , 实现具体深色的逻辑pushStagingDisplayListChanges(observer, info);mDisplayList->prepareListAndChildren([](RenderNode* child, TreeObserver});// 递归结束后将之前设置过+1的值做回退-1恢复操作 , 避免影响其他兄弟结点的深色模式值判断if (!mProperties.getAllowForceDark()) {info.disableForceDark--;}}可以看出 , 设置View的forceDarkAllowed最终会设置到当前RenderNode的mProperties.allowForceDark属性中 , 并在RenderNode遍历的过程中影响深色模式的执行 。
我们可以以下面的伪代码来更直观地了解深色模式执行的流程:
// 深色模式渲染伪代码int disableDark = if (themeAllowDark) 0 else 1;void RenderNode(Node node) {if (!node.allowDark) {disableDark++;}if (disableDark == 0) forceDarkCurrentNode();for (child : node.children) {RenderNode(child)}if (!node.allowDark) {disableDark--;}}至此 , 我们分析完所有强制深色模式的原理 。 总结一下 , 主题默认不会强制深色 , 若主题设置了强制深色 , 则遍历View树对其节点进行强制深色转换 。 碰到某个View不希望被强制深色 , 则包括它和它的所有子节点都不会被强制深色 。
总结到这里 , 我们了解了可以通过设置-night资源以及判断当前颜色模式来自定义切换主题、色值、图片和动画的颜色 , 也从源代码角度了解Force Dark的原理和生效规则 。


推荐阅读