如何制作带圆角的ImageView?

mic*_*ael 537 android rounded-corners imageview android-image android-imageview

在Android中,默认情况下ImageView是一个矩形.如何在ImageView中将其设置为圆角矩形(将我的Bitmap的所有4个角切掉为圆角矩形)?

Geo*_* II 538

这已经很晚了,但对于其他正在寻找此问题的人来说,您可以执行以下代码来手动围绕图像的角落.

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这有助于某人!

  • 在尝试设置imageview的scaletype时工作不正常,只有fitXY正在工作,centerCrop和其他人都显示出不可预测的结果,这里的任何人都有同样的问题吗? (15认同)
  • 对于200*200的图片,这需要将近0.03秒,所以我认为这不是最好的解决方案. (6认同)
  • 它不适用于所有设备.我需要在任何地方进行更改吗? (4认同)
  • 它只绕左上角和右上角.为什么? (2认同)
  • @vinc3m1 这里的解决方案 https://github.com/makeramen/RoundedImageView 效果非常好!另见他的回答(http://stackoverflow.com/a/15032283/2048266) (2认同)

vin*_*3m1 206

虽然上述答案有效,但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);
Run Code Online (Sandbox Code Playgroud)

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

  • 不创建位图的单独副本,它使用大量内存和大图像[与此处的大多数其他答案]
  • 支持antialisasing [vs clipPath方法]
  • 支持alpha [vs xfermode + porterduff方法]
  • 支持硬件加速 [vs clipPath方法]
  • 绘制一次到画布 [vs xfermode和clippath方法]

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

  • 请注意,如果图像大小超过2048像素,则无法使用.着色器不支持纹理大于该纹理. (10认同)

Tar*_*ych 168

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

  <android.support.v7.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"
                />
        </android.support.v7.widget.CardView>
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 似乎是一个很好的解决方法.但它不会在前Lollipops上剪辑图像. (5认同)
  • 如果,我们只需要左上角和右上角的半径而不是所有角呢? (4认同)
  • 在任何视图中应用曲线边框的非常简单和智能的方法. (2认同)
  • 要禁用卡提升使用 app:cardElevation="0dp"(不是 android:elevation) (2认同)

tyc*_*czj 125

在支持库的v21中,现在有一个解决方案:它叫做RoundedBitmapDrawable.

它基本上就像普通的Drawable一样,除非你给它一个角落半径用于裁剪:

setCornerRadius(float cornerRadius)
Run Code Online (Sandbox Code Playgroud)

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

RoundedBitmapDrawable dr = RoundedBitmapDrawableFactory.create(res, src);
dr.setCornerRadius(cornerRadius);
imageView.setImageDrawable(dr);
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢,这是下一步:http://stackoverflow.com/questions/24878740/how-to-use-roundedbitmapdrawable (3认同)
  • 这个解决方案很简单,也是最新的.它需要最少量的代码并具有很好的可扩展性.可以使用本地文件,缓存可绘制的图像,甚至可以使用Volley的NetworkImageView.我非常同意这应该是现在公认的答案,正如@Jonik指出的那样. (3认同)
  • @deadfish是的,它在`v4`支持库中,但直到支持库的`REVISION 21` (2认同)
  • 不幸的是,它不适用于scaleType`centerCrop`(支持库v25.3.1) (2认同)

hun*_*ost 119

View在API 21中向类中添加了剪切为圆形的形状.

这样做:

  • 创建一个圆形的drawable,如下所示:

RES /抽拉/ round_outline.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="10dp" />
    ...
</shape>
Run Code Online (Sandbox Code Playgroud)
  • 将drawable设置为ImageView的背景: android:background="@drawable/round_outline"
  • 根据此文档,您需要做的就是添加android:clipToOutline="true"

不幸的是,有一个错误,并且无法识别XML属性.幸运的是,我们仍然可以在Java中设置剪辑:

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

这是它的样子:

在此输入图像描述

注意:

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

关于ImageViews的特别说明

setClipToOutline()仅在视图的背景设置为可绘制形状时才有效.如果存在此背景形状,View会将形状的轮廓视为用于剪切和阴影的边框.

