【问题标题】:How to make an ImageView with rounded corners?如何制作带圆角的 ImageView?
【发布时间】:2011-01-28 10:19:39
【问题描述】:

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

【问题讨论】:

标签: android imageview android-imageview android-image rounded-corners


【解决方案1】:

这已经很晚了,但是对于正在寻找这个的其他人,您可以执行以下代码来手动圆角图像。

http://www.ruibm.com/?p=184

这不是我的代码,但我已经使用了它,它的效果非常好。我将它用作 ImageHelper 类中的帮助器,并对其进行了一点扩展,以传递给定图像所需的羽化量。

最终代码如下所示:

package com.company.app.utils;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;

public class ImageHelper {
    public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap
                .getHeight(), 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(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);

        return output;
    }
}

【讨论】:

  • 它不适用于所有设备。我需要在任何地方更改吗?
  • 一张 200*200 的图片需要将近 0.03 秒的时间,所以我认为这不是最好的解决方案。
  • 它只舍入左上角和右上角。为什么?
  • @vinc3m1 解决方案在这里github.com/makeramen/RoundedImageView 效果很好!另见他的回答 (stackoverflow.com/a/15032283/2048266)
  • 尝试设置 imageview 的 scaletype 时效果不佳,只有 fitXY 工作,centerCrop 和其他显示不可预测的结果,这里有人遇到同样的问题吗?
【解决方案2】:

另一种简单的方法是使用带有圆角半径的 CardView 和内部的 ImageView:

  <androidx.cardview.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:cardCornerRadius="8dp"
            android:layout_margin="5dp"
            android:elevation="10dp">

            <ImageView
                android:id="@+id/roundedImageView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@drawable/image"
                android:background="@color/white"
                android:scaleType="centerCrop"
                />
        </androidx.cardview.widget.CardView>

【讨论】:

  • 似乎是一个很好的解决方法。但它不会在棒棒糖之前剪辑图像。
  • 如果我们只想要左上角和右上角的半径而不是所有的角呢?
  • 在任何视图中应用曲线边框的非常简单和智能的方法。
  • 很好的解决方案,但只有 api 级别 21 及以上才支持提升
  • 禁用卡片提升使用 app:cardElevation="0dp" (不是 android:elevation)
【解决方案3】:

在 API 21 中的 View 类中添加了圆形剪辑。

这样做:

  • 创建一个圆形可绘制对象,如下所示:

res/drawable/round_outline.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="10dp" />
    ...
</shape>
  • 将可绘制对象设置为 ImageView 的背景: android:background="@drawable/round_outline"
  • 根据这个documentation,那么你只需添加android:clipToOutline="true"

不幸的是,a bug 无法识别该 XML 属性。幸运的是,我们仍然可以在 Java 中设置剪辑:

  • 在您的活动或片段中:ImageView.setClipToOutline(true)

如下所示:

注意:

此方法适用于任何可绘制形状(不仅仅是圆形)。它会将 ImageView 剪辑到您在 Drawable xml 中定义的任何形状轮廓。

关于 ImageViews 的特别说明

setClipToOutline() 仅在 View 的背景设置为可绘制形状时有效。如果存在此背景形状,View 会将形状的轮廓视为边界,以进行剪切和阴影处理。

这意味着,如果您想使用setClipToOutline() 对 ImageView 进行圆角,则必须使用 android:src 而不是 android:background 设置图像(因为背景必须设置为圆形)。如果您必须使用背景而不是 src 来设置图像,您可以使用以下解决方法:

  • 创建布局并将其背景设置为可绘制的形状
  • 将该布局包裹在您的 ImageView 周围(没有填充)
  • ImageView(包括布局中的任何其他内容)现在将以圆形布局形状显示。

【讨论】:

  • 错误:(x) 在包 'android' 中找不到属性 'clipToOutline' 的资源标识符
  • 代替android:clipToOutline,必须使用android:outlineProvider="background"
  • 我如此“爱”Google 的另一个原因是,这个 bug 几乎是我的年龄,并且仍然存在于它的小世界中。谷歌似乎没有给出任何废话))
  • 当我只将背景形状中的左上角和右上角设置为圆形时,我似乎没有成功。
  • @AnuMartin 这是已知问题 - issuetracker.google.com/issues/37036728
【解决方案4】:

虽然上述答案有效,但 Romain Guy(核心 Android 开发人员)在他的博客中显示 a better method 通过使用着色器而不创建位图副本来使用更少的内存。该功能的一般要点在这里:

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 支持和可选的圆角边框。

【讨论】:

  • 在您的/ example / res / layout / rounded_item.xml 中,当您的所有来源都被硬编码时,为什么要指定图像 src ?不错的演示,只是有点矫枉过正。
  • 您的样本存在严重的内存不足问题,就像 Romain Guy 的原始样本一样。我仍然不知道是什么原因造成的,但就像他的代码一样,这真的很难找到。如果您因为 OOM 而无法从应用程序中看到崩溃,您可以多次旋转应用程序直到它发生(取决于您的设备、ROM 等...)。我过去曾在这里报道过:stackoverflow.com/questions/14109187/…
  • 没有其他人报告内存不足问题,因此它一定是您在代码之外执行的操作不正确。该示例在适配器中正确地保存了一组有限的位图而不在每次绘制视图时都重新创建它们。此处显示的示例是 Drawable 中 draw() 方法的一个 sn-p,它使用对它所持有的原始位图的引用并且可以正常工作。 不是的意思是改变原始位图,而只是用圆角渲染它。中心裁剪在示例中也可以正常工作。
  • 如果您可以提供无法使用的屏幕截图或设备,甚至提供修复和拉取请求,那将是最有效率的。我已经在我的设备上测试了多次旋转,内存保持不变。
  • 请注意,如果图像大小超过 2048 像素,它将不起作用。着色器不支持大于该值的纹理。
