ImageView圆角化

36

我想让这张图片拥有圆角。我使用了以下的 XML 代码,并将其应用在我的 ImageView 上。但是图片会重叠在圆角外面。我通过异步任务下载该图片。

<?xml version="1.0" encoding="utf-8"?>
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
 android:shape="rectangle" >
 <corners android:radius="20dip" />
</shape>


<ImageView
    android:id="@+id/trVouchersImage"
    android:layout_width="55dp"
    android:layout_height="55dp"
    android:layout_marginLeft="8dp"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true"
    android:layout_alignParentLeft="true"
    android:background="@drawable/ash_arrow"
 />

有一个库可以让你轻松地完成这个任务。在这里 - Yvan RAJAONARIVONY
6
重要提示:您需要将形状用作图像源,原始图像用作背景图像。 这就是诀窍。 - Pradip
你可以使用这个库 implementation 'de.hdodenhof:circleimageview:3.1.0' <de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/profile_image" android:layout_width="96dp" android:layout_height="96dp" android:src="@drawable/profile" app:civ_border_width="2dp" app:civ_border_color="#FF000000"/> - Ali Hassan
17个回答

38

最简单的方法:

在您的应用程序的res/drawable/文件夹下创建一个名为rounded_fg.xml的xml文件。 rounded_fg.xml文件的内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:innerRadiusRatio="2"
    android:shape="ring"
    android:thicknessRatio="1"
    android:useLevel="false">
    <gradient
        android:type="radial"
        android:gradientRadius="8dp"
        android:endColor="@color/white"
       />
</shape>

您可以将endColor与ImageView容器布局背景进行匹配,并且根据您的要求,gradientRadius可以是任何值(<=36dp)。

现在将此可绘制对象用作图像视图的前景,如下所示:

 <ImageView
     android:layout_width="55dp"
     android:layout_height="55dp" 
     android:foreground="@drawable/rounded_fg" />

与正方形图片和/或图像视图完美配合使用。

正方形图片/图像视图:

正方形图片/图像视图

矩形图片/图像视图:

矩形图片/图像视图

前景应用于按钮上:

前景应用于按钮上


2
如何制作矩形?你能给一个示例吗? - Leon
如果ImageView布局的高度和宽度不同,那么你将会得到一个如上图所示的矩形视图。这种技术不能为矩形视图提供完美的圆角效果,对于正方形视图效果最佳。这就是为什么我进行了比较。如果你认为可以接受,那就使用它吧。 - Nihal
我们可以将其用于带有圆角的矩形视图吗?@Nihal - Parth Anjaria
无法获取精确值,您能在此处添加详细信息吗? - Parth Anjaria
@ParthAnjaria 你在谈论什么值?drawable rounded_fg.xml 文件中不会有任何变化。只有容器视图的尺寸(宽度和高度)会发生变化。 - Nihal
显示剩余2条评论

23

我使用Universal Image Loader库来下载并将图像的边角变圆,并且它对我起作用。

ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(thisContext)
            // You can pass your own memory cache implementation
           .discCacheFileNameGenerator(new HashCodeFileNameGenerator())
           .build();

DisplayImageOptions options = new DisplayImageOptions.Builder()
            .displayer(new RoundedBitmapDisplayer(10)) //rounded corner bitmap
            .cacheInMemory(true)
            .cacheOnDisc(true)
            .build();

ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.init(config);
imageLoader.displayImage(image_url,image_view, options );

请注意,使用RoundedBitmapDisplayer会导致OOM异常。 - zionpi

16

现在我们无需使用任何第三方库或自定义imageView

现在我们可以使用ShapeableImageView

示例代码

首先在您的build.gradle文件中添加以下dependencies

implementation 'com.google.android.material:material:1.2.0-alpha05'

使用编码使ImageView变为圆形

在您的布局中添加ShapeableImageView

<com.google.android.material.imageview.ShapeableImageView
    android:id="@+id/myShapeableImageView"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:layout_margin="20dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:srcCompat="@drawable/nilesh" />

将ImageView变成圆形的Kotlin代码

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.google.android.material.shape.CornerFamily
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


