从零开始实现图片加载特效之渐变加载圆角图片

Posted gengqiquan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从零开始实现图片加载特效之渐变加载圆角图片相关的知识,希望对你有一定的参考价值。

尊重他人的劳动成果,转载请标明出处:http://blog.csdn.net/gengqiquan/article/details/53161853, 本文出自:【gengqiquan的博客】

之前有写了一个从零开始实现一个网络图片加载框架,实现了基本的加载网络和图片功能

这篇博客来教大家怎么给图片加载加上特效,本次讲解是基于从零开始实现一个网络图片加载框架的,建议没看过的去看一下,当然,不看也可以,加载特效是可以放在任何获取了bitmap的情况下的

既然是要放在获取bitmap后,那我们就在之前的框架的给imageview设置图片的地方做文章

首先我们定义一个加载器接口,方便以后实现各种各样的加载特效

public interface Displayer 
    void display(Bitmap bm, ImageInfo img);

不同图片的加载特效需求可能不一致,所以我们把加载器绑定给LoaderConfigure,在LoaderConfigure添加一个成员变量,这样我们的LoaderConfigure就变成了这样

public class LoaderConfigure 
    public int loading = 0;//加载占位图资源id
    public int error = 0;//加载失败展位图资源id
    int width = -1;//图片目标宽度
    int height = -1;//图片目标高度
    public boolean roundBitmap = false;//是否圆形图片
    public boolean memoryCache = true;//是否需要内存缓存
    public boolean diskCache = true;//是否需要本地缓存
    public boolean adjust = true;//是否需要按控件大小裁剪
    public boolean cacheBaseImage = false;//是否只缓存原图
    private Displayer displayer;//图片加载器
  

然后将我们之前的直接设置bitmap

    if (bm != null) 
                            bm = ImageUtil.configureImage(bm, imageView, configure);
                            imageView.setImageBitmap(bm);
                        

改成通过加载器进行加载

  if (bm != null) 
                            bm = ImageUtil.configureImage(bm, imageView, configure);
                            configure.getDisplayer().display(bm, imageInfo);

                        

定义一个默认的基础加载器,功能和最初的一样

public class SimpleImageDisplayer implements Displayer 
    @Override
    public void display(Bitmap bm, ImageInfo info) 
        if (bm != null && !bm.isRecycled())
            info.getImageView().setImageBitmap(bm);
    

运行效果和之前是一样的

现在我们写一个有着渐变加载效果的加载器,就是图片由透明状态慢慢变清晰的


public class FadeInImageDisplayer implements Displayer 
    private final int durationMillis;
    private final boolean animateFromNetwork;
    private final boolean animateFromDisk;
    private final boolean animateFromMemory;

    public FadeInImageDisplayer(int durationMillis) 
        this(durationMillis, true, true, true);
    

    public FadeInImageDisplayer(int durationMillis, boolean animateFromNetwork, boolean animateFromDisk, boolean animateFromMemory) 
        this.durationMillis = durationMillis;
        this.animateFromNetwork = animateFromNetwork;
        this.animateFromDisk = animateFromDisk;
        this.animateFromMemory = animateFromMemory;
    
@Override
    public void display(Bitmap bitmap, ImageInfo info) 
        ImageView imageView = info.getImageView();
        LoadedFrom loadedFrom = info.getLoadedFrom();
        imageView.setImageBitmap(bitmap);
        if (this.animateFromNetwork && loadedFrom == LoadedFrom.NETWORK || this.animateFromDisk && (loadedFrom == LoadedFrom.DISC_CACHE || loadedFrom == LoadedFrom.DISC) || this.animateFromMemory && loadedFrom == LoadedFrom.MEMORY_CACHE) 
            animate(imageView, this.durationMillis);
        

    

    public static void animate(View imageView, int durationMillis) 
        if (imageView != null) 
            AlphaAnimation fadeImage = new AlphaAnimation(0.0F, 1.0F);
            fadeImage.setDuration((long) durationMillis);
            fadeImage.setInterpolator(new DecelerateInterpolator());
            imageView.startAnimation(fadeImage);
        

    