【解决方案5】:

Material Components Library1.2.0-alpha03版本开始,有新的ShapeableImageView

你可以使用类似的东西:

  <com.google.android.material.imageview.ShapeableImageView
      ...
      app:shapeAppearanceOverlay="@style/roundedImageView"
      app:srcCompat="@drawable/ic_image" />

与:

  <style name="roundedImageView" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">8dp</item>
  </style>

或以编程方式:

float radius = getResources().getDimension(R.dimen.default_corner_radius);
imageView.setShapeAppearanceModel(imageView.getShapeAppearanceModel()
    .toBuilder()
    .setAllCorners(CornerFamily.ROUNDED,radius)
    .build());


使用 jetpack compose,您可以使用 RoundedCornerShape 应用 clip Modifier

Image(
        painter = painterResource(R.drawable.xxxx),
        contentDescription = "xxxx",
        contentScale = ContentScale.Crop,            
        modifier = Modifier
            .size(64.dp)
            .clip(RoundedCornerShape(8.dp))             
    )

【讨论】:

  • 如果图像有背景色,当前会生成背景色以在圆角下方突出显示。这也会忽略图像上的 scaleType 属性。
  • 当我们以编程方式增加大小时它不起作用
  • 简单的解决方案,适用于根布局背景
  • 完美答案。谢谢你
【解决方案6】:

在支持库的 v21 中,现在有一个解决方案:它称为 RoundedBitmapDrawable

它基本上就像一个普通的 Drawable,除了你给它一个圆角半径来进行裁剪:

setCornerRadius(float cornerRadius)

所以,从Bitmap src 和目标ImageView 开始,它看起来像这样:

RoundedBitmapDrawable dr = RoundedBitmapDrawableFactory.create(res, src);
dr.setCornerRadius(cornerRadius);
imageView.setImageDrawable(dr);

【讨论】:

  • 非常感谢,这是下一步:stackoverflow.com/questions/24878740/…
  • 其实有android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory所以v4也支持。
  • @deadfish 是的,它在 v4 支持库中,但直到支持库的 REVISION 21 才出现
  • 这是一个简单且最新的解决方案。它需要最少的代码并且具有很好的可扩展性。可以处理来自本地文件的图像、缓存的可绘制对象,甚至可以使用 Volley 的 NetworkImageView。正如@Jonik 指出的那样,我非常同意这应该是当今公认的答案。
  • 很遗憾不适用于scaleType centerCrop(支持库v25.3.1)
【解决方案7】:

一个快速的 xml 解决方案 -

<android.support.v7.widget.CardView
            android:layout_width="40dp"
            android:layout_height="40dp"
            app:cardElevation="0dp"
            app:cardCornerRadius="4dp">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/rounded_user_image"
        android:scaleType="fitXY"/>

</android.support.v7.widget.CardView>

您可以在 CardView 上设置所需的宽度、高度和半径,在 ImageView 上设置 scaleType。

对于 AndroidX,使用 &lt;androidx.cardview.widget.CardView&gt;

【讨论】:

  • 这种方法在我的情况下适用于 androidx.cardview.widget.CardView
  • 但是,它可以工作,但这里的图像会因为scaleType="fitXY" 而拉伸,并且看起来不合适@ThemBones
  • @WIZARD 这就是为什么我提到你可以在 ImageView 上设置你想要的 scaleType
  • 对我不起作用,我正在使用 androidx.cardview.widget.CardView 和 scaleType centerCrop
  • 对我不起作用。 imageview 与 cardview 的圆角重叠
【解决方案8】:

我已经通过自定义 ImageView 完成了:

public class RoundRectCornerImageView extends ImageView {

    private float radius = 18.0f;
    private Path path;
    private RectF rect;

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

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

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

    private void init() {
        path = new Path();

    }

    @Override
    protected void onDraw(Canvas canvas) {
        rect = new RectF(0, 0, this.getWidth(), this.getHeight());
        path.addRoundRect(rect, radius, radius, Path.Direction.CW);
        canvas.clipPath(path);
        super.onDraw(canvas);
    }
}

使用方法:

<com.mypackage.RoundRectCornerImageView
     android:id="@+id/imageView"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@drawable/image"
     android:scaleType="fitXY" />

输出:

希望这会对你有所帮助。

【讨论】:

  • 这会使图像模糊
  • 甚至可以使用 android:scaleType="centerCrop",简单,不会创建新的位图。谢谢!
  • @Hiren 此解决方案适用于具有背景图像的 ImageView。但它不适用于只有背景颜色且没有图像的 ImageView。你能告诉我为什么会这样吗?
  • 此解决方案仅适用于使用android:background 设置的图像,但不适用于android:src
  • 我已经改进了这段代码CircularImage