//        <dimen name="image_corner_radius">50dp</dimen>

        val radius = resources.getDimension(R.dimen.image_corner_radius)
        myShapeableImageView.shapeAppearanceModel = myShapeableImageView.shapeAppearanceModel
            .toBuilder()
            .setTopRightCorner(CornerFamily.ROUNDED, radius)
            .setTopLeftCorner(CornerFamily.ROUNDED, radius)
            .setBottomLeftCorner(CornerFamily.ROUNDED, radius)
            .setBottomRightCorner(CornerFamily.ROUNDED, radius)
            .build()

            // or  You can use setAllCorners() method

        myShapeableImageView.shapeAppearanceModel = myShapeableImageView.shapeAppearanceModel
            .toBuilder()
            .setAllCorners(CornerFamily.ROUNDED, radius)
            .build()


    }
}

输出

enter image description here

如何通过样式将ImageView变成圆形

首先,在你的 style.xml 文件中创建以下样式

<style name="circleImageViewStyle" >
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">50%</item>
</style>

现在像这样在你的布局中使用那个样式

<com.google.android.material.imageview.ShapeableImageView
    android:id="@+id/myShapeableImageView"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:layout_margin="20dp"
    app:shapeAppearanceOverlay="@style/circleImageViewStyle"
    app:srcCompat="@drawable/nilesh" />

输出

在此输入图像描述

请在此处查找完整示例,了解如何使用ShapeableImageView


16

你可以通过以下方式使用XML进行操作

<stroke android:width="3dp"
        android:color="#ff000000"/>

<padding android:left="1dp"
         android:top="1dp"
         android:right="1dp"
         android:bottom="1dp"/> 

<corners android:radius="30px"/> 

实际上,您可以创建圆形位图并将其设置在ImageView中。

public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
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 = 12;

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;
}

对于通用的懒加载器,你也可以使用这个。

DisplayImageOptions options = new DisplayImageOptions.Builder()
        .displayer(new RoundedBitmapDisplayer(25)) // default
        .build();

我尝试了第二段代码,但问题是我下载图像并将其保存为位图,然后将位图进行圆角处理,并将其设置为图像视图。 图像视图是表格布局的一部分。在第一次安装时,它没有对图像进行圆角处理。但之后就可以正常工作了。为什么第一次不起作用呢? - FIXI
你是否正在使用UniversalImageLoader库? - Sanket Kachhela
我已经包含了库,但不知道该使用哪种方法来使边角变圆。 - FIXI
如果是使用该库,则可以设置半径。如果使用其他库,则只需将其显示为圆角。因此,首先将位图转换,然后将其保存为SD卡中的缓存。 - Sanket Kachhela

12

新答案 使用 Glide 库来实现。这个库也是 Google 推荐的。参见如何使用 Glide 库对图像进行圆角处理?

旧答案 只需将该图像添加到一个 cardView 中,并将 cardView 的高度设置为 0dp... 就可以解决问题了(在我的情况下是一个带有图片的 viewPager - 只需用一个 ImageView 替换 viewPager)。

<android.support.v7.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="250dp"
    app:cardElevation="0dp">

    <android.support.v4.view.ViewPager
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

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

哇,我很惊讶这个能用!不知道效率如何。 - eddie
2
我认为这应该适用于早期的Lollipop版本,因为您使用了v7兼容库。 - Alexandru Circus
你需要在 CardView 中定义 app:contentPadding="0dp"。否则,它将具有默认填充。 - Moses Aprico
@Marchy - 现在我建议使用Glide库(也被Google推荐)来实现这个效果。https://dev59.com/U18e5IYBdhLWcg3w4dik - Alexandru Circus

9
你应该使用来自这个库RoundedCornersTransformation,并创建一个圆形的ImageView
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import com.squareup.picasso.Transformation;

public class RoundedCornersTransformation implements Transformation {