这意味着,如果要用于setClipToOutline()对ImageView上的角进行圆角处理,则必须使用android:src而不是android:background(因为背景必须设置为圆角形状)来设置图像.如果你必须使用背景来设置你的图像而不是src,你可以使用这个解决方法:

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

  • 错误:(x)在'android'包中找不到属性'clipToOutline'的资源标识符 (7认同)
  • 我如此“喜爱”Google 的另一个原因是,这个 bug 和我差不多年纪了,而且仍然存在于它的小世界里。谷歌似乎对此没有给出任何废话)) (7认同)
  • 取而代之的是“ android:clipToOutline”,必须使用“ android:outlineProvider =“ background”`。 (3认同)
  • 当我只将背景形状中的左上角和右上角设置为圆角时,我似乎没有成功使用此方法。 (3认同)

Gab*_*tti 118

与版本开始1.2.0-alpha03的的的材料构件库有新的ShapeableImageView

您可以使用以下内容:

  <com.google.android.material.imageview.ShapeableImageView
      ...
      app:shapeAppearanceOverlay="@style/roundedImageView"
      app:srcCompat="@drawable/ic_image" />
Run Code Online (Sandbox Code Playgroud)

和:

  <style name="roundedImageView" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">8dp</item>
  </style>
Run Code Online (Sandbox Code Playgroud)

或以编程方式:

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

在此处输入图片说明


使用jetpack compose, 1.0.x您可以使用 a 应用:clip ModifierRoundedCornerShape

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


Hir*_*tel 65

我已经通过Custom 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

如何使用:

<com.mypackage.RoundRectCornerImageView
     android:id="@+id/imageView"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@drawable/image"
     android:scaleType="fitXY" />
Run Code Online (Sandbox Code Playgroud)

输出:

在此输入图像描述

希望这会对你有所帮助.

  • 即使使用 android:scaleType="centerCrop" 也能工作,很简单,不会创建新的位图。谢谢! (2认同)
  • @Hiren 这个解决方案适用于带有背景图像的 ImageView。但它不适用于只有背景颜色而没有图像的 ImageView。你能告诉我为什么会发生这种情况吗? (2认同)
  • 此解决方案仅适用于使用“android:background”设置的图像,但不适用于“android:src”。 (2认同)

Cas*_*mer 56

我发现这两种方法都非常有助于提出一个有效的解决方案.这是我的复合版本,它是像素独立的,允许你有一些方角,其余的角具有相同的半径(这是通常的用例).感谢上述两种解决方案:

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;
}
Run Code Online (Sandbox Code Playgroud)

另外,我重写了ImageView,因此我可以在xml中定义它.你可能想要添加超级​​调用在这里制作的一些逻辑,但我已经对它进行了评论,因为它对我的情况没有帮助.

    @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);
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!

  • 非常棒,特别是扩展了ImageView (4认同)
  • 保持ImageView#onDraw()逻辑的一种简单方法是将圆角位图设置为ImageView的drawable,并保留super.onDraw()以绘制位图.我创建了一个类[RoundedCornerImageView](http://code.google.com/p/android-batsg/source/browse/android-batsg/src/com/chauhai/android/batsg/widget/RoundedCornerImageView.java) ,它的使用示例是[这里](http://code.google.com/p/android-batsg/wiki/RoundedCornerImageView).请注意我使用的getRoundedCornerBitmap()不是像素独立的. (2认同)

sha*_*esh 46

圆角图像使用ImageLoader 此处

创建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);
Run Code Online (Sandbox Code Playgroud)

或者您可以Picasso从Square 用户库.

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);
Run Code Online (Sandbox Code Playgroud)

你可以在这里下载RoundedTransformation文件

  • Picasso库似乎没有转换"占位符"和"错误"图像,因此如果您的图像无法加载(错误)或最初加载需要一段时间(占位符),它将不会将图像显示为圆形图像.https://github.com/square/picasso/issues/337 (3认同)
  • Picasso图书馆很好,很容易实现,非常感谢+1 (2认同)

小智 43

快速的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>
Run Code Online (Sandbox Code Playgroud)

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

  • 不确定为什么没有更多投票吗?在我看来,没有库和大量糟糕代码的最佳解决方案(尽管在我的案例中使用了centerCrop缩放)。 (6认同)
  • 这种方法在我的情况下适用于androidx.cardview.widget.CardView (4认同)

Chr*_*ian 26

由于所有的答案对于我来说似乎太复杂了,我认为并且来到另一个我认为值得分享的解决方案,只是在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> 
Run Code Online (Sandbox Code Playgroud)

然后在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>
Run Code Online (Sandbox Code Playgroud)


Mar*_*ler 23

可以通过ShapeableImageView使用 a来完成ShapeAppearanceOverlay

<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"/>
Run Code Online (Sandbox Code Playgroud)

风格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>
Run Code Online (Sandbox Code Playgroud)

这只需要相等layout_heightlayout_width设置,否则将是一个没有圆圈的药丸。


Dam*_*jan 14

我实现了带圆角小部件的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);

    }

}
Run Code Online (Sandbox Code Playgroud)

  • ImageUtilities来自哪里? (12认同)

ucM*_*dia 13

2023 年 11 月
尝试材质组件库并使用ShapeableImageView.
像这样的东西:

爪哇:

imageView=new ShapeableImageView(context);
imageView.setShapeAppearanceModel(
        imageView.getShapeAppearanceModel()
                 .toBuilder()
                 .setAllCornerSizes(20)
                 .build());
Run Code Online (Sandbox Code Playgroud)

科特林:

val imageView = ShapeableImageView(context)
imageView.setShapeAppearanceModel(
        imageView.getShapeAppearanceModel()
                 .toBuilder()
                 .setAllCornerSizes(20f)
                 .build())
Run Code Online (Sandbox Code Playgroud)

喷气背包组成:

   Image(
        modifier = Modifier.clip(RoundedCornerShape(X)),
        painter = painterResource(id = R.drawable.photo),
        contentDescription = null)
Run Code Online (Sandbox Code Playgroud)

X是一个数值,一个单一值,用于创建四个角应用相同大小的形状。您还可以为每个角使用四个不同的值。

x : Int = 50 // Size in percents
x : Float = 25f // Size in pixels
x : Dp = 25.dp // Size in Dp
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


Sir*_*lot 11

截至最近,还有另一种方法 - 使用Glide的Generated API.它需要一些初步的工作,但随后给你Glide的所有功能,可以灵活地做任何事情,因为你写了实际的代码,所以我认为从长远来看这是一个很好的解决方案.此外,使用非常简单和整洁.

首先,设置Glide版本4+:

implementation 'com.github.bumptech.glide:glide:4.6.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.6.1'
Run Code Online (Sandbox Code Playgroud)

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

@GlideModule
public final class MyAppGlideModule extends AppGlideModule {}
Run Code Online (Sandbox Code Playgroud)

然后创建实际完成工作的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));
    }
}
Run Code Online (Sandbox Code Playgroud)

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

然后在你的代码中使用它,如下所示:

GlideApp.with(this)
        .load(imageUrl)
        .roundedCorners(getApplicationContext(), 5)
        .into(imageView);
Run Code Online (Sandbox Code Playgroud)


Vah*_*hid 9

科特林

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)
Run Code Online (Sandbox Code Playgroud)

为了使ImageView循环,我们可以改变cornerRadius

rounded.isCircular = true
Run Code Online (Sandbox Code Playgroud)


grr*_*ore 9

有一个很酷的库,可以让你塑造形象视图.

这是一个例子:

<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"/>
Run Code Online (Sandbox Code Playgroud)

形状定义:

<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>
Run Code Online (Sandbox Code Playgroud)

结果:

结果


dea*_*ish 8

这是一个覆盖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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

我只是重写了setImageDrawable支持v4方法,并将其用于可绘制的圆形位图。

用法:

<com.example.widgets.RoundedImageView
        android:layout_width="39dp"
        android:layout_height="39dp"
        android:src="@drawable/your_drawable" />
Run Code Online (Sandbox Code Playgroud)

使用imageView和自定义imageView进行预览:

在此处输入图片说明


MrS*_*ake 7

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

如果您想在图像周围使用框架,您还可以将圆形框架叠加在布局中的图像视图顶部.

[编辑]通过使用FrameLayout例如将帧叠加到原始图像上.第一个元素FrameLayout将是您想要四舍五入的图像.然后ImageView用框架添加另一个.第二个ImageView将显示在原始文件的顶部,ImageView因此Android将在orignal上方绘制它的内容ImageView.


小智 6

上面的乔治沃尔特斯二世的道具,我只是采取了他的答案并扩展了一点,以支持不同的圆角.这可以进一步优化(一些目标重叠),但不是很多.

我知道这个帖子有点陈旧,但它是谷歌查询如何在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;
}
Run Code Online (Sandbox Code Playgroud)


小智 6

为什么不在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;
        }
    }

}
Run Code Online (Sandbox Code Playgroud)


Ale*_*lex 6

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);
Run Code Online (Sandbox Code Playgroud)


j7n*_*n7k 6

在我的情况下,这个纯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>
Run Code Online (Sandbox Code Playgroud)

在布局文件中,添加包含标准ImageView的LinearLayout,以及嵌套的FrameLayout.FrameLayout使用填充和自定义drawable来给出圆角的错觉.

<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>
Run Code Online (Sandbox Code Playgroud)


us_*_*vid 6

答案中提供的任何方法都不适合我。如果您的 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);
}
Run Code Online (Sandbox Code Playgroud)

没有要定义的 xml 形状,上面的代码只为顶部创建角,普通方法不起作用。如果您需要圆角 4 个角,请删除:

"+ curveRadius"  
Run Code Online (Sandbox Code Playgroud)

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

安卓开发者文档


请注意,与 Android 中的任何度量一样,您必须“转换”通常来自 DP 的大小。在上面的示例中,假设您希望半径为 24

                            int curveRadius = 24;
Run Code Online (Sandbox Code Playgroud)

例如,您可能稍后会在半径设置为“24”的 drawable 中添加边框,并且您希望它匹配。因此,

    float desiredRadius = 24;
    float radiusConverted = TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            desiredRadius,
            itemView.getContext().getResources().getDisplayMetrics());
Run Code Online (Sandbox Code Playgroud)

进而

                            int curveRadius = radiusConverted;
Run Code Online (Sandbox Code Playgroud)


Dan*_*OMS 5

下面创建一个圆角矩形布局对象,围绕放置在其中的任何子对象绘制一个圆角矩形.它还演示了如何在不使用布局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);
 }
}
Run Code Online (Sandbox Code Playgroud)

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

}
Run Code Online (Sandbox Code Playgroud)


jig*_*gar 5

将形状应用于您的形状,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>
Run Code Online (Sandbox Code Playgroud)

这可能对您的朋友有帮助。


Ani*_*udh 5

如果您正在使用 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));
}
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

419537 次

最近记录:

5 年,11 月 前