绘制基础(三)- 头像切割

继续基础View的学习,这回到了头像的处理

本次主要使用到的知识点是canvas.saveLayer:通过saveLayer()、new Canvas(bitmap)这些方法来人为新建一个画布。尤其是saveLayer(),一旦调用saveLayer()新建一个画布以后,以后的所有draw函数所画的图像都是画在这个画布上的,只有当调用restore()、resoreToCount()函数以后,才会返回到原始画布上绘制。实际应该属于图像缓存区,这个在以后再说。

先看下代码实例:

public class AvatarView extends View {

    private static final float WIDTH = UiUtils.dpToPixel(250);
    private static final float PADDING = UiUtils.dpToPixel(50);
    private static final float EDGE = UiUtils.dpToPixel(15);
    private Bitmap bitmap;
    private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    PorterDuffXfermode mode;
    RectF saveArea = new RectF();

    public AvatarView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    {
        bitmap = getAvatar((int) WIDTH);
        mode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
        saveArea.set(PADDING, PADDING, PADDING + WIDTH, PADDING + WIDTH);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 先绘制一个大椭圆
        canvas.drawOval(PADDING - EDGE, PADDING - EDGE,
                PADDING + WIDTH + EDGE, PADDING + WIDTH + EDGE, paint);
        // 开始产生一个透明图层,后续都在此透明图层上绘制
        int saved = canvas.saveLayer(saveArea, paint);
        // 在图层上绘制一个小一点的椭圆
        canvas.drawOval(PADDING, PADDING, PADDING + WIDTH, PADDING + WIDTH, paint);
        // 设置xfermode为SRC_IN,这样新的图,会被上一个椭圆切图
        paint.setXfermode(mode);
        // 绘制bitmap里的图片
        canvas.drawBitmap(bitmap, PADDING, PADDING, paint);
        // 重置paint的xfermode
        paint.setXfermode(null);
        // 重置canvas,并将透明图层绘制到最初界面
        canvas.restoreToCount(saved);
    }

    Bitmap getAvatar(int width) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        // 设为true后,decodeResource()只会取图片的宽高
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(getResources(), R.mipmap.name, options);
        options.inJustDecodeBounds = false;
        options.inDensity = options.outWidth;
        options.inTargetDensity = width;
        return BitmapFactory.decodeResource(getResources(), R.mipmap.name, options);
    }
}

注释了说的很清楚了,看下最终效果:


头像示例

原始图片是一个正方形的头像,最终效果是被一个圆形切割成了圆头像,接着又覆盖在一个比它稍微大点的黑心园,所以还有个黑边。

总结:了解下图层也是挺有意思的。

你可能感兴趣的:(绘制基础(三)- 头像切割)