在Android中,ImageView默认是一个矩形。如何使它成为一个圆角矩形(剪辑我的位图的所有4个角为圆角矩形)在ImageView?


请注意,从2021年起,只需使用ShapeableImageView


当前回答

虽然上面的答案是可行的,Romain Guy(核心Android开发人员)在他的博客中展示了一个更好的方法,通过使用着色器而不是创建位图的副本来使用更少的内存。该功能的一般要点如下:

BitmapShader shader;
shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);

RectF rect = new RectF(0.0f, 0.0f, width, height);

// rect contains the bounds of the shape
// radius is the radius in pixels of the rounded corners
// paint contains the shader that will texture the shape
canvas.drawRoundRect(rect, radius, radius, paint);

与其他方法相比,这种方法的优点是:

不创建一个单独的位图副本,对于大图像使用大量内存[相对于这里的大多数其他答案] 支持反锯齿[vs clipPath方法] 支持alpha [vs xfermode+porterduff方法] 支持硬件加速[vs clipPath方法] 只在画布上绘制一次[相对于xfermode和clippath方法]

我创建了一个基于这段代码的RoundedImageView,它将这个逻辑包装到一个ImageView中,并添加了适当的ScaleType支持和可选的圆角边框。

其他回答

您可以尝试这个库- RoundedImageView

它是:

一个快速的ImageView,支持圆角,椭圆形和圆形。CircleImageView的完整超集。

我在我的项目中使用了它,它非常简单。

这里要回答的问题是: 如何在Android中创建一个圆形ImageView ?

public static Bitmap getRoundBitmap(Bitmap bitmap) {

    int min = Math.min(bitmap.getWidth(), bitmap.getHeight());

    Bitmap bitmapRounded = Bitmap.createBitmap(min, min, bitmap.getConfig());

    Canvas canvas = new Canvas(bitmapRounded);
    Paint paint = new Paint();
    paint.setAntiAlias(true);
    paint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
    canvas.drawRoundRect((new RectF(0.0f, 0.0f, min, min)), min/2, min/2, paint);

    return bitmapRounded;
}

最近,还有另一种方法——使用Glide的生成API。它需要一些初始的工作,但它给了你Glide所有的力量,以及做任何事情的灵活性,因为你重写了实际的代码,所以我认为从长远来看,这是一个很好的解决方案。另外,使用非常简单和整洁。

首先,设置Glide版本4+:

implementation 'com.github.bumptech.glide:glide:4.6.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.6.1'

然后创建Glid的app模块类来触发注释处理:

@GlideModule
public final class MyAppGlideModule extends AppGlideModule {}

然后创建实际工作的Glide扩展。你可以自定义它来做任何你想做的事情:

@GlideExtension
public class MyGlideExtension {

    private MyGlideExtension() {}

    @NonNull
    @GlideOption
    public static RequestOptions roundedCorners(RequestOptions options, @NonNull Context context, int cornerRadius) {
        int px = Math.round(cornerRadius * (context.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
        return options.transforms(new RoundedCorners(px));
    }
}

添加这些文件之后,构建您的项目。

然后像这样在你的代码中使用它:

GlideApp.with(this)
        .load(imageUrl)
        .roundedCorners(getApplicationContext(), 5)
        .into(imageView);

如果你的图片在互联网上,最好的方法是使用glide和RoundedBitmapDrawableFactory(来自API 21 -但在支持库中可用),如下所示:

 Glide.with(ctx).load(url).asBitmap().centerCrop().into(new BitmapImageViewTarget(imageView) {
    @Override
    protected void setResource(Bitmap res) {
        RoundedBitmapDrawable bitmapDrawable =
             RoundedBitmapDrawableFactory.create(ctx.getResources(), res);
        bitmapDrawable.setCircular(true);//comment this line and uncomment the next line if you dont want it fully cricular
        //circularBitmapDrawable.setCornerRadius(cornerRadius);
        imageView.setImageDrawable(bitmapDrawable);
    }
});

答案中提供的方法没有一个对我有用。我发现如果你的android版本是5.0或以上,以下方法是有效的:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

    ViewOutlineProvider provider = new ViewOutlineProvider() {
        @Override
        public void getOutline(View view, Outline outline) {
            int curveRadius = 24;
            outline.setRoundRect(0, 0, view.getWidth(), (view.getHeight()+curveRadius), curveRadius);
        }
    };
    imageview.setOutlineProvider(provider);
    imageview.setClipToOutline(true);
}

不需要定义xml形状,上面的代码只为顶部创建角,这是普通方法无法实现的。如果你需要4个圆角,移除:

"+ curveRadius"  

从setRoundRect中底部的参数。您可以通过指定适合您需要的轮廓来进一步将该形状扩展到任何其他形状。请查看以下链接:

Android开发者文档。


注意,与Android中的任何度量一样,你必须从DP“转换”大小。在上面的例子中,假设你想让半径为24

                            int curveRadius = 24;

例如,您可能稍后在可绘制对象中添加半径设置为“24”的边界,并希望它与之匹配。因此,

    float desiredRadius = 24;
    float radiusConverted = TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            desiredRadius,
            itemView.getContext().getResources().getDisplayMetrics());

然后

                            int curveRadius = radiusConverted;