    public enum CornerType {
        ALL,
        TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT,
        TOP, BOTTOM, LEFT, RIGHT,
        OTHER_TOP_LEFT, OTHER_TOP_RIGHT, OTHER_BOTTOM_LEFT, OTHER_BOTTOM_RIGHT,
        DIAGONAL_FROM_TOP_LEFT, DIAGONAL_FROM_TOP_RIGHT
    }

    private int mRadius;
    private int mDiameter;
    private int mMargin;
    private CornerType mCornerType;

    public RoundedCornersTransformation(int radius, int margin) {
        this(radius, margin, CornerType.ALL);
    }

    public RoundedCornersTransformation(int radius, int margin, CornerType cornerType) {
        mRadius = radius;
        mDiameter = radius * 2;
        mMargin = margin;
        mCornerType = cornerType;
    }

    @Override public Bitmap transform(Bitmap source) {
        int width = source.getWidth();
        int height = source.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
        drawRoundRect(canvas, paint, width, height);
        source.recycle();
        return bitmap;
    }

    private void drawRoundRect(Canvas canvas, Paint paint, float width, float height) {
        float right = width - mMargin;
        float bottom = height - mMargin;
        switch (mCornerType) {
            case ALL:
                canvas.drawRoundRect(new RectF(mMargin, mMargin, right, bottom), mRadius, mRadius, paint);
            break;
            case TOP_LEFT:
                drawTopLeftRoundRect(canvas, paint, right, bottom);
            break;
            case TOP_RIGHT:
                drawTopRightRoundRect(canvas, paint, right, bottom);
            break;
            case BOTTOM_LEFT:
                drawBottomLeftRoundRect(canvas, paint, right, bottom);
            break;
            case BOTTOM_RIGHT:
                drawBottomRightRoundRect(canvas, paint, right, bottom);
            break;
            case TOP:
                drawTopRoundRect(canvas, paint, right, bottom);
            break;
            case BOTTOM:
                drawBottomRoundRect(canvas, paint, right, bottom);
            break;
            case LEFT:
                drawLeftRoundRect(canvas, paint, right, bottom);
            break;
            case RIGHT:
                drawRightRoundRect(canvas, paint, right, bottom);
            break;
            case OTHER_TOP_LEFT:
                drawOtherTopLeftRoundRect(canvas, paint, right, bottom);
            break;
            case OTHER_TOP_RIGHT:
                drawOtherTopRightRoundRect(canvas, paint, right, bottom);
            break;
            case OTHER_BOTTOM_LEFT:
                drawOtherBottomLeftRoundRect(canvas, paint, right, bottom);
            break;
            case OTHER_BOTTOM_RIGHT:
                drawOtherBottomRightRoundRect(canvas, paint, right, bottom);
            break;
            case DIAGONAL_FROM_TOP_LEFT:
                drawDiagonalFromTopLeftRoundRect(canvas, paint, right, bottom);
            break;
            case DIAGONAL_FROM_TOP_RIGHT:
                drawDiagonalFromTopRightRoundRect(canvas, paint, right, bottom);
            break;
            default:
                canvas.drawRoundRect(new RectF(mMargin, mMargin, right, bottom), mRadius, mRadius, paint);
            break;
        }
    }

