用TransitionDrawable实现ImageView渐隐渐显效果,并解决OutOfMemory问题
http://blog.csdn.net/heqiangflytosky/article/details/20145939?utm_source=tuicool&utm_medium=referral
1、实现ImageView的渐隐渐现的效果
实现两张图片渐隐渐现的过渡效果,大家马上回想到使用TransitionDrawable来实现,这方面的例子网上挺多:比在布局文件中使用translation实现
在Java中使用代码:
- <transition xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/image_expand" />
- <item android:drawable="@drawable/image_collapse" />
- </transition>
Resources res = getResources(); TransitionDrawable transition = (TransitionDrawable)res.getDrawable(R.drawable.expand_collapse); ImageView image = (ImageView) findViewById(R.id.toggle_image); image.setImageDrawable(transition); transition.startTransition(1000);或者使用下面代码实现:
TransitionDrawable mTransitionDrawable = new TransitionDrawable(new Drawable[]{ view.getDrawable(), new BitmapDrawable(bitmap) }); mTransitionDrawable.setCrossFadeEnabled(true); mTransitionDrawable.startTransition(500); view.setImageDrawable(mTransitionDrawable);
其中500是渐变持续的时间,
TransitionDrawable
的第一个参数是渐变开始时的图像,第二个参数是最终要显示的图像。注意到这里的问题了,2000多张图片,预示着要生成2000多个TransitionDrawable 的临时变量,通常情况下是显示不到20张就OutOfMemory了。在http://adk.tumblr.com/post/13069401302/outofmemoryerror-imageview-and-transitiondrawable-a一文中作者提到了,是存在内存泄露的情况了。最后采取了文中的方法,成功实现了想要的效果。
2、代码:
这里先从ImageView中取出它包含的Drawable,看是属于TransitionDrawable还是属于BitmapDrawable的实例,如果属于TransitionDrawable,那么就取出它的第二个layer的图片作为下一个动画的第一个layer,把将要显示的图片作为第二个layer。如果属于BitmapDrawable那就说明还没有为该gridview创建TransitionDrawable,那么就创建一个。并把该BitmapDrawable作为下一个动画的第一个layer,把将要显示的图片作为第二个layer。由于GridView仅保存几个ImageView实例来循环使用来显示图片,因此并不会频繁的创建TransitionDrawable,这样就不会内存泄露造成OOM了。
Drawable oldDrawable = view.getDrawable();
BitmapDrawable oldBitmapDrawable = null;
TransitionDrawable oldTransitionDrawable=null;
if(oldDrawable instanceof TransitionDrawable){
oldTransitionDrawable = (TransitionDrawable)oldDrawable;
oldBitmapDrawable =(BitmapDrawable)oldTransitionDrawable.findDrawableByLayerId(oldTransitionDrawable.getId(1));
//oldBitmapDrawable =(BitmapDrawable) (oldTransitionDrawable).getDrawable(1);
}
else if(oldDrawable instanceof BitmapDrawable){
oldBitmapDrawable = (BitmapDrawable) oldDrawable;
}
else{
Log.e(TAG, "Some Error in setImageSourceAndDoAni");
}
if(oldTransitionDrawable==null){
oldTransitionDrawable = new TransitionDrawable(new Drawable[]{
oldBitmapDrawable,
new BitmapDrawable(bitmap)
});
//----------very important!!!
oldTransitionDrawable.setId(0, 0);
oldTransitionDrawable.setId(1, 1);
//----------
oldTransitionDrawable.setCrossFadeEnabled(true);
view.setImageDrawable(oldTransitionDrawable);
}
else{
oldTransitionDrawable.setDrawableByLayerId(oldTransitionDrawable.getId(0), oldBitmapDrawable);
oldTransitionDrawable.setDrawableByLayerId(oldTransitionDrawable.getId(1), new BitmapDrawable(bitmap) );
}
oldTransitionDrawable.startTransition(800);
特别注意在使用过程中下面两行代码:
oldTransitionDrawable.setId(0, 0); oldTransitionDrawable.setId(1, 1);如果不设置的话,你会发现getId(0)和getId(1)都会是0,那么setDrawableByLayerId就会达不到想要的效果。