如何使用RoundedBitmapDrawable?

65

有人成功使用RoundedBitmapDrawable吗?如果我理解的不对,请纠正我,但据我所知,它可以将常规矩形图像变成圆形图像。

到目前为止,我尝试的是这个:

RoundedBitmapDrawable.createRoundedBitmapDrawable(getResources(), BitmapFactory.decodeResource(getResources(), iconResource))

我尝试实现的目标是:将任何图像转换为圆形图像并使用ImageView显示。

如果我把事情搞混了,或者我所说的一切都是无意义的。是否可能(或更简单)使用任何新框架来完成它?(Android L或新的Support库)


你从这里得到了什么? - Pratik Dasa
原始图像(正方形图像) - gian1200
我认为你需要使用第三方库。 - Pratik Dasa
请查看 https://github.com/MostafaGazar/CustomShapeImageView API。 - Jaiprakash Soni
8个回答

125

您需要设置圆角半径。

Resources res = getResources();
Bitmap src = BitmapFactory.decodeResource(res, iconResource);
RoundedBitmapDrawable dr =
    RoundedBitmapDrawableFactory.create(res, src);
dr.setCornerRadius(Math.max(src.getWidth(), src.getHeight()) / 2.0f);
imageView.setImageDrawable(dr);

1
谢谢您的回答。我也找到了那个方法。只有一个问题,为什么要使用Math.max和getHeight/getWidth/2;而不是dr.setCornerRadius(Math.min(dr.getMinimumWidth(),dr.getMinimumHeight() - gian1200
你是对的,那样更好。我想由于RoundedBitmapDrawable约束了角半径,它们实际上可能会返回相同的结果。只传入宽度或高度也可能有效。 - alanv
RoundedBitmapDrawableFactory 只有一个 "create()" 函数,而没有 "createRoundedBitmapDrawable",两者都使用相同的参数,我做错了什么? - Miko Diko
19
dr.setCircular(true) - don't panic
2
非正方形的图像作为输入怎么办?根据我所看到的,输出在这种情况下会被拉伸。有没有使用中心裁剪的方法? - android developer
显示剩余2条评论

70

可能有些晚了,但我希望对其他人有所帮助。

如果您的图像具有相同的宽度和高度,则可以将 setCircular 设置为 true,以获得圆形位图,如下所示。

RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(getResources(),your_bitmap);
drawable.setCircular(true);

1
简单,卓越! - Tash Pemhiwa
3
工具栏图标不接受 RoundedBitmapDrawable,那么我该如何从中获取圆角位图?使用 getBitmap 方法只能返回原始位图。 - Cerlin
当输入图像不是正方形(例如长方形),输出的圆形图像内容会被拉伸。是否有任何方法可以实现中心裁剪机制? - android developer

9

我也在寻找圆形图片视图,为了效率,我搜索了所有第三方库,发现它们都会创建新的位图,这在列表中是一项繁琐的任务,会消耗更多的内存。

参考库:

  1. http://ruibm.com/2009/06/16/rounded-corner-bitmaps-on-android/
  2. https://github.com/vinc3m1/RoundedImageView
  3. https://github.com/lopspower/CircularImageView

我使用了这个库

https://github.com/vinc3m1/RoundedImageView

因为这是一个快速的ImageView(和Drawable),支持基于Romain Guy原始示例的圆角(以及椭圆形或圆形)。
  • 不创建原始位图的副本
  • 不使用未经硬件加速和未反锯齿的clipPath。
  • 不使用setXfermode来裁剪位图并在画布上绘制两次。

7

完整代码:

ImageView img= (ImageView) findViewById(R.id.yourimageid);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.yourpictureresource);

RoundedBitmapDrawable rnd = (RoundedBitmapDrawable) RoundedBitmapDrawableFactory.create(getResources(), bitmap);
rnd.setCircular(true);
img.setImageDrawable(rnd);

4
我创建了一个实用类来创建圆角位图(RoundedBitmapDrawables),可以用于创建圆形和圆角矩形。 https://gist.github.com/lawloretienne/a91fb0ce40f083073d4b8939281b3ecb
public class RoundedBitmapDrawableUtility {

    public static RoundedBitmapDrawable getRoundedSquareBitmapDrawable(Context context, Bitmap originalBitmap, int cornerRadius){
        return getRoundedSquareBitmapDrawable(context, originalBitmap, cornerRadius, -1, -1);
    }


    public static RoundedBitmapDrawable getRoundedSquareBitmapDrawable(Context context, Bitmap originalBitmap, int cornerRadius, int borderWidth, int borderColor){
        int originalBitmapWidth = originalBitmap.getWidth();
        int originalBitmapHeight = originalBitmap.getHeight();

        if(borderWidth != -1 && borderColor != -1){
            Canvas canvas = new Canvas(originalBitmap);
            canvas.drawBitmap(originalBitmap, 0, 0, null);

            Paint borderPaint = new Paint();
            borderPaint.setStyle(Paint.Style.STROKE);
            borderPaint.setStrokeWidth(borderWidth);
            borderPaint.setAntiAlias(true);
            borderPaint.setColor(borderColor);

            int roundedRectDelta = (borderWidth/3);
            RectF rectF = new RectF(0 + roundedRectDelta, 0 + roundedRectDelta, originalBitmapWidth - roundedRectDelta, originalBitmapHeight - roundedRectDelta);
            canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, borderPaint);
        }

        RoundedBitmapDrawable roundedImageBitmapDrawable = RoundedBitmapDrawableFactory.create(context.getResources(), originalBitmap);
        roundedImageBitmapDrawable.setCornerRadius(cornerRadius);
        roundedImageBitmapDrawable.setAntiAlias(true);
        return roundedImageBitmapDrawable;
    }

    public static RoundedBitmapDrawable getCircleBitmapDrawable(Context context, Bitmap originalBitmap){
        return getCircleBitmapDrawable(context, originalBitmap, -1, -1);
    }

    public static RoundedBitmapDrawable getCircleBitmapDrawable(Context context, Bitmap originalBitmap, int borderWidth, int borderColor){
        if(borderWidth != -1 && borderColor != -1) {
            Canvas canvas = new Canvas(originalBitmap);
            canvas.drawBitmap(originalBitmap, 0, 0, null);

            Paint borderPaint = new Paint();
            borderPaint.setStyle(Paint.Style.STROKE);
            borderPaint.setStrokeWidth(borderWidth);
            borderPaint.setAntiAlias(true);
            borderPaint.setColor(borderColor);

            int circleDelta = (borderWidth / 2) - DisplayUtility.dp2px(context, 1);
            int radius = (canvas.getWidth() / 2) - circleDelta;
            canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, radius, borderPaint);
        }

        RoundedBitmapDrawable roundedImageBitmapDrawable = RoundedBitmapDrawableFactory.create(context.getResources(), originalBitmap);
        roundedImageBitmapDrawable.setCircular(true);
        roundedImageBitmapDrawable.setAntiAlias(true);
        return roundedImageBitmapDrawable;
    }
}