【解决方案9】:

我发现这两种方法都非常有助于提出可行的解决方案。这是我的复合版本,它与像素无关,允许您有一些方角,其余角具有相同的半径(这是通常的用例)。 感谢以上两种解决方案:

public static Bitmap getRoundedCornerBitmap(Context context, Bitmap input, int pixels , int w , int h , boolean squareTL, boolean squareTR, boolean squareBL, boolean squareBR  ) {

    Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
    Canvas canvas = new Canvas(output);
    final float densityMultiplier = context.getResources().getDisplayMetrics().density;

    final int color = 0xff424242;
    final Paint paint = new Paint();
    final Rect rect = new Rect(0, 0, w, h);
    final RectF rectF = new RectF(rect);

    //make sure that our rounded corner is scaled appropriately
    final float roundPx = pixels*densityMultiplier;

    paint.setAntiAlias(true);
    canvas.drawARGB(0, 0, 0, 0);
    paint.setColor(color);
    canvas.drawRoundRect(rectF, roundPx, roundPx, paint);


    //draw rectangles over the corners we want to be square
    if (squareTL ){
        canvas.drawRect(0, h/2, w/2, h, paint);
    }
    if (squareTR ){
        canvas.drawRect(w/2, h/2, w, h, paint);
    }
    if (squareBL ){
        canvas.drawRect(0, 0, w/2, h/2, paint);
    }
    if (squareBR ){
        canvas.drawRect(w/2, 0, w, h/2, paint);
    }


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

    return output;
}

另外,我覆盖了 ImageView 以将其放入,以便我可以在 xml 中定义它。 您可能想在此处添加 super 调用的一些逻辑,但我已对其进行了评论,因为它对我的情况没有帮助。

    @Override
protected void onDraw(Canvas canvas) {
    //super.onDraw(canvas);
        Drawable drawable = getDrawable();

        Bitmap b =  ((BitmapDrawable)drawable).getBitmap() ;
        Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

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


        Bitmap roundBitmap =  CropImageView.getRoundedCornerBitmap( getContext(), bitmap,10 , w, h , true, false,true, false);
        canvas.drawBitmap(roundBitmap, 0,0 , null);
}

希望这会有所帮助!

【讨论】:

  • 非常棒,尤其是扩展 ImageView
  • 保持ImageView#onDraw()逻辑的简单方法是将圆角位图设置为ImageView的drawable,留给super.onDraw()来绘制位图。我创建了一个类RoundedCornerImageView,它的使用示例是here。请注意,我使用的 getRoundedCornerBitmap() 不是像素独立的。
  • 感谢 RoundedCornerImageView。我使用它,但将其修改为与像素密度无关。
  • umba 的 RoundedCornerImageView 的源代码在这里:code.google.com/p/android-batsg/source/browse/trunk/…
  • @Caspar Harmer 工作良好只需 1 次编辑...有四个条件..只需更改它们,就好像我设置了 true、true、false、false 它会设置底角而不是顶角..否则代码工作正常。所以 squareTL 和 squareTR 分别是 squareBL 和 squareBR 的条件。反之亦然。
【解决方案10】:

圆形图像使用ImageLoader here

创建DisplayImageOptions:

DisplayImageOptions options = new DisplayImageOptions.Builder()
    // this will make circle, pass the width of image 
    .displayer(new RoundedBitmapDisplayer(getResources().getDimensionPixelSize(R.dimen.image_dimen_menu))) 
    .cacheOnDisc(true)
    .build();

imageLoader.displayImage(url_for_image,ImageView,options);

或者您可以使用 Square 的 Picasso Library。

Picasso.with(mContext)
    .load(com.app.utility.Constants.BASE_URL+b.image)
    .placeholder(R.drawable.profile)
    .error(R.drawable.profile)
    .transform(new RoundedTransformation(50, 4))
    .resizeDimen(R.dimen.list_detail_image_size, R.dimen.list_detail_image_size)
    .centerCrop()
    .into(v.im_user);

您可以在此处下载 RoundedTransformation 文件 here

【讨论】:

  • 毕加索图书馆很好,而且很容易实现,非常感谢+1
  • 毕加索库似乎没有转换“占位符”和“错误”图像,所以如果您的图像无法加载(错误)或需要一段时间才能加载(占位符)它不会将图像显示为圆形图像。 github.com/square/picasso/issues/337
  • 这个库提供了其他有用的毕加索变换,它还包含一个 RoundedCornersTransformation:github.com/wasabeef/picasso-transformations
  • 不适用于 Univ 中的裁剪图像。图片加载器。
【解决方案11】:

因为所有的答案对我来说似乎都太复杂了,我认为并得出了另一个我认为值得分享的解决方案,只是使用 XML 以防图像周围有一些空间:

创建一个带有透明内容的边框形状,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners 
        android:radius="30dp" />
    <stroke 
        android:color="#ffffffff"
        android:width="10dp" />
</shape> 

然后在RelativeLayout 中,您可以先放置图像,然后在形状上方与另一个ImageView 相同的位置。封面形状的大小应该比边框宽度大。请注意在定义外半径时采用较大的圆角半径,但内半径是覆盖图像的部分。

