android圆形图片效果

前言

App展示的图片通常都是长方形,这种展示方式非常单调而且古板。图像的直角让人感觉比较尖锐不是那么的友好,因而一些用户头像通常都要求展示带有圆角效果,相对来说带圆角的图片整体感觉更加柔和。圆角效果可以让设计切图,但是这种方式工作量比较大,很浪费设计的工作效率,在项目中往往都是前端实现。现在来讨论一下在android前端实现圆角效果实现方式。

PorterDuff效果实现

PorterDuff是一种定义图形混合的处理技术,它有点类似于数学集合学上的文式图。可以把图片里的像素想像成集合的元素,两个图片之间做各种并交差等集合运算,最后剩下来的像素点就是处理的结果。在PorterDuff里有目标图片dst其实就是在画布上先放上去的图片,源图片src会被放到目标图片上做处理。至于处理的细节可以在查看网络的这篇博客:http://blog.csdn.net/t12x3456/article/details/10432935,里面以图片的方式展示了各种叠加效果。
现在考虑实现图片的圆形效果,首先需要把原来的矩形图片放到画布上去也就是dst图片,再找一个圆形的src图片放在矩形图片上面。分析一下最后需要留下的只有圆形里面的dst图片部分,所有使用DST_IN这种处理效果最合适。实现代码如下:

// 需要圆角处理的图片
Bitmap photo = BitmapFactory.decodeResource(getResources(), R.drawable.progress_loading_image_02);
Bitmap dst = Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888); // 目标图片
Bitmap src = dst.copy(Bitmap.Config.ARGB_8888, true); // 源图片
Bitmap b3 = dst.copy(Bitmap.Config.ARGB_8888, true); // 生成的结果图片

Canvas canvas1 = new Canvas(dst);
Canvas canvas2 = new Canvas(src);
Canvas canvas3 = new Canvas(b3);

Paint paint1 = new Paint();
Rect rect1 = new Rect(0, 0, photo.getWidth(), photo.getHeight());
Rect rect2 = new Rect(0, 0, 300, 300);
canvas1.drawBitmap(photo, rect1, rect2, paint1); // 把目标图片画到画布上

Paint paint2 = new Paint();
paint2.setStrokeWidth(2);
paint2.setStyle(Paint.Style.FILL);
paint2.setColor(Color.RED);
canvas2.drawCircle(150, 150, 150, paint2); // 把带圆的图片画到画布上

// 需要在新的图层上进行porterduff处理,如果不用图层porterduff没有效果(不知道为什么?哪位大神能告诉下)
Paint paint = new Paint();
int layer = canvas3.saveLayer(0, 0, 300, 300, paint, Canvas.ALL_SAVE_FLAG); 
canvas3.drawBitmap(dst, 0, 0, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas3.drawBitmap(src, 0, 0, paint);
canvas3.restoreToCount(layer);

paint.setXfermode(null);
canvas.drawBitmap(b3, 0, 0, paint);

这种处理方式比较麻烦,需要使用到Canvas的图层才能保证效果展示正确,在项目中并没有使用这种复杂的方式,主要用于学习目的。

Canvas ClipPath实现

对画布执行剪切操作会导致以后所有的绘画操作只展示在剪切区域中,剪切区域之外的内容都不会展示出来。为了不影响后面的onDraw画图,需要对画布执行save/restore操作。分析圆形图像实际展示的只有圆形内部的区域,代码实现如下:

canvas.save();
Path path = new Path();
path.addCircle(300, 300, 200, Path.Direction.CCW); // 画一个圆形的path
canvas.clipPath(path); // 裁剪画布的区域为圆形
RectF rectF = new RectF(100, 100, 500, 500);
canvas.drawBitmap(photo, null, rectF, paint); // 在区域之外的部分不会被渲染出来
canvas.restore();

两个代码实现效果如下:
这里写图片描述

BitmapShader实现

Shader也就是所谓的着色器,用户使用画笔工具绘画的时候实际上相当于使用一个一个点来绘制图片,如果画笔的着色直接使用一副图片,再画出来的圆就可以绘制出圆形的图片。实现代码如下:

public class RoundCornerImageView extends ImageView {
    private BitmapShader bitmapShader;
    private Bitmap bitmap;
    private Paint paint;
    public RoundCornerImageView(Context context) {
        super(context);
        init(context);
    }

    public RoundCornerImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public RoundCornerImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.nothing_image);
        bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        paint = new Paint();
        paint.setShader(bitmapShader);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawCircle(150, 150, 150, paint);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值