Android设置图片某几个角为圆角

项目里使用的图片加载框架是Universal-Image-Loader,这个框架本身支持设置圆角图片(RoundedBitmapDisplayer),但是不能够指定那几个角设置为圆角,在网上找到了很好的解决方案(详见http://www.2cto.com/kf/201608/539093.html)

其原理很简单,就是根据RoundedBitmapDisplayer的源码,自己又重新实现了一个FlexibleRoundedBitmapDisplayer,允许构造方法传入哪几个角要设置为圆角,着重重写了其子类FlexibleRoundedDrawable 的draw(Canvas canvas)方法,思路先画一个圆角矩形把这个图片变成圆角,然后想让那个角不是圆角,就把对应角位置那部分的原图画出来即可,画一个矩形就可以把原来的角显示出来,用的方法是drawRect()。
完整源码如下,注释很详细了~~~

/**
 * Created by July on 2017/5/20.
 * Universal-Image-Loader中RoundedBitmapDisplayer的增强版,可以自定义图片 4 个角中的指定角为圆角
 * 

* 思路是先画一个圆角矩形把这个图片变成圆角,然后想让那个角不是圆角,就把对应角位置那部分的原图画出来即可,画一个矩形就可以把原来的角显示出来,用的方法是drawRect() *

*/ public class FlexibleRoundedBitmapDisplayer implements BitmapDisplayer { protected int cornerRadius; protected int corners; // 无圆角,不建议使用 public static final int CORNER_NONE = 0; // 左上角为圆角 public static final int CORNER_TOP_LEFT = 1; // 右上角为圆角 public static final int CORNER_TOP_RIGHT = 1 << 1; // 右下角为圆角 public static final int CORNER_BOTTOM_LEFT = 1 << 2; // 右下角为圆角 public static final int CORNER_BOTTOM_RIGHT = 1 << 3; public static final int CORNER_ALL = CORNER_TOP_LEFT | CORNER_TOP_RIGHT | CORNER_BOTTOM_LEFT | CORNER_BOTTOM_RIGHT; /** * 构造方法说明:设定圆角像素大小,所有角都为圆角 * * @param cornerRadiusPixels 圆角像素大小 */ public FlexibleRoundedBitmapDisplayer(int cornerRadiusPixels) { this.cornerRadius = cornerRadiusPixels; this.corners = CORNER_ALL; } /** * 构造方法说明:设定圆角像素大小,指定角为圆角 * * @param cornerRadiusPixels 圆角像素大小 * @param corners 自定义圆角 CORNER_NONE 无圆角 CORNER_ALL 全为圆角 CORNER_TOP_LEFT | * CORNER_TOP_RIGHT | CORNER_BOTTOM_LEFT | CORNER_BOTTOM_RIGHT * 指定圆角(选其中若干组合 ) */ public FlexibleRoundedBitmapDisplayer(int cornerRadiusPixels, int corners) { this.cornerRadius = cornerRadiusPixels; this.corners = corners; } @Override public void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom) { if (!(imageAware instanceof ImageViewAware)) { throw new IllegalArgumentException("ImageAware should wrap ImageView. ImageViewAware is expected."); } else { imageAware.setImageDrawable(new FlexibleRoundedDrawable(bitmap, cornerRadius, corners)); } } public static class FlexibleRoundedDrawable extends Drawable { protected final float cornerRadius; protected final RectF mRect = new RectF(), mBitmapRect; protected final BitmapShader bitmapShader; protected final Paint paint; private int corners; public FlexibleRoundedDrawable(Bitmap bitmap, int cornerRadius, int corners) { this.cornerRadius = cornerRadius; this.corners = corners; bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mBitmapRect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()); paint = new Paint(); paint.setAntiAlias(true); paint.setShader(bitmapShader); } @Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); mRect.set(0, 0, bounds.width(), bounds.height()); Matrix shaderMatrix = new Matrix(); shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL); bitmapShader.setLocalMatrix(shaderMatrix); } @Override public void draw(Canvas canvas) { // 先画一个圆角矩形将图片显示为圆角 canvas.drawRoundRect(mRect, cornerRadius, cornerRadius, paint); // 异或,相同为0,不同为1 int notRoundedCorners = corners ^ CORNER_ALL; // 哪个角不是圆角再用小矩形画出来(原理类似图层加了一个白蒙板,然后用不透明度100%的黑色画笔去在蒙板上绘制,画笔所过之处你原来的图层就会显现出来) try { if ((notRoundedCorners & CORNER_TOP_LEFT) != 0) { // 左上角恢复为直角 canvas.drawRect(0, 0, cornerRadius, cornerRadius, paint); } if ((notRoundedCorners & CORNER_TOP_RIGHT) != 0) { // 右上角恢复为直角 canvas.drawRect(mRect.right - cornerRadius, 0, mRect.right, cornerRadius, paint); } if ((notRoundedCorners & CORNER_BOTTOM_LEFT) != 0) { // 左下角恢复为直角 canvas.drawRect(0, mRect.bottom - cornerRadius, cornerRadius, mRect.bottom, paint); } if ((notRoundedCorners & CORNER_BOTTOM_RIGHT) != 0) { // 右下角恢复为直角 canvas.drawRect(mRect.right - cornerRadius, mRect.bottom - cornerRadius, mRect.right, mRect.bottom, paint); } } catch (Exception e) { Log.e("FlexibleRoundedBitmapDisplayer ",e + " "); } } @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); } } }

那么怎么使用这个类呢?
在使用UIL时给ImageView设置url时,重载一个方法,其中将builder.displayer()的参数改为上面刚封装的FlexibleRoundedBitmapDisplayer就好了,如下:

public void setRoundedImageUrl(String url, int cornerRadius, int corners, int defaultImage, ImageView imageView) {
        ImageLoader imageLoader = ImageLoader.getInstance();
        DisplayImageOptions options = new DisplayImageOptions.Builder()
                .showImageOnLoading(defaultImage).showStubImage(defaultImage)
                .showImageForEmptyUri(defaultImage)//url为空时显示的图片
                .showImageOnFail(defaultImage)//加载失败显示的图片
                .cacheInMemory()//内存缓存
                .cacheOnDisc()//磁盘缓存
                .displayer(new FlexibleRoundedBitmapDisplayer(cornerRadius, corners))
                .build();
        imageLoader.displayImage(url, imageView, options);
 
    }

一般项目里都会重新封装ImageView,比如UniversalImageView,那么上述方法放在UniversalImageView类里,参数里就不用传ImageView 了,imageLoader.displayImage(url, imageView, options);中的imageView改成this就好了。

public void setRoundedImageUrl(String url, int cornerRadius, int corners, int defaultImage) {
        ImageLoader imageLoader = ImageLoader.getInstance();
        DisplayImageOptions options = new DisplayImageOptions.Builder()
                .showImageOnLoading(defaultImage).showStubImage(defaultImage)
                .showImageForEmptyUri(defaultImage)//url为空时显示的图片
                .showImageOnFail(defaultImage)//加载失败显示的图片
                .cacheInMemory()//内存缓存
                .cacheOnDisc()//磁盘缓存
                .displayer(new FlexibleRoundedBitmapDisplayer(cornerRadius, corners))
                .build();
        imageLoader.displayImage(url, this, options);
 
    }

imageView.setRoundedImageUrl("http://xxx", 22,
FlexibleRoundedBitmapDisplayer.CORNER_TOP_LEFT | FlexibleRoundedBitmapDisplayer.CORNER_TOP_RIGHT);
在给ImageView设置url时,传入圆角的大小(单位px)以及需要哪些角为圆角就可以了。
来张效果图:

Android设置图片某几个角为圆角_第1张图片

完工!

你可能感兴趣的:(Android设置图片某几个角为圆角)