ImageLoader这个图片加载器是我经常使用额一个图片加载器(https://github.com/nostra13/Android-Universal-Image-Loader)
这个图片加载器在加载的时候是支持图片加载效果的,原本自带了RoundBitmapDisplayer,圆角图片显示器。
但是项目的需要,我要弄一个圆形的图片,这样有两个思路,
其一,是弄一个CircleImageView 直接改写ImageView 以达到圆形图片的效果
但是这样有个问题,就是在列表加载的时候,这个图片是不能缓存的,每次都是用重新切图
其二,使用ImageLoader的BitmapDisplayer ,这个出来的图片是可以缓存到内存中的,所以在列表中加载比较有优势
下面就是实现这种功能代码
首先我们要实现一个最重要的CircleDrawable,就是靠这个实现了圆形的功能
package auggie.library.displayers; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.Shader; import android.graphics.drawable.Drawable; /** * Created With Android Studio * User @47 * Date 2014-07-28 * Time 0:32 */ public class CircleDrawable extends Drawable { public static final String TAG = "CircleDrawable"; protected final Paint paint; protected final int margin; protected final BitmapShader bitmapShader; protected float radius; protected Bitmap oBitmap;//原图 public CircleDrawable(Bitmap bitmap){ this(bitmap,0); } public CircleDrawable(Bitmap bitmap, int margin) { this.margin = margin; this.oBitmap = bitmap; bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); paint = new Paint(); paint.setAntiAlias(true); paint.setShader(bitmapShader); } @Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); computeBitmapShaderSize(); computeRadius(); } @Override public void draw(Canvas canvas) { Rect bounds = getBounds();//画一个圆圈 canvas.drawCircle(bounds.width() / 2F,bounds.height() / 2F,radius,paint); } @Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } @Override public void setAlpha(int alpha) { paint.setAlpha(alpha); } @Override public void setColorFilter(ColorFilter cf) { paint.setColorFilter(cf); } /** * 计算Bitmap shader 大小 */ public void computeBitmapShaderSize(){ Rect bounds = getBounds(); if(bounds == null) return; //选择缩放比较多的缩放,这样图片就不会有图片拉伸失衡 Matrix matrix = new Matrix(); float scaleX = bounds.width() / (float)oBitmap.getWidth(); float scaleY = bounds.height() / (float)oBitmap.getHeight(); float scale = scaleX > scaleY ? scaleX : scaleY; matrix.postScale(scale,scale); bitmapShader.setLocalMatrix(matrix); } /** * 计算半径的大小 */ public void computeRadius(){ Rect bounds = getBounds(); radius = bounds.width() < bounds.height() ? bounds.width() /2F - margin: bounds.height() / 2F - margin; } }
接着就是CircleBitmapDisplayer 这个外壳
package auggie.library.displayers; import android.graphics.Bitmap; import com.nostra13.universalimageloader.core.assist.LoadedFrom; import com.nostra13.universalimageloader.core.display.BitmapDisplayer; import com.nostra13.universalimageloader.core.imageaware.ImageAware; import com.nostra13.universalimageloader.core.imageaware.ImageViewAware; /** * Created With Android Studio * User @47 * Date 2014-07-27 * Time 20:55 * 显示原型图片的ImageLoader使用的显示器 * */ public class CircleBitmapDisplayer implements BitmapDisplayer { protected final int margin ; public CircleBitmapDisplayer() { this(0); } public CircleBitmapDisplayer(int margin) { this.margin = margin; } @Override public void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom) { if (!(imageAware instanceof ImageViewAware)) { throw new IllegalArgumentException("ImageAware should wrap ImageView. ImageViewAware is expected."); } imageAware.setImageDrawable(new CircleDrawable(bitmap, margin)); } }
这样着在ImageLoader 那里使用就可以了
package org.hangox.circleimageview; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.widget.ImageView; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import auggie.library.displayers.CircleBitmapDisplayer; public class MainActivity extends ActionBarActivity { ImageView iViewCircleImageDisplayer; String imageUrl = "http://d.hiphotos.baidu" + ".com/image/pic/item/9358d109b3de9c8242a7de176e81800a18d84363.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iViewCircleImageDisplayer = (ImageView) findViewById(R.id.circle_image_displayer); ImageLoader.getInstance().displayImage(imageUrl,iViewCircleImageDisplayer,options); // BitmapDrawable bitmapDrawable = (BitmapDrawable) getResources().getDrawable(R.drawable.test_personal); // iViewCircleImageDisplayer.setImageDrawable(new CircleDrawable(bitmapDrawable.getBitmap())); } DisplayImageOptions options = new DisplayImageOptions.Builder() .cacheInMemory(true) .cacheOnDisk(true) .displayer(new CircleBitmapDisplayer()) .build(); }
效果图:
总结:其实我想想做第一种的,结果我就做第二种的,发现第二种可以曲线实现第一种,就是把ImageView里面的Drawable
替换为CircleBitmapDislplayer ,其实这个我是写了的,在分开库的时候不知道为什么代码不见了。。。。。。。。
不过,这个库应该会继续更新,可能会用更多的显示效果