Android中使用背景色Alpha值遇到的一个坑

所属分类: 软件编程 / Android 阅读数: 61
收藏 0 赞 0 分享

前言

Android通过设置Alpha值图片淡化、透明度大家应该都知道,下面是段简单的示例代码:

View v = findViewById(R.id.img_layout); 
v.getBackground().setAlpha(77);// 设置背景图片透明度;0~255透明度值 

以上是个简单的介绍,但本文介绍的是公司项目一个留了很久的 bug,尝试找了很多次原因都没有头绪。

这个 bug 是这样的:

定义了一个主题色为例如 #FF0000,很多界面控件都用了这个颜色。可是这个颜色在 app 使用过程中用着用着就会出现变成了透明的情况,而且出现透明之后,所有使用这个颜色的控件都会变成透明。

更奇怪的是,重启应用会恢复这个问题,但是操作一会儿又会出现。

项目有个随着页面滚动标题栏从透明过渡到主题色的界面实现,类似于 Design 库中 AppBar 的那种效果。实现方法是这样的:

// 滚动监听器 伪代码
someParams -> {
 //...
 view.getBackground().setAlpha(percent);
 //...
}

今天「代码级复用」这一 feature 时,发现把 bug 也引入了新项目,才发现这个实现的问题之所在……

首先,view.getBackground() 获得的是一个 ColorDrawable,然后给这个 ColorDrawable 设置 Alpha 值的话,会影响所有设置 background 为这个颜色的背景色的 Alpha 值。

然后就写了个小 demo 验证了一下这个说法,虽然不是立即生效的,然后返回退出应用后,两个相同颜色背景的 view,改变其中一个确实会影响到另一个。

当时反应就是:WTF?难不成全局的相同颜色的 Drawable 都是同一个对象?不过很快打印了一下 background 的 drawable 对象验证了并不是这样——虽然这些 view 获得的 ColorDrawable 的 Alpha 值都相同,但 hashcode 都是不同的。

所以我更倾向于这是 Android 内存优化带来的 bug,即使这个颜色在定义时就有 Alpha 值,在修改后也会被忽略,并影响到其他的 view。该问题只在布局文件里设置 background 为一个 color 的 id 或者值,或者 setBackgroundResource 为一个 color 时存在。如果使用 new ColorDrawable(int) 来构造一个使用相同颜色值的对象则不受影响,我目前也正是使用这个方法来躲避掉这个 feature。

UPDATE:

发现文档里有这个方法,验证了之前的说法,从同一资源加载的 drawable 确实会共享状态,不过有一个 mutate 方法来禁用这一特性。文档如下:

Drawable mutate ()

Make this drawable mutable. This operation cannot be reversed. A mutable drawable is guaranteed to not share its state with any other drawable. This is especially useful when you need to modify properties of drawables loaded from resources. By default, all drawables instances loaded from the same resource share a common state; if you modify the state of one instance, all the other instances will receive the same modification. Calling this method on a mutable Drawable will have no effect.

翻译:

Drawable mutate ()

让一个 Drawable 变为 mutable 的。这个操作是不可逆的。一个 mutable 的 drawable 可以保证不会分享自己的状态给其他 drawable。当一个 drawable 是从 resource 加载的,在需要更改它状态时这个方法特别有用。在默认情况下,所有从相同 resource 的 drawable 的实例是共享一个通用状态的;如果你修改了其中一个的状态,所有其他的实例也会收到相同的改动。在一个已经是可变的 drawable 上调用该方法没有效果。

所以,上述代码只要在 drawable 获取之后,调用一下 mutate() 方法即可。

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

更多精彩内容其他人还在看

Android样式和主题之选择器的实例讲解

今天小编就为大家分享一篇关于Android样式和主题之选择器的实例讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
收藏 0 赞 0 分享

Android应用动态修改主题的方法示例

今天小编就为大家分享一篇关于Android应用动态修改主题的方法示例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
收藏 0 赞 0 分享

Flutter 网络请求框架封装详解

这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Flutter倒计时/计时器的实现代码

这篇文章主要介绍了Flutter倒计时/计时器的实现代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

Android使用google breakpad捕获分析native cash

这篇文章主要介绍了Android使用google breakpad捕获分析native cash 的相关知识,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

详解Flutter WebView与JS互相调用简易指南

这篇文章主要介绍了详解Flutter WebView与JS互相调用简易指南,分为JS调用Flutter和Flutter调用JS,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Android开发实现ListView和adapter配合显示图片和文字列表功能示例

这篇文章主要介绍了Android开发实现ListView和adapter配合显示图片和文字列表功能,涉及Android使用ListView结合adapter适配器实现图文显示功能相关的布局、解析、权限控制等操作技巧,需要的朋友可以参考下
收藏 0 赞 0 分享

Android文字基线Baseline算法的使用讲解

今天小编就为大家分享一篇关于Android文字基线Baseline算法的使用讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
收藏 0 赞 0 分享

Flutter自定义实现神奇动效的卡片切换视图的示例代码

这篇文章主要介绍了Flutter自定义实现神奇动效的卡片切换视图的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Android实现自定义滑动刻度尺方法示例

这篇文章主要给大家介绍了关于Android实现自定义滑动刻度尺的相关资料,文中通过示例代码介绍的非常详细,对各位Android开发者们具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享
查看更多