Android中使用背景色Alpha值遇到的一个坑
作者:twiceyuan 发布时间:2023-06-04 11:47:31
前言
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()
方法即可。
来源:https://twiceyuan.com/2017/01/12/colordrawable-bug/


猜你喜欢
- 基于SSM框架的仓库管理系统功能:系统操作权限管理。系统提供基本的登入登出功能,同时系统包含两个角色:系统超级管理员和普通管理员,超级管理员
- 1. Mybatis分页插件1.1 分页插件介绍分页可以将很多条结果进行分页显示。如果当前在第一页,则没有上一页。如果当前在最后一页,则没有
- 前言我们在 WPF 中使用绑定时可以使用 ElementName=Foo 这样的写法,并且还能够真的在运行时找到这个名称对应的对象,是因为
- 本文主要介绍了java(包括springboot)读取resources下文件方式实现,分享给大家,具体如下:1、使用项目内路径读取,该路径
- 一、背景在通过Runnable接口创建线程时,启动线程需要借助Thread类,这里就涉及到了静态代理模式。二、实例以歌手演出为例,在演出的这
- 本文实例为大家分享了java商品库存管理平台的具体代码,供大家参考,具体内容如下1.完成超市商品初始化。创建商品,将商品添加到集合2.显示来
- 本文实例为大家分享了java多线程之铁路售票系统的具体代码,供大家参考,具体内容如下问题:铁路售票,一共100张,通过四个窗口卖完。要求:分
- 本文实例讲述了Java网络编程实现的简单端口扫描器。分享给大家供大家参考,具体如下:在计算机网络的学习中,不由得觉得这门课的零碎知识点异常之
- 以下总结是2016/3/23在做一个网站时遇到的一个功能模块,现在将总结从为知笔记上搬家到CSDN,与大家共享,欢迎指正。0.准备工作 0.
- 目录引言命名规则代码排版1.代码缩进对齐2.遇到分号换行3.大括号、括号等成对出现4.加上注释Java注释注释的作用注释的3种类型给代码加上
- FPS 每秒帧数背景消除建模 BSMBackground SUbtractionBS算法图像分割(GMM-高斯混合模型)机器学习(KNN-K
- 本文实例讲述了Android实现完整游戏循环的方法。分享给大家供大家参考。具体如下:1. DroidzActivity.java:packa
- 本文实例讲述了C#实现向函数传递不定参数的方法。分享给大家供大家参考。具体实现方法如下:using System;class Min{ pu
- 前言Spring 事务注解 @Transactional 本来可以保证原子性,如果事务内有报错的话,整个事务可以保证回滚,但是加上try c
- 本文实例为大家分享了C#使用Aforge调用摄像头拍照的具体代码,供大家参考,具体内容如下一、新建一个Winform项目二、使用Nuget添
- 这篇文章主要介绍了Java代码块与代码加载顺序原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋
- forword跳转页面的三种方式:1.使用serlvet/** * 使用forward跳转,传递基本类型参数到页面
- IDEA 全称 IntelliJ IDEA,是java编程语言开发的集成环境。IntelliJ在业界被公认为最好的java开发工具,尤其在智
- C# WinForm控件的拖动和缩放是个很有用的功能。实现起来其实很简单的,主要是设计控件的MouseDown、MouseLeave、Mou
- Python是一种广泛使用的解释型、高级编程、通用型编程语言,由吉多·范罗苏姆创造,第一版发布于1991年。可以视之为一种改良(加入一些其他