如何创建一个带有圆角的ImageView?

708

在Android中,ImageView默认是矩形的。如何将它变成圆角矩形(剪切Bitmap的四个角成为圆角矩形)?


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


这可能会有帮助 https://dev59.com/UoXca4cB1Zd3GeqPCw48 - Mangesh
在更老、更复杂的答案下面,我认为现在应该接受的答案是:RoundedBitmapDrawable,它在v4支持库修订版21中添加。 - Jonik
你可以最简单的方法使用CardView,里面放一个ImageView - 在这里查看示例https://dev59.com/xHE95IYBdhLWcg3wGZ9_#41479670 - Taras Vovkovych
4
Material Design 1.2.0引入了ShapeableImageView,可能会很有用。 - Ali
使用Material Component Library中的ShapeableImageView。请查看此答案 https://dev59.com/rbvoa4cB1Zd3GeqPxR7e#61960983 - Khaled Saifullah
显示剩余2条评论
58个回答

3

您可以在布局中只使用 ImageView,并使用 Glide 库,使用此方法应用圆角。

首先,在 gradle 中编写以下代码:

compile 'com.github.bumptech.glide:glide:3.7.0'

对于具有圆角的图像,

public void loadImageWithCorners(String url, ImageView view) {
    Glide.with(context)
            .load(url)
            .asBitmap()
            .centerCrop()
            .placeholder(R.color.gray)
            .error(R.color.gray)
            .diskCacheStrategy(DiskCacheStrategy.SOURCE)
            .into(new BitmapImageViewTarget(view) {
                @Override
                protected void setResource(Bitmap resource) {
                    RoundedBitmapDrawable circularBitmapDrawable =
                            RoundedBitmapDrawableFactory.create(context.getResources(), resource);
                    circularBitmapDrawable.setCornerRadius(32.0f); // radius for corners
                    view.setImageDrawable(circularBitmapDrawable);
                }
            });
}

调用方法:

loadImageWithCorners("your url","your imageview");

这将添加一个用于通过HTTP请求加载图像的库,与问题无关。 - creativecreatorormaybenot
哪个库将被加载?对于图像加载,您可以使用Glide,并且代码片段纯粹基于Glide本身的方法和类。不需要添加其他库。 - Deep Patel
Glide是一个主要用于通过HTTP加载图像的库,但OP想知道如何将ImageView的角落变圆。 - creativecreatorormaybenot

3

通过使用以下代码,您可以更改顶部圆角半径

val image = findViewById<ImageView>(R.id.image)
val curveRadius = 20F

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

    image.outlineProvider = object : ViewOutlineProvider() {

        @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
        override fun getOutline(view: View?, outline: Outline?) {
            outline?.setRoundRect(0, 0, view!!.width, (view.height+curveRadius).toInt(), curveRadius)
        }
    }

    image.clipToOutline = true

}

对于安卓平台,代码如下:float curveRadius = 20F;ViewOutlineProvider outlineProvider = new ViewOutlineProvider() {@Override public void getOutline(View view, Outline outline) { outline.setRoundRect(0, 0, view.getWidth(), (int) (view.getHeight()+curveRadius), curveRadius); }};imatge.setOutlineProvider(outlineProvider);imatge.setClipToOutline(true); - OneKe

2

如果你正在使用Glide和Kotlin,你可以通过扩展RequestBuilder来实现。

fun <T> GlideRequest<T>.roundCorners(cornerRadius: Int) =
    apply(RequestOptions().transform(RoundedCorners(cornerRadius)))

并使用作为;

 GlideApp.with(context)
            .load(url)
            .roundCorners(context.resources.getDimension(R.dimen.radius_in_dp).toInt())
            .into(imgView)