    private void drawTopLeftRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
        canvas.drawRoundRect(new RectF(mMargin, mMargin, mMargin + mDiameter, mMargin + mDiameter), mRadius, mRadius, paint);
        canvas.drawRect(new RectF(mMargin, mMargin + mRadius, mMargin + mRadius, bottom), paint);
        canvas.drawRect(new RectF(mMargin + mRadius, mMargin, right, bottom), paint);
    }

    private void drawTopRightRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
        canvas.drawRoundRect(new RectF(right - mDiameter, mMargin, right, mMargin + mDiameter), mRadius, mRadius, paint);
        canvas.drawRect(new RectF(mMargin, mMargin, right - mRadius, bottom), paint);
        canvas.drawRect(new RectF(right - mRadius, mMargin + mRadius, right, bottom), paint);
    }

    private void drawBottomLeftRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
        canvas.drawRoundRect(new RectF(mMargin, bottom - mDiameter, mMargin + mDiameter, bottom), mRadius, mRadius, paint);
        canvas.drawRect(new RectF(mMargin, mMargin, mMargin + mDiameter, bottom - mRadius), paint);
        canvas.drawRect(new RectF(mMargin + mRadius, mMargin, right, bottom), paint);
    }

    private void drawBottomRightRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
        canvas.drawRoundRect(new RectF(right - mDiameter, bottom - mDiameter, right, bottom), mRadius, mRadius, paint);
        canvas.drawRect(new RectF(mMargin, mMargin, right - mRadius, bottom), paint);
        canvas.drawRect(new RectF(right - mRadius, mMargin, right, bottom - mRadius), paint);
    }

    private void drawTopRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
        canvas.drawRoundRect(new RectF(mMargin, mMargin, right, mMargin + mDiameter), mRadius, mRadius, paint);
        canvas.drawRect(new RectF(mMargin, mMargin + mRadius, right, bottom), paint);
    }

    private void drawBottomRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
        canvas.drawRoundRect(new RectF(mMargin, bottom - mDiameter, right, bottom), mRadius, mRadius, paint);
        canvas.drawRect(new RectF(mMargin, mMargin, right, bottom - mRadius), paint);
    }

    private void drawLeftRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
        canvas.drawRoundRect(new RectF(mMargin, mMargin, mMargin + mDiameter, bottom), mRadius, mRadius, paint);
        canvas.drawRect(new RectF(mMargin + mRadius, mMargin, right, bottom), paint);
    }

    private void drawRightRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
        canvas.drawRoundRect(new RectF(right - mDiameter, mMargin, right, bottom), mRadius, mRadius, paint);
        canvas.drawRect(new RectF(mMargin, mMargin, right - mRadius, bottom), paint);
    }

    private void drawOtherTopLeftRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
        canvas.drawRoundRect(new RectF(mMargin, bottom - mDiameter, right, bottom), mRadius, mRadius, paint);
        canvas.drawRoundRect(new RectF(right - mDiameter, mMargin, right, bottom), mRadius, mRadius, paint);
        canvas.drawRect(new RectF(mMargin, mMargin, right - mRadius, bottom - mRadius), paint);
    }

    private void drawOtherTopRightRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
        canvas.drawRoundRect(new RectF(mMargin, mMargin, mMargin + mDiameter, bottom), mRadius, mRadius, paint);
        canvas.drawRoundRect(new RectF(mMargin, bottom - mDiameter, right, bottom), mRadius, mRadius, paint);
        canvas.drawRect(new RectF(mMargin + mRadius, mMargin, right, bottom - mRadius), paint);
    }

    private void drawOtherBottomLeftRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
        canvas.drawRoundRect(new RectF(mMargin, mMargin, right, mMargin + mDiameter), mRadius, mRadius, paint);
        canvas.drawRoundRect(new RectF(right - mDiameter, mMargin, right, bottom), mRadius, mRadius, paint);
        canvas.drawRect(new RectF(mMargin, mMargin + mRadius, right - mRadius, bottom), paint);
    }

    private void drawOtherBottomRightRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
        canvas.drawRoundRect(new RectF(mMargin, mMargin, right, mMargin + mDiameter), mRadius, mRadius, paint);
        canvas.drawRoundRect(new RectF(mMargin, mMargin, mMargin + mDiameter, bottom), mRadius, mRadius, paint);
        canvas.drawRect(new RectF(mMargin + mRadius, mMargin + mRadius, right, bottom), paint);
    }

    private void drawDiagonalFromTopLeftRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
        canvas.drawRoundRect(new RectF(mMargin, mMargin, mMargin + mDiameter, mMargin + mDiameter), mRadius, mRadius, paint);
        canvas.drawRoundRect(new RectF(right - mDiameter, bottom - mDiameter, right, bottom), mRadius, mRadius, paint);
        canvas.drawRect(new RectF(mMargin, mMargin + mRadius, right - mDiameter, bottom), paint);
        canvas.drawRect(new RectF(mMargin + mDiameter, mMargin, right, bottom - mRadius), paint);
    }

    private void drawDiagonalFromTopRightRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
        canvas.drawRoundRect(new RectF(right - mDiameter, mMargin, right, mMargin + mDiameter), mRadius, mRadius, paint);
        canvas.drawRoundRect(new RectF(mMargin, bottom - mDiameter, mMargin + mDiameter, bottom), mRadius, mRadius, paint);
        canvas.drawRect(new RectF(mMargin, mMargin, right - mRadius, bottom - mRadius), paint);
        canvas.drawRect(new RectF(mMargin + mRadius, mMargin + mRadius, right, bottom), paint);
    }

    @Override public String key() {
        return "RoundedTransformation(radius=" + mRadius + ", margin=" + mMargin + ", diameter=" + mDiameter + ", cornerType=" + mCornerType.name() + ")";
    }
}

