Android绘制圆形图片的3个方法

在日常开发中,我们经常需要用到圆形图片,最近总结了3个绘制圆形图片的方法,在这里总结一下

BitmapShader

BitmapShaderShader 的子类,Shader 是 画笔的着色器,是用于给画布着色,利用 BitmapShader ,我们可以给画布绘制一个圆形图片:

public class CircleHeadView extends View {
    private Paint mPaint;
    ....
    {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //Shader.TileMode.CLAMP为拉伸图片铺满
        BitmapShader bitmapShader = new BitmapShader(getBitmap(dp2px(100))
                , Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        mPaint.setShader(bitmapShader);
    }  
    
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制一个圆形,圆形的颜色就是我们指定的图片
        canvas.drawCircle(dp2px(50), dp2px(50), dp2px(50), mPaint);
    }
    
    private Bitmap getBitmap(int width) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(getResources(), R.drawable.bg_header, options);
        options.inJustDecodeBounds = false;
        //设置位图的屏幕密度,即每英寸有多少个像素
        options.inDensity = options.outWidth;
        //设置位图被画出来时的目标像素密度
        //与options.inDensity配合使用,可对图片进行缩放
        options.inTargetDensity = width;
        return BitmapFactory.decodeResource(getResources(), R.drawable.bg_header, options);
    }

    /**
     * 将dp或dp值转换为px值,保证尺寸大小不变
     */
    private int dp2px(float dpValue) {
        float scale = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue
                , Resources.getSystem().getDisplayMetrics());
        return (int) (scale + 0.5f);
    }
}

可以看到运行结果:

Android绘制圆形图片的3个方法_第1张图片

一个漂亮的圆形图片就出来了

PorterDuffXfermode

使用图像混合模式,我们也可以很简单弄出一个圆形图片:

public class CircleHeadView extends View {
    private Paint mPaint;
    ....
       {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//        BitmapShader mBitmapShader = new BitmapShader(getBitmap(dp2px(100))
//                , Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
//        mPaint.setShader(mBitmapShader);
	    //设置图像混合模式
        mPorterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
        //开启软件加速
        setLayerType(View.LAYER_TYPE_SOFTWARE, mPaint);
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //设置离线缓存层,图像混合计算都需要在上面计算,从而生成新的图像
        int save = canvas.saveLayer(dp2px(50), dp2px(50)
                , dp2px(150), dp2px(150), mPaint, Canvas.ALL_SAVE_FLAG);
        canvas.drawCircle(dp2px(100), dp2px(100)
                , dp2px(50), mPaint);
        mPaint.setXfermode(mPorterDuffXfermode);
        canvas.drawBitmap(getBitmap(dp2px(100)), dp2px(50), dp2px(50), mPaint);
        mPaint.setXfermode(null);
        //恢复画布,将图像绘制到上面
        canvas.restoreToCount(save);
    }
    
    private Bitmap getBitmap(int width) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(getResources(), R.drawable.bg_header, options);
        options.inJustDecodeBounds = false;
        //设置位图的屏幕密度,即每英寸有多少个像素
        options.inDensity = options.outWidth;
        //设置位图被画出来时的目标像素密度
        //与options.inDensity配合使用,可对图片进行缩放
        options.inTargetDensity = width;
        return BitmapFactory.decodeResource(getResources(), R.drawable.bg_header, options);
    }

    /**
     * 将dp或dp值转换为px值,保证尺寸大小不变
     */
    private int dp2px(float dpValue) {
        float scale = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue
                , Resources.getSystem().getDisplayMetrics());
        return (int) (scale + 0.5f);
    }
}

可以看到运行结果:

Android绘制圆形图片的3个方法_第2张图片

关于图片混合模式,建议看 Hencoder 这文章,里面说的很详细了,这里就不多说了

Canvas的clipPath

我们还可以使用裁剪画布的方法来弄出一个圆形的图片,在执行了 clipPath 方法后,绘制都会限制在裁剪的范围里面:

public class CircleHeadView extends View {
    private Paint mPaint;
    private Path mClipPath;//用于固定裁剪的范围
    private RectF mRectF;//用于固定图片的绘制范围
    ..........
    {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mClipPath = new Path();
        mClipPath.addCircle(dp2px(150), dp2px(150), dp2px(50)
                , Path.Direction.CW);
        mRectF = new RectF();
        mRectF.set(dp2px(100), dp2px(100), dp2px(200), dp2px(200));
        //开启软件加速
        setLayerType(View.LAYER_TYPE_SOFTWARE, mPaint);
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //这里需要开启离屏缓存层,裁剪过程应该放在离屏缓存层,避免对原画布产生影响
        int saveCount = canvas.saveLayer(dp2px(100), dp2px(100)
                , dp2px(200), dp2px(200), mPaint, Canvas.ALL_SAVE_FLAG);
        //裁剪画布
        canvas.clipPath(mClipPath);
        //在指定范围内绘制图片
        canvas.drawBitmap(getBitmap(dp2px(100)), null, mRectF, mPaint);
       //将离屏缓存的绘制复制到画布上面
        canvas.restoreToCount(saveCount);
    }

    private Bitmap getBitmap(int width) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(getResources(), R.drawable.bg_header, options);
        options.inJustDecodeBounds = false;
        //设置位图的屏幕密度,即每英寸有多少个像素
        options.inDensity = options.outWidth;
        //设置位图被画出来时的目标像素密度
        //与options.inDensity配合使用,可对图片进行缩放
        options.inTargetDensity = width;
        return BitmapFactory.decodeResource(getResources(), R.drawable.bg_header, options);
    }

    /**
     * 将dp或dp值转换为px值,保证尺寸大小不变
     */
    private int dp2px(float dpValue) {
        float scale = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue
                , Resources.getSystem().getDisplayMetrics());
        return (int) (scale + 0.5f);
    }
}

可以看到运行效果:

Android绘制圆形图片的3个方法_第3张图片

你可能感兴趣的:(Android)