.roundedCorners没有出现,我们需要设置其他东西吗? - Cyph3rCod3r
你是否像上面那样添加了扩展函数 roundCorners?@Dr.aNdRO - dgngulcan
请提供正确的例子!这个答案很令人困惑! - Junia Montana
@JuniaMontana,同意。这就像.transform(roundedCorners)一样简单,其中roundedCorners:RoundedCorners = RoundedCorners(roundingRadius) - CoolMind

2

借助于glide库和RoundedBitmapDrawableFactory类,实现这个功能非常容易。你可能需要创建一个圆形的占位图像。

    Glide.with(context)
        .load(imgUrl)
        .asBitmap()
        .placeholder(R.drawable.placeholder)
        .error(R.drawable.placeholder)
        .into(new BitmapImageViewTarget(imgProfilePicture) {
            @Override
            protected void setResource(Bitmap resource) {
                RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(context.getResources(),
                        Bitmap.createScaledBitmap(resource, 50, 50, false));
                drawable.setCornerRadius(10); //drawable.setCircular(true);
                imgProfilePicture.setImageDrawable(drawable);
            }
        });

2

如果要使用圆角边框,请使用以下代码:

  <com.google.android.material.card.MaterialCardView
                        android:id="@+id/circle"
                        android:layout_width="45dp"
                        android:layout_height="45dp"
                        android:layout_marginStart="5dp"

                        app:cardCornerRadius="25dp"
                        app:strokeColor="@color/colorDarkGreen"

                        app:strokeWidth="1dp">

                        <ImageView
                            android:id="@+id/toolbarProfile"
                            android:scaleType="fitXY"

                            android:layout_width="match_parent"
                            android:layout_height="match_parent"

                            android:src="@drawable/avater" />
                    </com.google.android.material.card.MaterialCardView>

1
使用此代码可获得带边框的圆形图像 -
    public static Bitmap getCircularBitmapWithBorder(Bitmap bitmap, int bordercolor) {
    if (bitmap == null || bitmap.isRecycled()) {
        return null;
    }
    int borderWidth=(int)(bitmap.getWidth()/40);
    final int width = bitmap.getWidth() + borderWidth;
    final int height = bitmap.getHeight() + borderWidth;

    Bitmap canvasBitmap = Bitmap.createBitmap(width, height,
            Bitmap.Config.ARGB_8888);
    BitmapShader shader = new BitmapShader(bitmap, TileMode.CLAMP,
            TileMode.CLAMP);
    Paint paint = new Paint();
    paint.setAntiAlias(true);
    paint.setShader(shader);

    Canvas canvas = new Canvas(canvasBitmap);
    float radius = width > height ? ((float) height) / 2f
            : ((float) width) / 2f;
    canvas.drawCircle(width / 2, height / 2, radius, paint);
    paint.setShader(null);
    paint.setStyle(Paint.Style.STROKE);
    paint.setColor(bordercolor);
    paint.setStrokeWidth(borderWidth);
    canvas.drawCircle(width / 2, height / 2, radius - borderWidth / 2,
            paint);
    return canvasBitmap;
}

这可以帮助我给圆形图像添加白色边框。谢谢。 - Alexandro

1
感谢melanke的帮助,您可以使用自定义类并创建自定义的圆形ImageView
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;

public class MLRoundedImageView extends android.support.v7.widget.AppCompatImageView {

    public MLRoundedImageView(Context context) {
        super(context);
    }

    public MLRoundedImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MLRoundedImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        Drawable drawable = getDrawable();

        if (drawable == null) {
            return;
        }

        if (getWidth() == 0 || getHeight() == 0) {
            return;
        }
        Bitmap b = ((BitmapDrawable) drawable).getBitmap();
        Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

