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

作者: Vivi成长吧 | 来源:发表于2017-05-20 15:13 被阅读131次

    项目里使用的图片加载框架是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 个角中的指定角为圆角
     * <p>
     * 思路是先画一个圆角矩形把这个图片变成圆角,然后想让那个角不是圆角,就把对应角位置那部分的原图画出来即可,画一个矩形就可以把原来的角显示出来,用的方法是drawRect()
     * </p>
     */
    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设置图片某几个角为圆角

        本文链接:https://www.haomeiwen.com/subject/uvkpxxtx.html