Android 圆角、圆形 ImageView 实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 圆角、圆形 ImageView 实现相关的知识,希望对你有一定的参考价值。

参考技术A

我们要实现的图片控件继承自 AppCompatImageView ,它是 ImageView 的子类,但提供了更好的兼容性,我们在此基础上添加了若干自定义的属性和方法以实现最终的 NiceImageView :

要实圆角或者圆形的显示效果,就是对图片显示的内容区域进行“裁剪”,只显示指定的区域即可。如何做呢?

一种比较直接的办法是这样的,由于图片是被绘制在画布上的,所以用 canvas 的 clipPath() 方法先将画布裁剪成指定形状,这样就能让图片按指定形状显示了,重新 draw() 方法即可:

这样使用 src 、 background 属性给ImageView设置显示的图片都能达到预期的显示效果。但是由于 clipPath() 方法不支持抗锯齿,图片边缘会有明显的毛糙感,体验并不理想,所以需要寻找其它方法。

另一种方法是使用图像的 Alpha 合成模式 ,即
PorterDuff 来实现, 官方文档 。这里我们使用其中的 DST_IN 模式。整个过程就是先绘制目标图像,也就是图片;再绘制原图像,即一个圆角矩形或者圆形,这样最终目标图像只显示和原图像重合的区域。

到这里就实现了显示为圆角或者圆形了。但是需要通过 src 属性或者对应的方法来设置图片,否则不能达到预期效果。

绘制边框就相对容易理解了,只需要绘制一个指定样式的圆角矩形或者圆形即可:

当图片显示为圆形时,还可以绘制一个内边框,但圆角矩形的话由于圆角大小的问题,目前只能设置一个边框咯。

但是有个问题,绘制的边框会覆盖在图片上,如果边框太宽会导致图片的可见区域变小了,影像显示效果,像这样,左下角的花盆不见了:

那么如何让边框不覆盖在图片上呢?可以在 Alpha 合成绘制前先将画布缩小一定比例,最后再绘制边框,这样问题就解决了。

缩放后的ImageView显示区域的宽高就是原宽、高分别减去2倍的边框宽度,这样缩小的比例也就显而易见了。效果如下,左下角的花盆出来了:

遮罩可以理解为一层带透明度的颜色,遮罩默认不绘制,当制定了遮罩颜色时才会绘制,实现很简单:

例如加一个透明度30%的红色遮罩后的效果:

核心的实现逻辑就这些了,剩下的就是自定义属性和方法了,有兴趣的可以看源码,都很简单,希望对你有所帮助吧!

更多细节及用法见GitHub: https://github.com/SheHuan/NiceImageView

如果你需要实现类似钉钉的圆形组合头像,例如:

Xamarin Android 圆角边框与彩色 ImageView

【中文标题】Xamarin Android 圆角边框与彩色 ImageView【英文标题】:Xamarin Android round corner border with color ImageView 【发布时间】:2016-06-15 06:41:35 【问题描述】:

我正在使用 BaseAdapter 以自定义布局呈现 GridView。我的视图在 ImageView 下包含 ImageView 和 TextView。对于 ImageView 我想用黑色设置圆角边框。

我尝试了一些来自社区答案的建议。

    创建带有圆形边框的可绘制对象并将其设置为 ImageView 的背景。 使用另一个虚拟 ImageView 将 ImageView 包装到 FrameLayout 中,该虚拟 ImageView 将用作框架,并将可绘制的边框设置为它的背景。 使用 RoundedBitmapDrawableFactory 创建 RoundedBitmap 并将可绘制的边框设置为背景。

在上述所有情况下,我都没有得到我想得到的效果。 图像边框仅与图像重叠。

在 #3 中,问题是边框和圆角位图角彼此不完全匹配。我不确定如何支持多种屏幕尺寸和密度see here

如果我使用代码创建圆角位图,则存在严重的内存问题: more details, see comments. Further details

对于选项 3 代码:

internal void SetImageWithRoundCorners(int imageResID, Context context)

    Resources res = context.Resources;
    Bitmap src = BitmapFactory.DecodeResource(res, imageResID);
    RoundedBitmapDrawable dr = RoundedBitmapDrawableFactory.Create(res, src);
    dr.CornerRadius = 50.0f;
    ImgTopicIcon.SetImageDrawable(dr);

round_border_corner.xml

<!-- language: lang-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="2dp"
        android:top="2dp"
        android:right="2dp"
        android:bottom="2dp" />
     <corners android:radius="@dimen/GVImgRoundCornerRad" />
     <stroke android: android:color="#ff000000" />
</shape> 

Grid_Custom_Item.xml

<!-- language: lang-xml -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_
    android:layout_
    android:minHeight="48dp"
    android:gravity="center"
    android:orientation="vertical">
    <FrameLayout
        android:layout_
        android:layout_>
        <ImageView
            android:layout_
            android:layout_
            android:id="@+id/ImgCategoryIcon" />
        <ImageView
            android:src="@drawable/round_corner_border"
            android:layout_
            android:layout_ />
    </FrameLayout>
    <TextView
    android:layout_
    android:layout_
    android:textColor="@android:color/black"
    android:id="@+id/TxtCategoryName"
    android:gravity="center" />
</LinearLayout>

预期结果: http://screencast.com/t/6hd8moeTgqAQ

输出: http://screencast.com/t/WVgdlyq87IU

任何人都知道如何在没有内存问题的情况下实现所需的输出。

【问题讨论】:

【参考方案1】:

您可以定义一个自定义的 ImageView 来在图像上添加颜色边框;这是我多年前的一个项目,它是一种适用于 Android 操作系统的圆形图像小部件。

https://github.com/avenwu/IndexImageView

【讨论】:

以上是关于Android 圆角、圆形 ImageView 实现的主要内容,如果未能解决你的问题,请参考以下文章

Android自定义圆角矩形ImageView,支持Glide加载图片及颜色填充

Android自定义圆角矩形ImageView,支持Glide加载图片及颜色填充

Android圆角图片和圆形图片实现总结

Xamarin Android 圆角边框与彩色 ImageView

Android圆角图片和圆形图片实现总结

如何在圆形 imageView android 上添加一个阴影和边界