        int w = getWidth(), h = getHeight();

        Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
        canvas.drawBitmap(roundBitmap, 0, 0, null);

    }

    public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
        Bitmap sbmp;

        if (bmp.getWidth() != radius || bmp.getHeight() != radius) {
            float smallest = Math.min(bmp.getWidth(), bmp.getHeight());
            float factor = smallest / radius;
            sbmp = Bitmap.createScaledBitmap(bmp, (int)(bmp.getWidth() / factor), (int)(bmp.getHeight() / factor), false);
        } else {
            sbmp = bmp;
        }

        Bitmap output = Bitmap.createBitmap(radius, radius,
                Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final int color = 0xffa19774;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, radius, radius);

        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);
        paint.setDither(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(Color.parseColor("#BAB399"));
        canvas.drawCircle(radius / 2 + 0.7f,
                radius / 2 + 0.7f, radius / 2 + 0.1f, paint);
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(sbmp, rect, rect, paint);

        return output;
    }

}

然后在XML中使用它,例如:
<your.package.name.MLRoundedImageView
..
/>

源代码


1

这个问题很老了,我知道,但是这里有另一种更简单的方法来调整图像的大小:

这是一种编程方法。

创建你的void并且...

} public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) { Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output); final int color = 0xff424242;
final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = pixels; paint.setAntiAlias(true); 
canvas.drawARGB(0, 0, 0, 0); paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint); return output;

加载您的图像,然后设置圆角

imageview1.setImageResource(R.drawable.yourimage);

Bitmap bm = ((android.graphics.drawable.BitmapDrawable) imageview1.getDrawable()).getBitmap();
imageview1.setImageBitmap(getRoundedCornerBitmap(bm, 30)); 

如果您的半径为30,则会得到类似于以下内容:

example of a rounded image/icon

不要在意我的图片外观,它只是一个放大的小图标。


1
我正在使用一个自定义视图,将其布局在其他视图之上,并只以与背景相同的颜色绘制四个小倒角。
优点:
- 不会分配位图。 - 无论您要应用圆角的视图是什么都可以正常工作。 - 适用于所有API级别 ;)
代码:
public class RoundedCornersView extends View {
    private float mRadius;
    private int mColor = Color.WHITE;
    private Paint mPaint;
    private Path mPath;

    public RoundedCornersView(Context context) {
        super(context);
        init();
    }

    public RoundedCornersView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();

        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.RoundedCornersView,
                0, 0);

        try {
            setRadius(a.getDimension(R.styleable.RoundedCornersView_radius, 0));
            setColor(a.getColor(R.styleable.RoundedCornersView_cornersColor, Color.WHITE));
        } finally {
            a.recycle();
        }
    }

    private void init() {
        setColor(mColor);
        setRadius(mRadius);
    }

    private void setColor(int color) {
        mColor = color;
        mPaint = new Paint();
        mPaint.setColor(mColor);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setAntiAlias(true);

        invalidate();
    }

    private void setRadius(float radius) {
        mRadius = radius;
        RectF r = new RectF(0, 0, 2 * mRadius, 2 * mRadius);
        mPath = new Path();
        mPath.moveTo(0,0);
        mPath.lineTo(0, mRadius);
        mPath.arcTo(r, 180, 90);
        mPath.lineTo(0,0);
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {

        /*This just draws 4 little inverted corners */

        int w = getWidth();
        int h = getHeight();
        canvas.drawPath(mPath, mPaint);
        canvas.save();
        canvas.translate(w, 0);
        canvas.rotate(90);
        canvas.drawPath(mPath, mPaint);
        canvas.restore();
        canvas.save();
        canvas.translate(w, h);
        canvas.rotate(180);
        canvas.drawPath(mPath, mPaint);
        canvas.restore();
        canvas.translate(0, h);
        canvas.rotate(270);
        canvas.drawPath(mPath, mPaint);
    }
}

1
你可以很容易地使用RoundedImageView库:

compile 'com.makeramen:roundedimageview:2.3.0'

然后:

<com.makeramen.roundedimageview.RoundedImageView
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:id="@+id/img_episode"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:elevation="7dp"
  app:riv_border_color="@color/colorPrimary"
  app:riv_border_width="1dip"
  app:riv_corner_radius="10dip"
  app:riv_mutate_background="true"
  />

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