通过透明度动画来实现

loadedFrom 类,是记录图片的加载途径,有时候我们从本地或者内存加载的图片,用户可能不能接受等待的特效。需要立刻显示在用户面前

public enum LoadedFrom 
    NETWORK,
    DISC,
    DISC_CACHE,
    MEMORY_CACHE;

    private LoadedFrom() 
    

加载图片时调用

  LoaderConfigure configure = new LoaderConfigure();
        configure.setDisplayer(new FadeInImageDisplayer(2000));
        HelloLoader.bind(mImageView).LoaderConfigure(configure).load(mImageUrl);

看下效果

这里为了效果明显我把时间设置了2秒,大家可以根据实际情况设置。

再写一个支持圆角的加载器,通过canvas来实现


public class RoundImageDisplayer implements Displayer 
    protected final int cornerRadius;
    protected final int margin;

    public RoundImageDisplayer(int cornerRadiusPixels) 
        this(cornerRadiusPixels, 0);
    

    public RoundImageDisplayer(int cornerRadiusPixels, int marginPixels) 
        this.cornerRadius = cornerRadiusPixels;
        this.margin = marginPixels;
    

    public void display(Bitmap bitmap, ImageInfo info) 
        ImageView imageView = info.getImageView();
        imageView.setImageDrawable(new RoundImageDisplayer.RoundedDrawable(bitmap, this.cornerRadius, this.margin));

    

    public static class RoundedDrawable extends Drawable 
        protected final float cornerRadius;
        protected final int margin;
        protected final RectF mRect = new RectF();
        protected final RectF mBitmapRect;
        protected final BitmapShader bitmapShader;
        protected final Paint paint;

        public RoundedDrawable(Bitmap bitmap, int cornerRadius, int margin) 
            this.cornerRadius = (float) cornerRadius;
            this.margin = margin;
            this.bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            this.mBitmapRect = new RectF((float) margin, (float) margin, (float) (bitmap.getWidth() - margin), (float) (bitmap.getHeight() - margin));
            this.paint = new Paint();
            this.paint.setAntiAlias(true);
            this.paint.setShader(this.bitmapShader);
        

        protected void onBoundsChange(Rect bounds) 
            super.onBoundsChange(bounds);
            this.mRect.set((float) this.margin, (float) this.margin, (float) (bounds.width() - this.margin), (float) (bounds.height() - this.margin));
            Matrix shaderMatrix = new Matrix();
            shaderMatrix.setRectToRect(this.mBitmapRect, this.mRect, Matrix.ScaleToFit.FILL);
            this.bitmapShader.setLocalMatrix(shaderMatrix);
        

        public void draw(Canvas canvas) 
            canvas.drawRoundRect(this.mRect, this.cornerRadius, this.cornerRadius, this.paint);
        

        public int getOpacity() 
            return PixelFormat.TRANSLUCENT;
        

        public void setAlpha(int alpha) 
            this.paint.setAlpha(alpha);
        

        public void setColorFilter(ColorFilter cf) 
            this.paint.setColorFilter(cf);
        
    

加载图片时设置圆角600px.边距0px

      LoaderConfigure configure = new LoaderConfigure();
        configure.setDisplayer(new RoundImageDisplayer(600,0));
        HelloLoader.bind(mImageView).LoaderConfigure(configure).load(mImageUrl);

看下效果

完整的示例项目Githu地址 https://github.com/gengqiquan/HelloLoader.git

有什么意见和疑惑欢迎留言

我建了一个QQ群(群号:121606151),用于大家讨论交流android技术问题,有兴趣的可以加下,大家一起进步。

以上是关于从零开始实现图片加载特效之渐变加载圆角图片的主要内容,如果未能解决你的问题,请参考以下文章

【从0开始学Laya】7-如何使用图集和加载资源

Image-Universal-Loader

Glide加载圆角图片的方法

Glide的加载图片的帮助类,用来把图片圆角或者改成圆形图片

Flutter之Decoration(边框圆角阴影形状渐变背景图像等)

jQuery图片渐变特效的简单实现