用TransitionDrawable实现ImageView渐隐渐显过渡效果,并解决OutOfMemory问题

感谢 http://adk.tumblr.com/post/13069401302/outofmemoryerror-imageview-and-transitiondrawable-a

1、实现ImageView的渐隐渐现的效果

实现两张图片渐隐渐现的过渡效果,大家马上回想到使用TransitionDrawable来实现,这方面的例子网上挺多:
比在布局文件中使用translation实现
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/image_expand" />
    <item android:drawable="@drawable/image_collapse" />
</transition>

在Java中使用代码:
    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);


最近在项目中的使用第二钟方法来实现在gridview中显示大量从网络下载的图片显示的情况。gridview中最多要显示2000多种图片,就在adapter的getView方法中开启synctask来下载图片,下载完成后就更新到UI,并实现渐隐渐现的动画效果。
注意到这里的问题了,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就会达不到想要的效果。

你可能感兴趣的:(用TransitionDrawable实现ImageView渐隐渐显过渡效果,并解决OutOfMemory问题)