希望它也能帮助别人。

编辑根据 CQM 请求相关布局示例:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/imageToShow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/imgCorners"
        android:layout_alignLeft="@+id/imgCorners"
        android:layout_alignRight="@+id/imgCorners"
        android:layout_alignTop="@+id/imgCorners"
        android:background="#ffffff"
        android:contentDescription="@string/desc"
        android:padding="5dp"
        android:scaleType="centerCrop" />

    <ImageView
        android:id="@+id/imgCorners"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:contentDescription="@string/desc"
        android:src="@drawable/corners_white" />

</RelativeLayout>

【讨论】:

  • 您能否用更多代码详细说明这一点,尤其是第二个图像视图正在做什么以及“边框形状”xml 的应用位置(作为 src 还是作为背景?)这里有几个问题.我想喜欢这个解决方案,因为它可以让我独立控制所有四个角
  • 虽然看起来是一个简单的答案,但不幸的是,它在“蒙版”图像视图周围增加了边距,这是不受欢迎的副作用。
  • 是的,但同样适用于 ImageView
  • 我正在做同样的事情,它的工作;只是想知道它是否不会对方向和不同的手机尺寸造成任何问题?
  • 如果您保持相对于彼此的尺寸,这应该不会造成问题。
【解决方案12】:

我的 ImageView 实现带有圆角小部件,它(向下||向上)将图像大小调整到所需的尺寸。它使用 CaspNZ 形式的代码。

public class ImageViewRounded extends ImageView {

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

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

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

    @Override
    protected void onDraw(Canvas canvas) {
        BitmapDrawable drawable = (BitmapDrawable) getDrawable();

        if (drawable == null) {
            return;
        }

        if (getWidth() == 0 || getHeight() == 0) {
            return; 
        }

        Bitmap fullSizeBitmap = drawable.getBitmap();

        int scaledWidth = getMeasuredWidth();
        int scaledHeight = getMeasuredHeight();

        Bitmap mScaledBitmap;
        if (scaledWidth == fullSizeBitmap.getWidth() && scaledHeight == fullSizeBitmap.getHeight()) {
            mScaledBitmap = fullSizeBitmap;
        } else {
            mScaledBitmap = Bitmap.createScaledBitmap(fullSizeBitmap, scaledWidth, scaledHeight, true /* filter */);
        }

        Bitmap roundBitmap = ImageUtilities.getRoundedCornerBitmap(getContext(), mScaledBitmap, 5, scaledWidth, scaledHeight,
                false, false, false, false);
        canvas.drawBitmap(roundBitmap, 0, 0, null);

    }

}

【讨论】:

  • ImageUtilities 从何而来?
  • @JasonWyatt 请参阅下面的 sorrodos 帖子
【解决方案13】:

最近,还有另一种方法 - 使用 Glide's Generated 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);

【讨论】:

  • .roundedCorners 没有出现,我们需要设置其他东西吗?即使在重建项目之后
  • 这对我有用,谢谢。我发现避免使用 @GlideExtension 带注释的类更简单,只使用 .transform(new RoundedCorners(px)) 其中 px 是相同的 (int px = Math.round(cornerRadius * (context.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));)。
【解决方案14】:

有一个cool library 可以让您塑造图像视图。

这是一个例子:

<com.github.siyamed.shapeimageview.mask.PorterShapeImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:siShape="@drawable/shape_rounded_rectangle"
    android:src="@drawable/neo"
    app:siSquare="true"/>

形状定义:

<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
    <corners
        android:topLeftRadius="18dp"
        android:topRightRadius="18dp"
        android:bottomLeftRadius="18dp"
        android:bottomRightRadius="18dp" />
    <solid android:color="@color/black" />
</shape>

结果:

