有时候我们项目需要加载网络圆形图片 比如头像等,在这里我用的是Glide来加载圆形图的。
首先先把代码写下来:
RequestOptions optionsCircle = new RequestOptions();
DrawableTransitionOptions transitionOptions = new DrawableTransitionOptions();
Glide.with(mContext) .load(url) .apply(optionsCircle.transform(new GlideCircleTransform())).transition(transitionOptions.crossFade()) .into(imageView);
实现圆形图的是调用transform(new GlideCircleTransform()),GlideCircleTransform自定义继承BitmapTransformation实现的,代码如下:
public class GlideCircleTransform extends BitmapTransformation {
public GlideCircleTransform() { uper(); }
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
return circleCrop(pool, toTransform);
}
private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
if (source == null) return null;
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
if (result == null) { result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); } Canvas canvas = new Canvas(result);
Paint paint = new Paint();
paint.setShader(newBitmapShader(squared,BitmapShader.TileMode.CLAMP,BitmapShader.TileMode.CLAMP));
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
return result; }
@Override
public void updateDiskCacheKey(MessageDigest messageDigest) { }
}
到此我们就实现了使用Glide加载圆形图了。查看代码发现核心方法是circleCrop(BitmapPool pool, Bitmap source)实现的。它是用canvas来画圆图的,
Paint paint = new Paint();
paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
paint.setAntiAlias(true);
canvas.drawCircle(r, r, r, paint);
这是核心代码,发现是把bitmap赋值到paint来实现的,所以通过观察发现paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));这行代码我们用的很少,接下来就是重点介绍这行代码:
点进去查看源码发现,具体代码就不再这写了,可以自己查看。
setShader(Shader shader){
................
}
我们发现用到了一个类Shader,点进去看,发现对它的解释是这样的,
Shader is the based class for objects that return horizontal spans of colors during drawing. A subclass of Shader is installed in a Paint calling paint.setShader(shader). After that any object (other than a bitmap) that is drawn with that paint will get its color(s) from the shader.
解释就是:Shader 是用于在绘图期间返回颜色水平范围的对象的基类。它的子类被安装在一个叫Paint . setshader (Shader)的中。之后,绘制的任何对象(除了位图之外)都将从Shader 中得到它的颜色。
因此我们就知道了,我们是如何使用canvas画出圆图得了。而且BitmapShader 就是shader的子类,BitmapShader 就是用来将图片来进行绘制的。
BitmapShader (Bitmap bitmap,Shader.TileMode tileX, Shader.TileMode tileY)
很多人对最后两个参数比较疑惑,点进去发现就是个枚举:
public enum TileMode {
/** * replicate the edge color if the shader draws outside of its original bounds */
CLAMP (0),
/** * repeat the shader's image horizontally and vertically */
REPEAT (1),
/** * repeat the shader's image horizontally and vertically, alternating mirror images so that adjacent images always seam */ MIRROR (2);
TileMode(int nativeInt) { this.nativeInt = nativeInt; }
final int nativeInt; }
发现可以通过tiling mode来达到镜面和重复等效果。
那么为了更直观的观察他们的区别我们可以自定义一个view来查看他们的区别,我们只需实现以下就可以查看了:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int w = getWidth();
int h = getHeight();
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.mipmap.dog);
mShader =new BitmapShader(bmp, Shader.TileMode.REPEAT,Shader.TileMode.REPEAT);
mPaint.setShader(mShader);
canvas.drawRect(0,0,w,h,mPaint);
}
然后我们在布局里:
android:layout_width="match_parent"
android:layout_height="400dp"/>
调用我们自定义的view即可 就可以了查看效果了。我们可以把Shader.TileMode.REPEAT,再替换成Shader.TileMode.MIRROR,Shader.TileMode.CLAMP来查看各自的效果,当然BitmapShader (Bitmap bitmap,Shader.TileMode tileX, Shader.TileMode tileY),最后两个参数是不需要保持一样,通过自己动手,可以很多好玩的东西。具体的可以自己试试,在这就不粘贴效果图了。通过学习Glide4.0 使用 +圆形图,我们发现了一个好玩的类Shader,我们可以用它实现很多东西,不仅仅局限于圆形图。等我们什么时候需要用到canvas时,我们就可以考虑是否可以用Shader来实现功能。