原文来自Android SDK文档中的 resources/articles/drawable-mutations.html
Android的drawables非常便于构建应用。Drawable是一个可插拨的绘制容器(drawing container), 通常与一个View关联。 比如, BitmapDrawable用于显示图片, ShapeDrawable用于绘制图形和渐变, 等等。 还可以组合使用,创建更复杂的渲染效果。
Drawables允许不必继承Widget就可以方便地定制Widget的渲染效果。事实上, 它们是如此方便易用,多数自带的Android应用和Widget是通过使用Drawables来构建的。 Android核心框架使用了大约700个Drawables。 由于Drawables的系统中大量使用, Android优化过其加载过程。 比如, 每次当你创建一个Button, 一个新的Drawable将从框架资源文件中(android.R.drawable.btn_default)加载进来。 这意味着所有应用中所有的button使用不同的Drawable实例作为它们的背景。 但是所有这些Drawables共享相同的状态, 即Constant State。 这个状态中的内容因使用的Drawable类型而变化,但通常都包含所有可用的资源属性。 以button为例, Constant State包含一个Bitmap Image。 这样,所有应用中的所有Button都共享相同的Bitmap, 可以节省大量内存。
下图展示当把同一个Image资源作为两个不同的View的背景时哪些实体将被创建。 正如你所见, 两个Drawable被创建,但他们共享同一个Constant State, 即同一个Bitmap
虽然共享Constant State这个特性有利于减少内存的使用, 但当你需要修改Drawable的属性时可能产生问题。 考虑一个应用, 它有一个Book列表。 每个Book书名旁边有一个星形, 当用户标记当前Book为喜欢时这个星形完全不透明, 而未标记为喜欢时这个星形为半透明。 为实现这个显示效果, list adapter中的getView()方法可以这样写:
Book book = ...; TextView listItem = ...; listItem.setText(book.getTitle()); Drawable star = context.getResources().getDrawable(R.drawable.star); if (book.isFavorite()) { star.setAlpha(255); // opaque } else { star.setAlpha(70); // translucent }很不幸, 以上代码将产生奇怪的结果:所有的星形都成了半透明。如下图所示:
这个结果也说明了Constant State的特点。 尽管我们为每个Item生成了一个新的Drawable实例, Constant State仍然是相同的。 对BitmapDrawable而言, 透明度也是Constant State的一部分。因此, 改变一个Drawable实例的透明度, 同时也会影响其他Drawable实例的透明度。 更糟糕的是, 这个问题在Android 1.0和Android 1.1上不容易修复。
Android 1.5及以上版本提供了一个简单的办法来解决这个问题:新添加的mutate()方法。当你在某个Drawable上调用mutate()方法时, 将复制该Drawable的Constant State, 并允许修改该复制结果的属性且不会对其他Drawable生成影响。 注意, 就算复制了Drawable, Drawable仍然共享Bitmap。 下图显示了在Drawable上调用mutate()之后的结果:
现在, 使用mutate()重新修改一下之前的代码:
Drawable star = context.getResources().getDrawable(R.drawable.star); if (book.isFavorite()) { star.mutate().setAlpha(255); // opaque } else { star. mutate().setAlpha(70); // translucent }mutate()方法返回Drawable自己, 所以链式调用非常方便。 这个方法并没有创建一个新的Drawable实例 。 修改后的代码结果是正确的。
(另外附上自己根据这篇文档写的一个例子, 验证下mutate()的用法)
代码:
public class ConstantStateActivity extends ListActivity { private ListAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAdapter = new MyListAdapter(this, R.layout.my_adatper, R.id.textView1, Arrays.asList("and-aa", "iphone-b")); getListView().setAdapter(mAdapter); } static class MyListAdapter extends ArrayAdapter<String> { private int mRes; private List<String> mData; public MyListAdapter(Context context, int resource, int textViewResourceId, List<String> objects) { super(context, resource, textViewResourceId, objects); this.mRes = resource; this.mData = objects; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = convertView; if (null == view) { LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(LAYOUT_INFLATER_SERVICE); view = inflater.inflate(mRes, parent, false); ImageView icon = (ImageView) view.findViewById(R.id.imageView1); MyLog.i(icon + ""); if (mData.get(position).startsWith("and")) { icon.getDrawable().setAlpha(0); // icon.getDrawable().mutate().setAlpha(0); } } return view; } } }布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center_vertical"> <ImageView android:layout_height="wrap_content" android:src="@drawable/icon" android:layout_width="wrap_content" android:id="@+id/imageView1"></ImageView> <TextView android:text="TextView" android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView> </LinearLayout>不调用mutate()时截图如下(ImageView都变成透明的了, 所以看不见)
调用mutate()方法时截图如下(一个ImageView透明, 另一个不透明, 正确结果!)
相关推荐
android-gif-drawable 用于在Android上显示动画GIF
Android所有系统资源图标android.R.drawable.xxx查看软件 源码地址:http://blog.csdn.net/dianyueneo/article/details/7197067
Android-android-gif-drawable.zip,在android上显示动画gif的视图和绘图,安卓系统是谷歌在2008年设计和制造的。操作系统主要写在爪哇,C和C 的核心组件。它是在linux内核之上构建的,具有安全性优势。
android_gif_drawable(播放gif图片)
android-gif-drawable Views and Drawable for animated GIFs in Android. Overview Bundled GIFLib via JNI is used to render frames. This way should be more efficient than WebView or Movie classes. ...
Android系统图标android.R.drawable下的所有图标查看软件
android-gif-drawable 开源组件,需要的朋友下载
参照github上android-gif-drawable框架出现的5.0不适配的问题。
Android应用源码之android-gif-drawable 支持fig显示的view.zip
android-gif-drawable最快最流畅的GIF,带源码带so库,带范例!不像很多其他资源,虽说用了android-gif-drawable的开源项目,但是没有编译so,也没有上传,你下载他的根本用不了!因此特意上传亲测可以直接使用的给...
github最新android-gif-drawable资源so; android-async-http-1.4.5.jar demo中实现了本地gif显示和网络加载gif显示
开源库 android-gif-drawable使用的jar包,使用详见博客http://blog.csdn.net/u012587637/article/details/18596465
查看android.R.drawable图片。点击并显示出名称 UTF-8 android2.2~android4.2
android中的drawable集合,包括Bitmap、shape、Layer、Transition等等
android 通过图片名称获取 drawable 目录下的图片 ~~~~~~~~~~~~~~~~~
几种比较流行的图片加载框架,可以播放gif格式的动态图片,它们分别是 glide-3.7.0.jar picasso-2.5.2.jar android-gif-drawable-master.jar。
《google android sdk开发范例大全(第3版)》在上一版的基础上,以android手机应用程序开发(采用android sdk 2.3.3)为主题,超过200多个范例全面且深度地整合了手机、网络及服务等多个开发领域,为读者提高程序设计...
Android图像介绍-Drawable
Google Android SDK开发范例大全(完整版)共4个分卷 目录 第1章 了解.深入.动手做. 1.1 红透半边天的Android 1.2 本书目的及涵盖范例范围 1.3 如何阅读本书 1.4 使用本书范例 1.5 参考网站 第2章 Android初体验 2.1...