带有自定义视图的圆角图像视图

Rounded corner image view with a custom view

我目前正在尝试制作一个不使用任何库的项目。现在,我想多次使用圆形图像我不能只这样做:

<CardView>
   <ImageView/>
</CardView>

每次。所以,我决定为它定制一个class。这是我的 class:

class RoundedImageView : AppCompatImageView {

    constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet) {
        init(attributeSet)
    }

    constructor(context: Context) : super(context) {
        init(null);
    }

    private fun init(attributeSet: AttributeSet?) {
        if (attributeSet == null) return

        val typedArray: TypedArray =
            context.obtainStyledAttributes(attributeSet, R.styleable.RoundedImageView, 0, 0)
        try {
            val bitmapDrawable : BitmapDrawable? = drawable as? BitmapDrawable

            val cornerRadius = typedArray.getDimension(R.styleable.RoundedImageView_cornerRadius,0F)

            bitmapDrawable?.bitmap?.let { getRoundedCornerBitmap(it, cornerRadius) }
        }finally {
            typedArray.recycle()
        }
    }

    private fun getRoundedCornerBitmap(bitmap: Bitmap, pixels: Float) {
        val output = Bitmap.createBitmap(
            bitmap.width, bitmap
                .height, Bitmap.Config.ARGB_8888
        )
        val canvas = Canvas(output)
        val color = -0xbdbdbe
        val paint = Paint()
        val rect = Rect(0, 0, bitmap.width, bitmap.height)
        val rectF = RectF(rect)
        val roundPx = pixels.toFloat()
        paint.isAntiAlias = true
        canvas.drawARGB(0, 0, 0, 0)
        paint.color = color
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint)
        paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
        canvas.drawBitmap(bitmap, rect, rect, paint)
        setImageBitmap(bitmap)
    }
}

但是,这似乎不起作用。这就是我得到的结果:

而且,这是我用于它的代码:

<com.sambhav2358.facebookclone.customviews.RoundedImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"/>

我什至不确定代码是否到达那个方法


PS:不要将其标记为重复,因为我在这里尝试了所有方法,但其中 none 似乎有效。即使那个方法 getRoundedCornerBitmap 是从答案中提取的,但那是行不通的。

你可以尝试下面的代码并参考官方 link 了解更多详情。

<com.google.android.material.imageview.ShapeableImageView
        android:id="@+id/ivNotificationIcon"
        android:layout_width="@dimen/_45sdp"
        android:layout_height="@dimen/_45sdp"
         android:backgroundTint="#EEF3F7"
        android:contentDescription="@string/image_description"
        android:scaleType="centerInside"   
 app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize50Percent"
        app:srcCompat="@drawable/slider" />

并将此样式添加到您的样式中。xml/theme。xml

 <style name="ShapeAppearanceOverlay.App.CornerSize50Percent" parent="">
 <item name="cornerFamily">rounded</item>
        <item name="cornerSize">50%</item>
        <item name="backgroundTint">@android:color/white</item>        </style>

根据您的要求,您将添加自定义样式的项目。

首先,您不是在 view 的 canvas 上绘制,您必须覆盖 onDraw 才能在 view 上绘制任何内容canvas。而且,由于您只是想让图像的四角呈圆形,因此不需要 PorterDuff。您可以从 canvas 中剪下一个圆角矩形,这足以满足您的用例。

您不必手动覆盖AppCompatImageView的每个构造函数,您可以使用@JvmOverloads注解覆盖java class中的每个构造函数kotlin.

使用core-ktx的withStyledAttributes扩展函数访问attributeSet

init 块可用于在 primary constructor.

之后执行代码

不要在 onDraw 内部进行对象分配,尽可能重用像 paintpath 这样昂贵的对象。

记住以上几点,你的class可以这样改

class RoundedImageView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet,
    defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr) {
    val path = Path()
    var cornerRadius: Float = 0f

    init {
        context.withStyledAttributes(attrs, R.styleable.RoundedImageView) {
            cornerRadius = getDimension(R.styleable.RoundedImageView_cornerRadius, 0F)
        }
    }

    override fun onDraw(canvas: Canvas?) {
        val corners = floatArrayOf(
            cornerRadius,
            cornerRadius,
            cornerRadius,
            cornerRadius,
            cornerRadius,
            cornerRadius,
            cornerRadius,
            cornerRadius
        )

        path.addRoundRect(
            0f,
            0f,
            width.toFloat(),
            height.toFloat(),
            corners,
            Path.Direction.CW
        )

        canvas?.clipPath(path)
        super.onDraw(canvas)
    }
}

现在可以这样用了

<com.sambhav2358.facebookclone.customviews.RoundedImageView
        android:layout_width="200dp"
        android:layout_height="200dp"
        app:cornerRadius="70dp"
        android:src="@drawable/ic_launcher_background"
        />

您可以创建一个 Drawable 资源,如下所示,rounded_corners.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
    <corners android:radius="5dp"/>
    <solid android:color="#00000000"/>
</shape>

然后您可以按如下方式使用它:

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/rounded_corners"/>

这将创建任何带圆角的 ImageView。您可以在 rounded_corners.xml 中控制半径和您需要的一切 我将其创建为透明的,因此您可以在 ImageView 中放置任何您想要的图像。