在圆圈中绘制位图并填充外部颜色画布不起作用

时间:2018-05-23 06:49:02

标签: android canvas bitmap geometry

我想用位图在圆圈内绘制图像并在外面填充颜色。

我扩展了AppCompatImageView并覆盖了onDraw方法,但它在画布中显示了白色圆圈。

以下是我的课程:

{{1}}

在没有外部矩形或画布填充颜色的情况下绘制位图时工作正常。但我需要用位图填充外部颜色。

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

以下是我之前在遇到相同问题时编写的代码,您可能希望使用以下类:

public class CircleImageView extends AppCompatImageView {
    private RectF drawableRect = new RectF();
    private Matrix shaderMatrix = new Matrix();
    private Paint bmpPaint = new Paint();
    private Paint backgroundPaint = new Paint();
    private Bitmap bmp;
    private int bmpWidth, bmpHeight;
    private BitmapShader bmpShader;
    private float radius;


    public CircleImageView(Context context) {
        super(context);
        setScaleType(ScaleType.CENTER_CROP);
        backgroundPaint.setStyle(Paint.Style.FILL);
        backgroundPaint.setColor(Color.TRANSPARENT);
        init();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (bmp == null) return;
        canvas.drawPaint(backgroundPaint);
        canvas.drawCircle(drawableRect.centerX(), drawableRect.centerY(), radius, bmpPaint);
    }



    private Bitmap getBitmapFromDrawable(Drawable drawable) {
        if (drawable == null) return null;
        if (drawable instanceof BitmapDrawable) return ((BitmapDrawable) drawable).getBitmap();
        try {
            Bitmap bitmap;
            if (drawable instanceof ColorDrawable) bitmap = Bitmap.createBitmap(5, 5, Bitmap.Config.ARGB_8888);
                         else bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
            drawable.draw(canvas);
            return bitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private void initImage() {
        bmp = getBitmapFromDrawable(getDrawable());
        init();
    }

    private void init() {
        if (getWidth() == 0 && getHeight() == 0) return;
        if (bmp == null) {invalidate();return;}

        bmpShader = new BitmapShader(bmp, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        bmpPaint.setAntiAlias(true);
        bmpPaint.setShader(bmpShader);
        bmpHeight = bmp.getHeight();
        bmpWidth = bmp.getWidth();
        drawableRect.set(new RectF(0,0,getWidth(),getHeight()));
        radius = Math.min(drawableRect.height() / 2.0f, drawableRect.width() / 2.0f);
        updateMatrix();
        invalidate();
    }


    private void updateMatrix() {
        float scale;
        float dx = 0;
        float dy = 0;
        shaderMatrix.set(null);
        if (bmpWidth * drawableRect.height() > drawableRect.width() * bmpHeight) {
            scale = drawableRect.height() / (float) bmpHeight;
            dx = (drawableRect.width() - bmpWidth * scale) * 0.5f;
        } else {
            scale = drawableRect.width() / (float) bmpWidth;
            dy = (drawableRect.height() - bmpHeight * scale) * 0.5f;
        }

        shaderMatrix.setScale(scale, scale);
        shaderMatrix.postTranslate((int) (dx + 0.5f) + drawableRect.left, (int) (dy + 0.5f) + drawableRect.top);
        bmpShader.setLocalMatrix(shaderMatrix);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        init();
    }

    public void setBackgroundColor(@ColorInt int backgroundColor) {
        backgroundPaint.setColor(backgroundColor);
        invalidate();
    }

    @Override
    public void setImageBitmap(Bitmap bm) {
        super.setImageBitmap(bm);
        initImage();
    }

    @Override
    public void setImageDrawable(Drawable drawable) {
        super.setImageDrawable(drawable);
        initImage();
    }

    @Override
    public void setImageResource(@DrawableRes int resId) {
        super.setImageResource(resId);
        initImage();
    }

    @Override
    public void setImageURI(Uri uri) {
        super.setImageURI(uri);
        initImage();
    }

    /* if this answer solved your problem please mark it as accepted by clicking the check mark next to the answer. Thank you */
}