【讨论】:

    【解决方案15】:

    这是一个简单的覆盖 imageView 的例子,你也可以在布局设计器中使用它来预览。

    public class RoundedImageView extends ImageView {
    
        public RoundedImageView(Context context) {
            super(context);
        }
    
        public RoundedImageView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public RoundedImageView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        public RoundedImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }
    
        @Override
        public void setImageDrawable(Drawable drawable) {
            float radius = 0.1f;
            Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
            RoundedBitmapDrawable rid = RoundedBitmapDrawableFactory.create(getResources(), bitmap);
            rid.setCornerRadius(bitmap.getWidth() * radius);
            super.setImageDrawable(rid);
        }
    }
    

    这是为了快速解决。半径用于所有角,基于位图宽度的百分比。

    我刚刚覆盖了setImageDrawable 并使用支持v4 方法来绘制圆角位图。

    用法:

    <com.example.widgets.RoundedImageView
            android:layout_width="39dp"
            android:layout_height="39dp"
            android:src="@drawable/your_drawable" />
    

    使用 imageView 和自定义 imageView 预览:

    【讨论】:

    • 如果使用 Glide 动态设置图像,应用会崩溃。
    【解决方案16】:

    科特林

    import android.graphics.BitmapFactory
    import android.os.Bundle
    import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory
    import kotlinx.android.synthetic.main.activity_main.*
    
    val bitmap = BitmapFactory.decodeResource(resources, R.drawable.myImage)
    val rounded = RoundedBitmapDrawableFactory.create(resources, bitmap)
    rounded.cornerRadius = 20f
    profileImageView.setImageDrawable(rounded)
    

    要制作ImageView Circular,我们可以将cornerRadius 更改为:

    rounded.isCircular = true
    

    【讨论】:

    • 被严重低估的答案。清晰且易于实施。应该是解决方案。
    【解决方案17】:

    将形状应用于您的imageView,如下所示:

    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle" >
        <solid android:color="#faf5e6" />
        <stroke
            android:width="1dp"
            android:color="#808080" />
        <corners android:radius="15dp" />
        <padding
            android:bottom="5dp"
            android:left="5dp"
            android:right="5dp"
            android:top="5dp" />
    </shape>
    

    它可能对你的朋友有帮助。

    【讨论】:

      【解决方案18】:

      您应该扩展ImageView 并绘制您自己的圆角矩形。

      如果您想在图像周围设置一个框架,您还可以在布局中的图像视图顶部叠加圆角框架。

      [编辑]将帧叠加到原始图像上,例如使用FrameLayoutFrameLayout 的第一个元素将是您要显示的圆形图像。然后在框架中添加另一个ImageView。第二个ImageView 将显示在原始ImageView 之上,因此Android 会将其内容绘制在原始ImageView 之上。

      【讨论】:

      • 谢谢。但是ImageView只有setDrawable方法,如何将ImageView的Drawable设置为我的图片内容,然后在ImageView上面叠加一个圆角框?
      • 对不起,我不清楚。我的意思是在布局中叠加:因此(即)使用FrameLayout 在其中放置一个ImageView 并添加另一个带有圆形框架的ImageView。这样第一个ImageView 将显示您选择的图片,第二个ImageFrame 将显示圆角边框。
      • 正确 - 使用 FrameLayout 您可以将一个图像/视图与另一个叠加。您还可以使用 FrameLayout 的 android:foreground 标签。
      【解决方案19】:

      上面对 George Walters II 的支持,我只是接受了他的回答并对其进行了扩展,以支持以不同的方式圆角各个角落。这可以进一步优化(一些目标矩形重叠),但不是很多。

      我知道这个帖子有点老了,但它是在 Google 上查询如何在 Android 上圆角 ImageViews 的最佳结果之一。

      /**
       * Use this method to scale a bitmap and give it specific rounded corners.
       * @param context Context object used to ascertain display density.
       * @param bitmap The original bitmap that will be scaled and have rounded corners applied to it.
       * @param upperLeft Corner radius for upper left.
       * @param upperRight Corner radius for upper right.
       * @param lowerRight Corner radius for lower right.
       * @param lowerLeft Corner radius for lower left.
       * @param endWidth Width to which to scale original bitmap.
       * @param endHeight Height to which to scale original bitmap.
       * @return Scaled bitmap with rounded corners.
       */
      public static Bitmap getRoundedCornerBitmap(Context context, Bitmap bitmap, float upperLeft,
              float upperRight, float lowerRight, float lowerLeft, int endWidth,
              int endHeight) {
          float densityMultiplier = context.getResources().getDisplayMetrics().density;
      
          // scale incoming bitmap to appropriate px size given arguments and display dpi
          bitmap = Bitmap.createScaledBitmap(bitmap, 
                  Math.round(endWidth * densityMultiplier),
                  Math.round(endHeight * densityMultiplier), true);
      
          // create empty bitmap for drawing
          Bitmap output = Bitmap.createBitmap(
                  Math.round(endWidth * densityMultiplier),
                  Math.round(endHeight * densityMultiplier), Config.ARGB_8888);
      
          // get canvas for empty bitmap
          Canvas canvas = new Canvas(output);
          int width = canvas.getWidth();
          int height = canvas.getHeight();
      
          // scale the rounded corners appropriately given dpi
          upperLeft *= densityMultiplier;
          upperRight *= densityMultiplier;
          lowerRight *= densityMultiplier;
          lowerLeft *= densityMultiplier;
      
          Paint paint = new Paint();
          paint.setAntiAlias(true);
          paint.setColor(Color.WHITE);
      
          // fill the canvas with transparency
          canvas.drawARGB(0, 0, 0, 0);
      
          // draw the rounded corners around the image rect. clockwise, starting in upper left.
          canvas.drawCircle(upperLeft, upperLeft, upperLeft, paint);
          canvas.drawCircle(width - upperRight, upperRight, upperRight, paint);
          canvas.drawCircle(width - lowerRight, height - lowerRight, lowerRight, paint);
          canvas.drawCircle(lowerLeft, height - lowerLeft, lowerLeft, paint);
      
          // fill in all the gaps between circles. clockwise, starting at top.
          RectF rectT = new RectF(upperLeft, 0, width - upperRight, height / 2);
          RectF rectR = new RectF(width / 2, upperRight, width, height - lowerRight);
          RectF rectB = new RectF(lowerLeft, height / 2, width - lowerRight, height);
          RectF rectL = new RectF(0, upperLeft, width / 2, height - lowerLeft);
      
          canvas.drawRect(rectT, paint);
          canvas.drawRect(rectR, paint);
          canvas.drawRect(rectB, paint);
          canvas.drawRect(rectL, paint);
      
          // set up the rect for the image
          Rect imageRect = new Rect(0, 0, width, height);
      
          // set up paint object such that it only paints on Color.WHITE
          paint.setXfermode(new AvoidXfermode(Color.WHITE, 255, AvoidXfermode.Mode.TARGET));
      
          // draw resized bitmap onto imageRect in canvas, using paint as configured above
          canvas.drawBitmap(bitmap, imageRect, imageRect, paint);
      
          return output;
      }
      

      【讨论】:

      • +1 用于添加密度乘数并添加对单独圆角的支持。我实际上使用了顶部的解决方案,因为您的解决方案不太有效 - 但它非常有帮助!请参阅下面的复合解决方案:
      【解决方案20】:

      Romain Guy 就是这样。

      缩小版如下。

      Bitmap bitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.image)).getBitmap();
      
      Bitmap bitmapRounded = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), 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, bitmap.getWidth(), bitmap.getHeight())), 10, 10, paint);
      
      imageView.setImageBitmap(bitmapRounded);
      

      【讨论】:

      • 遗憾的是,尽管它可以工作,但就像这里的其他解决方案一样,它会创建一个新的位图而不是使用当前的位图。
      • 并非如此。 bitmapRounded 将被一次又一次地使用。如果您可以访问可绘制画布,则可以直接使用 draw 方法而不是生成新的位图。
      • 你是怎么做到的?假设我不使用任何特殊的可绘制对象,只处理单个位图并在过程结束时使用 setImageBitmap 。我将如何实现这样的目标?
      • 两者都不会更改位图,而是使用自定义可绘制对象和自定义图像视图来包装它。这不是我问的。我问你如何改变位图本身。
      【解决方案21】:

      这个纯 xml 解决方案对我来说已经足够好了。 http://www.techrepublic.com/article/pro-tip-round-corners-on-an-android-imageview-with-this-hack/

      编辑

      简而言之,答案如下:

      在 /res/drawable 文件夹中,创建一个 frame.xml 文件。在其中,我们定义了一个带有圆角和一个透明中心的简单矩形。

      <?xml version="1.0" encoding="utf-8"?>
      <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
           <solid android:color="#00ffffff" />
           <padding android:left="6dp"
              android:top="6dp"
              android:right="6dp"
              android:bottom="6dp" />
           <corners android:radius="12dp" />
           <stroke android:width="6dp" android:color="#ffffffff" />
      </shape>
      

      在您的布局文件中添加一个包含标准 ImageView 以及嵌套 FrameLayout 的 LinearLayout。 FrameLayout 使用填充和自定义可绘制对象来产生圆角的错觉。

      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical"
          android:layout_gravity="center"
          android:gravity="center" 
          android:background="#ffffffff">
      
          <ImageView
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:padding="6dp"
              android:src="@drawable/tr"/>
      
          <FrameLayout 
              android:layout_width="wrap_content"
              android:layout_height="wrap_content">
      
              <ImageView
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:padding="6dp"
                  android:src="@drawable/tr"/>
      
              <ImageView 
                   android:src="@drawable/frame"
                   android:layout_width="match_parent"
                   android:layout_height="match_parent" />
      
          </FrameLayout>
      
      </LinearLayout>
      

      【讨论】:

        【解决方案22】:

        答案中提供的方法都不适合我。如果您的 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中bottom的参数。您可以通过指定适合您需要的轮廓进一步将形状扩展到任何其他形状。查看以下链接:

        Android Developer Documentation.


        请注意,与 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;
        

        【讨论】:

        • AHHHHH .. 乘以屏幕密度!
        • 亲爱的@us_david ,关于您的惊人回答,我添加了一条关于让半径正确以匹配应用程序中的其他半径的说明。显然删除或编辑你认为合适的!非常感谢您的回答!!!
        【解决方案23】:

        为什么不在draw() 中进行剪辑?

        这是我的解决方案:

        • 使用剪辑扩展RelativeLayout
        • 将 ImageView(或其他视图)放入布局中:

        代码:

        public class RoundRelativeLayout extends RelativeLayout {
        
            private final float radius;
        
            public RoundRelativeLayout(Context context, AttributeSet attrs) {
                super(context, attrs);
        
                TypedArray attrArray = context.obtainStyledAttributes(attrs,
                        R.styleable.RoundRelativeLayout);
                radius = attrArray.getDimension(
                        R.styleable.RoundRelativeLayout_radius, 0);
            }
        
            private boolean isPathValid;
            private final Path path = new Path();
        
            private Path getRoundRectPath() {
                if (isPathValid) {
                    return path;
                }
        
                path.reset();
        
                int width = getWidth();
                int height = getHeight();
                RectF bounds = new RectF(0, 0, width, height);
        
                path.addRoundRect(bounds, radius, radius, Direction.CCW);
                isPathValid = true;
                return path;
            }
        
            @Override
            protected void dispatchDraw(Canvas canvas) {
                canvas.clipPath(getRoundRectPath());
                super.dispatchDraw(canvas);
            }
        
            @Override
            public void draw(Canvas canvas) {
                canvas.clipPath(getRoundRectPath());
                super.draw(canvas);
            }
        
            @Override
            protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        
                int oldWidth = getMeasuredWidth();
                int oldHeight = getMeasuredHeight();
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        
                int newWidth = getMeasuredWidth();
                int newHeight = getMeasuredHeight();
                if (newWidth != oldWidth || newHeight != oldHeight) {
                    isPathValid = false;
                }
            }
        
        }
        

        【讨论】:

        • 这在开启硬加速的情况下不起作用,对吗?我没有看到一个简单的解决方法...
        【解决方案24】:

        可以通过ShapeableImageViewShapeAppearanceOverlay来完成:

        <com.google.android.material.imageview.ShapeableImageView
            android:id="@+id/avatar"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:padding="4dp"
            app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar"/>
        

        样式ShapeAppearanceOverlay.Avatar驻留在res/values/styles.xml

        <style name="ShapeAppearanceOverlay.Avatar" parent="ShapeAppearance.MaterialComponents.SmallComponent">
            <item name="cornerFamily">rounded</item>
            <item name="cornerSize">50%</item>
        </style>
        

        这只需要相等的layout_heightlayout_width 设置,否则将是药丸而不是圆圈。

        【讨论】:

          【解决方案25】:

          以下创建一个圆角矩形布局对象,该对象围绕放置在其中的任何子对象绘制一个圆角矩形。它还演示了如何在不使用布局 xml 文件的情况下以编程方式创建视图和布局。

          package android.example;
          
          import android.app.Activity;
          import android.graphics.Color;
          import android.os.Bundle;
          import android.util.DisplayMetrics;
          import android.util.TypedValue;
          import android.view.ViewGroup.LayoutParams;
          import android.widget.LinearLayout;
          import android.widget.TextView;
          
          public class MessageScreen extends Activity {
           /** Called when the activity is first created. */
           @Override
           public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            int mainBackgroundColor = Color.parseColor("#2E8B57");
            int labelTextColor = Color.parseColor("#FF4500");
            int messageBackgroundColor = Color.parseColor("#3300FF");
            int messageTextColor = Color.parseColor("#FFFF00");
          
            DisplayMetrics metrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(metrics);
            float density = metrics.density;
            int minMarginSize = Math.round(density * 8);
            int paddingSize = minMarginSize * 2;
            int maxMarginSize = minMarginSize * 4;
          
            TextView label = new TextView(this);
            /*
             * The LayoutParams are instructions to the Layout that will contain the
             * View for laying out the View, so you need to use the LayoutParams of
             * the Layout that will contain the View.
             */
            LinearLayout.LayoutParams labelLayoutParams = new LinearLayout.LayoutParams(
              LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
            label.setLayoutParams(labelLayoutParams);
            label.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
            label.setPadding(paddingSize, paddingSize, paddingSize, paddingSize);
            label.setText(R.string.title);
            label.setTextColor(labelTextColor);
          
            TextView message = new TextView(this);
            RoundedRectangle.LayoutParams messageLayoutParams = new RoundedRectangle.LayoutParams(
           LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
            /*
             * This is one of the calls must made to force a ViewGroup to call its
             * draw method instead of just calling the draw method of its children.
             * This tells the RoundedRectangle to put some extra space around the
             * View.
             */
            messageLayoutParams.setMargins(minMarginSize, paddingSize,
              minMarginSize, maxMarginSize);
            message.setLayoutParams(messageLayoutParams);
            message.setTextSize(TypedValue.COMPLEX_UNIT_SP, paddingSize);
            message.setText(R.string.message);
            message.setTextColor(messageTextColor);
            message.setBackgroundColor(messageBackgroundColor);
          
            RoundedRectangle messageContainer = new RoundedRectangle(this);
            LinearLayout.LayoutParams messageContainerLayoutParams = new LinearLayout.LayoutParams(
              LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
            messageContainerLayoutParams.setMargins(paddingSize, 0, paddingSize, 0);
            messageContainer.setLayoutParams(messageContainerLayoutParams);
            messageContainer.setOrientation(LinearLayout.VERTICAL);
            /*
             * This is one of the calls must made to force a ViewGroup to call its
             * draw method instead of just calling the draw method of its children.
             * This tells the RoundedRectangle to color the the exta space that was
             * put around the View as well as the View. This is exterior color of
             * the RoundedRectangle.
             */
            messageContainer.setBackgroundColor(mainBackgroundColor);
            /*
             * This is one of the calls must made to force a ViewGroup to call its
             * draw method instead of just calling the draw method of its children.
             * This is the interior color of the RoundedRectangle. It must be
             * different than the exterior color of the RoundedRectangle or the
             * RoundedRectangle will not call its draw method.
             */
            messageContainer.setInteriorColor(messageBackgroundColor);
            // Add the message to the RoundedRectangle.
            messageContainer.addView(message);
          
            //
            LinearLayout main = new LinearLayout(this);
            LinearLayout.LayoutParams mainLayoutParams = new LinearLayout.LayoutParams(
              LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
            main.setLayoutParams(mainLayoutParams);
            main.setOrientation(LinearLayout.VERTICAL);
            main.setBackgroundColor(mainBackgroundColor);
            main.addView(label);
            main.addView(messageContainer);
          
            setContentView(main);
           }
          }
          

          RoundedRectangle 布局对象的类定义如下:

          /**
           *  A LinearLayout that draws a rounded rectangle around the child View that was added to it.
           */
          package android.example;
          
          import android.app.Activity;
          import android.content.Context;
          import android.graphics.Canvas;
          import android.graphics.Paint;
          import android.graphics.Rect;
          import android.graphics.RectF;
          import android.util.AttributeSet;
          import android.util.DisplayMetrics;
          import android.widget.LinearLayout;
          
          /**
           * A LinearLayout that has rounded corners instead of square corners.
           * 
           * @author Danny Remington
           * 
           * @see LinearLayout
           * 
           */
          public class RoundedRectangle extends LinearLayout {
           private int mInteriorColor;
          
           public RoundedRectangle(Context p_context) {
            super(p_context);
           }
          
           public RoundedRectangle(Context p_context, AttributeSet attributeSet) {
            super(p_context, attributeSet);
           }
          
           // Listener for the onDraw event that occurs when the Layout is drawn.
           protected void onDraw(Canvas canvas) {
            Rect rect = new Rect(0, 0, getWidth(), getHeight());
            RectF rectF = new RectF(rect);
            DisplayMetrics metrics = new DisplayMetrics();
            Activity activity = (Activity) getContext();
            activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
            float density = metrics.density;
            int arcSize = Math.round(density * 10);
          
            Paint paint = new Paint();
            paint.setColor(mInteriorColor);
          
            canvas.drawRoundRect(rectF, arcSize, arcSize, paint);
           }
          
           /**
            * Set the background color to use inside the RoundedRectangle.
            * 
            * @param Primitive int - The color inside the rounded rectangle.
            */
           public void setInteriorColor(int interiorColor) {
            mInteriorColor = interiorColor;
           }
          
           /**
            * Get the background color used inside the RoundedRectangle.
            * 
            * @return Primitive int - The color inside the rounded rectangle.
            */
           public int getInteriorColor() {
            return mInteriorColor;
           }
          
          }
          

          【讨论】:

            【解决方案26】:

            如果您使用 Glide 库,这将很有帮助:

            Glide.with(getApplicationContext())
                 .load(image_url)
                 .asBitmap()
                 .centerCrop()
                 .into(new BitmapImageViewTarget(imageView) {
                    @Override
                    protected void setResource(Bitmap resource) {
                      RoundedBitmapDrawable circularBitmapDrawable =
                                   RoundedBitmapDrawableFactory.create(getApplicationContext().getResources(), resource);
                      circularBitmapDrawable.setCornerRadius(dpToPx(10));
                      circularBitmapDrawable.setAntiAlias(true);
                      imageView.setImageDrawable(circularBitmapDrawable);
                    }
                 });
            
            
            public int dpToPx(int dp) {
              DisplayMetrics displayMetrics = getApplicationContext().getResources().getDisplayMetrics();
              return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
            }
            

            【讨论】:

            • 如果使用 Glide 版本 4 及以上使用 --- RequestOptions requestOptions = new RequestOptions(); requestOptions = requestOptions.transforms(new CenterCrop(), new RoundedCorners(16)); Glide.with(itemView.getContext()) .load(item.getImage()) .apply(requestOptions) .into(mProgramThumbnail);
            • @B.shruti,可能它不起作用。查看更多新鲜解决方案。
            • Anirudh,哇,它适用于矩形图像!我转换为 Kotlin,它适用于 Glide 4。在这种情况下,.asBitmap() 应该插入到 .load(image_url) 之前。
            【解决方案27】:

            非常感谢第一个回答。这是将矩形图像转换为正方形(和圆角)的修改版本,并且填充颜色作为参数传递。

            public static Bitmap getRoundedBitmap(Bitmap bitmap, int pixels, int color) {
            
                Bitmap inpBitmap = bitmap;
                int width = 0;
                int height = 0;
                width = inpBitmap.getWidth();
                height = inpBitmap.getHeight();
            
                if (width <= height) {
                    height = width;
                } else {
                    width = height;
                }
            
                Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888);
                Canvas canvas = new Canvas(output);
            
                final Paint paint = new Paint();
                final Rect rect = new Rect(0, 0, width, height);
                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(Mode.SRC_IN));
                canvas.drawBitmap(inpBitmap, rect, rect, paint);
            
                return output;
            }
            

            【讨论】:

              【解决方案28】:

              如果您的图片在互联网上,最好的方法是使用 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);
                  }
              });
              

              【讨论】:

              • 这是一个优雅的 api,但是,.centerInside 似乎丢失了,因此使用 xml 来定义这些参数可能会更好
              • 这在图片在资源中并且需要使用centerCrop时也很有用
              【解决方案29】:

              您只能在布局中使用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请求加载图像的库,这与问题无关。
              • 将加载哪个库?对于图像加载,您可以使用 glide 和 sn-p 它纯粹基于 glide 本身的方法和类。无需添加其他库
              • Glide 是一个主要用于通过 HTTP 加载图像的库,但 OP 想知道如何圆角 ImageView
              【解决方案30】:

              此处重定向的问题的答案: “如何在 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;
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-10-29
                • 1970-01-01
                • 2013-04-16
                • 1970-01-01
                • 2013-08-16
                相关资源
                最近更新 更多