2
我建议另一种选择: 您可以使用这种方法,根据您的需求进行缩放,避免出现此异常:
public static Bitmap scaleBitmapAndKeepRation(Bitmap TargetBmp, int reqHeightInPixels, int reqWidthInPixels) {
        if (TargetBmp != null) {

            if (TargetBmp.getWidth() >= TargetBmp.getHeight()) {

                TargetBmp = Bitmap.createBitmap(
                        TargetBmp,
                        TargetBmp.getWidth() / 2 - TargetBmp.getHeight() / 2,
                        0,
                        TargetBmp.getHeight(),
                        TargetBmp.getHeight()
                );

            } else {

                TargetBmp = Bitmap.createBitmap(
                        TargetBmp,
                        0,
                        TargetBmp.getHeight() / 2 - TargetBmp.getWidth() / 2,
                        TargetBmp.getWidth(),
                        TargetBmp.getWidth()
                );
            }

            if (TargetBmp != null) {
                try {
                    Matrix m = new Matrix();
                    m.setRectToRect(new RectF(0, 0, TargetBmp.getWidth(), TargetBmp.getHeight()), new RectF(0, 0, reqWidthInPixels, reqHeightInPixels), Matrix.ScaleToFit.FILL);
                    Bitmap scaledBitmap = Bitmap.createBitmap(TargetBmp, 0, 0, TargetBmp.getWidth(), TargetBmp.getHeight(), m, true);
                    return scaledBitmap;
                } catch (Exception e) {
                    Log.e("Utils", e.toString());
                    return null;
                }
            }
            return null;
        } else
            return null;
    }

2

1
如果您有图像路径而不是位图,则可以按以下方式传递图像路径:
// set round image
RoundedBitmapDrawable dr = RoundedBitmapDrawableFactory.create(getResources(), avatarImgPath);
dr.setCircular(true);
avatarImageView.setImageDrawable(dr);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接