绘制带圆角的ImageView时的效率

jna*_*man 6 graphics android android-custom-view

我有一个ImageView子类,我用它来绘制带圆角的图像.代码基于这个答案,如下:

public class ImageViewRoundedCorners extends ImageView {
    ...
    @Override
    protected void onDraw(Canvas canvas) {
        Bitmap scaledBitmap = Bitmap.createBitmap(getMeasuredWidth(),
                                                  getMeasuredHeight(),
                                                  Bitmap.Config.ARGB_8888); 
        Canvas scaledCanvas = new Canvas(scaledBitmap);
        super.onDraw(scaledCanvas); 
        drawRoundedCornerBitmap(canvas, scaledBitmap, 
                                getMeasuredWidth(), getMeasuredHeight());

        scaledBitmap.recycle();
    }

    protected void drawRoundedCornerBitmap(Canvas outputCanvas, Bitmap input, int w, int h) {
        Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        mPaint.reset();
        mPaint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);

        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawPath(mClipPath, mPaint);

        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(input, 0, 0, mPaint);

        outputCanvas.drawBitmap(output, 0, 0, null);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用此代码,可以使用正确的圆角绘制图像.为了避免前两行的分配drawRoundedCornerBitmap,我想直接绘制outputCanvas,这是最初传递给的画布onDraw.新实现如下所示:

protected void drawRoundedCornerBitmap(...) {
    mPaint.reset();
    mPaint.setAntiAlias(true);
    outputCanvas.drawARGB(0, 0, 0, 0);

    mPaint.setStyle(Paint.Style.FILL);
    outputCanvas.drawPath(mClipPath, mPaint);

    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    outputCanvas.drawBitmap(input, 0, 0, mPaint);
}
Run Code Online (Sandbox Code Playgroud)

出于某种原因,此代码似乎忽略了Porter-Duff模式,而只是使用普通(非圆角)角绘制图像.为什么会这样?绘制到Bitmap使原始代码有效的中间体是什么意思?

Chr*_*ins 0

创建一个可绘制的 Romain Guy 已为您完成此操作。我们不是链接工厂,但他的博客文章对此进行了相当广泛的解释,并提供了一种有效的方法。圆角

真正的基本原则是创建BitmapShader并将其附加到一个Paint以自定义方式绘制的对象Drawable,这样您只需将其应用DrawableImageView.

使用可绘制对象意味着图像仅绘制到画布一次,这意味着绘制图像仅完成一次,然后 ImageView 所做的只是缩放可绘制对象。