Drawable的mutate方法——多ImageView.setAlpha失效问题解决

项目中有这样一个场景,不同界面的多个ImageView,展示同一个drawable资源,但是页面根据自身的scroll位置不同,设置了不同的alpha值。

初始代码如下:

imageView.setImageResource(resId);
imageView.setAlpha(alpha);

在实际测试中发现,多个页面加载同一Drawable的不同ImageView的表现一致,即均展示了统一的alpha(最后一次调用设置的alpha值)的效果。

原因是默认情况下,同一资源id加载的所有Drawable实例,共享同一状态。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.

 *

 * @return This drawable.

 * @see ConstantState

 * @see #getConstantState()

 */

public Drawable mutate() {

    return this;

}

mutate方法让drawable可变的,保证了与其他drawable的状态隔离,该操作不可逆。解决方案如下:

Drawable drawable = getResources().getDrawable(resId);
imageView.setImageDrawable(drawable.mutate());
imageView.getDrawable().setAlpha(255*alpha);

Android内部针对相同资源使用了缓存机制DrawableCache,缓存的信息是Drawable.CommonState,其中BitmapDrawable中BitmapState就是CommonState的实现类。

/**
     * If the resource is cached, creates and returns a new instance of it.
     *
     * @param key a key that uniquely identifies the drawable resource
     * @param resources a Resources object from which to create new instances.
     * @param theme the theme where the resource will be used
     * @return a new instance of the resource, or {@code null} if not in
     *         the cache
     */
    @UnsupportedAppUsage
    public Drawable getInstance(long key, Resources resources, Resources.Theme theme) {
        final Drawable.ConstantState entry = get(key, theme);
        if (entry != null) {
            return entry.newDrawable(resources, theme);
        }

        return null;
    }

BitmapState提供了newDrawable方法返回BitmapDrawable,且相同资源的BitmapDrawable对象共用同一个BitmapState,二者互相持有对象引用。setAlpha操作改变的就是BitmapDrawable的mBitmapState对象的属性值。这才导致上面的问题。

在尝试上述解决方案时,最初imageView一直未能未显示图片。原来是xml中设置了alpha属性为0,即imageView全透明。删除改行,动态设置alpha即可。

参考文章:
android Drawable.mutate()的使用
Android:关于Drawable的缓存机制应该了解的知识

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容