2
我需要将图像变成圆形,那么在这种情况下角落的值应该是多少? - Pravinsingh Waghela
3
这将使背景变成圆形,但是imageView中的图像仍然是矩形的。这不是合适的答案。 - Naveed Ahmad
这仅仅是设置了一个带有圆角的背景...如果你去掉颜色和填充,图像不会改变。 - Andrew Quebe

4
  • 也许你已经找到了解决方案,但我最近发现了一个新的库,它允许你创建任何形状并将其设置为ImageView

    • 这里下载该库
    • 定义您的Xml如下:
    • <com.makeramen.roundedimageview.RoundedImageView......... app:riv_corner_radius="Yourradiusdip"/>
    • 享受编码吧!我发现这个库是最好的!谢谢 [我后来发布了这个答案,但我最近使用了它并发现它真的很有用]

3

想知道是否仍有人需要完成此项任务。

对于他们来说:您可以使用RoundedBitmapDrawable来实现您的目的。

示例代码:

ImageView profilePic = (ImageView) findViewById(R.idimageView);

RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(this.getResources(),bitmap);
roundedBitmapDrawable.setCircular(true);
profilePic.setImageDrawable(roundedBitmapDrawable);

其中bitmap是您想要在imageView中加载的图像。


3
创建一个可绘制的XML文件。
<shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
        <corners android:radius="8dp" />
       <solid android:color="@android:color/white" />
<stroke
    android:width="1dp"
    android:color="@color/md_white_1000" />

在你的布局中,将drawable作为imageView的背景添加。
    <ImageView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:src="@drawable/photo"
        android:background="@drawable/roundcorners"/>

然后,您需要在Java代码中添加此行。

ImageView.setClipToOutline(true);

注意:此功能仅适用于21级或以上。

2

我在这里发现了一些东西:github

稍微改进了一下。非常简单和清晰。没有外部文件或方法:

public class RoundedImageView extends ImageView {


private float mCornerRadius = 10.0f;

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

public RoundedImageView(Context context, AttributeSet attributes) {
    super(context, attributes);
}



@Override
protected void onDraw(Canvas canvas) {
    // Round some corners betch!
    Drawable myDrawable = getDrawable();

    if (myDrawable!=null && myDrawable instanceof BitmapDrawable && mCornerRadius > 0) {
        Paint paint = ((BitmapDrawable) myDrawable).getPaint();
        final int color = 0xff000000;
        Rect bitmapBounds = myDrawable.getBounds();
        final RectF rectF = new RectF(bitmapBounds);
        // Create an off-screen bitmap to the PorterDuff alpha blending to work right
        int saveCount = canvas.saveLayer(rectF, null,
                Canvas.MATRIX_SAVE_FLAG |
                Canvas.CLIP_SAVE_FLAG |
                Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
                Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
                Canvas.CLIP_TO_LAYER_SAVE_FLAG);
        // Resize the rounded rect we'll clip by this view's current bounds
        // (super.onDraw() will do something similar with the drawable to draw)
        getImageMatrix().mapRect(rectF);

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

        Xfermode oldMode = paint.getXfermode();
        // This is the paint already associated with the BitmapDrawable that super draws
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        super.onDraw(canvas);
        paint.setXfermode(oldMode);
        canvas.restoreToCount(saveCount);
    } else {
        super.onDraw(canvas);
    }
}


}

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