如何在带有中心裁切的自定义图像视图中制作圆形图像?

问题描述 投票:0回答:2

我想为可在两种模式下工作的化身创建自定义图像视图:

  1. 如果android:src为空,则显示带有名字首字母的圆圈
  2. 其他显示圆圈的头像

现在,如果我使用android:src,则我的drawable不在中心,如何对其进行中心裁剪?

Example

这是自定义视图的代码:

class AvatarImageView : AppCompatImageView{

    private var letter = ""
    private var avatarBackgroundColor = 0
    private var avatarLetterColor = 0

    private val paintBackground = Paint()
    private val paintLetter = Paint(Paint.LINEAR_TEXT_FLAG)
    private val paintAvatarImage = Paint()

    private var circleX = 0f
    private var circleY = 0f
    private var circleRadius = 0f

    private var letterX = 0f
    private var letterY = 0f

    private val avatarImageRect = RectF(0f, 0f, 0f, 0f)

    constructor(context : Context)
            : this(context, null)

    constructor(context: Context, attrs : AttributeSet?)
            : this(context, attrs, 0)

    constructor(context: Context, attrs : AttributeSet?, defStyleAttr : Int)
            : super(context, attrs, defStyleAttr){
        attrs?.let{
            val array = context.obtainStyledAttributes(it, R.styleable.AvatarImageView)
            letter = array.getString(R.styleable.AvatarImageView_signature)?.trim()?.substring(0..0)?.toUpperCase(Locale.ROOT) ?: ""
            avatarBackgroundColor = array.getColor(R.styleable.AvatarImageView_background_color, Color.BLUE)
            avatarLetterColor = array.getColor(R.styleable.AvatarImageView_letter_color, Color.WHITE)
            array.recycle()
        }
        init()
    }

    private fun init(){
        paintBackground.style = Paint.Style.FILL
        paintBackground.color = avatarBackgroundColor

        paintLetter.color = avatarLetterColor
        paintLetter.textAlign = Paint.Align.CENTER
        paintLetter.isAntiAlias = true
        paintLetter.style = Paint.Style.FILL

        drawable?.let{
            paintAvatarImage.isAntiAlias = true
            val shader = BitmapShader(getBitmapFromDrawable(it), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
            paintAvatarImage.shader = shader
        }
    }

    private fun getBitmapFromDrawable(drawable: Drawable): Bitmap{
        if (drawable is BitmapDrawable) {
            drawable.bitmap?.let {
                return drawable.bitmap
            }
        }

        val bitmap: Bitmap = Bitmap.createBitmap(
            drawable.intrinsicWidth,
            drawable.intrinsicHeight,
            Bitmap.Config.ARGB_8888
        )
        return bitmap
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)

        val availableWidth = width
        val availableHeight = height

        circleX = availableWidth / 2f
        circleY = availableHeight / 2f
        circleRadius = min(availableWidth, availableHeight) / 2f

        paintLetter.textSize = availableHeight / 2f
        letterX = availableWidth / 2f
        letterY = availableHeight / 2f - ((paintLetter.descent() + paintLetter.ascent()) / 2f)

        avatarImageRect.right = width.toFloat()
        avatarImageRect.bottom = height.toFloat()
    }

    override fun onDraw(canvas: Canvas?) {
        drawable?.let{
            canvas?.drawRoundRect(avatarImageRect, width.toFloat(), height.toFloat(), paintAvatarImage)
        } ?:run {
            canvas?.drawCircle(circleX, circleY, circleRadius, paintBackground)
            canvas?.drawText(letter, letterX, letterY, paintLetter)
        }
    }
}

我的xml文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:padding="16dp"
    tools:context=".ui.AvatarsFragment">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <com.test.test.views.AvatarImageView
            android:layout_width="32dp"
            android:layout_height="32dp"
            android:src="@drawable/avatar"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginStart="10dp"
            style="@style/TextAppearance.AppCompat.Medium"
            android:text="Ivan Ivanov"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="10dp">

        <com.test.test.views.AvatarImageView
            android:layout_width="32dp"
            android:layout_height="32dp"
            app:signature="Ivan Ivanov"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginStart="10dp"
            style="@style/TextAppearance.AppCompat.Medium"
            android:text="Ivan Ivanov"/>

    </LinearLayout>

</LinearLayout>

更新:我了解其他库,但是我想在没有它们的情况下进行。

android kotlin imageview android-custom-view
2个回答
0
投票

我使用CircleImageView显示图像,并使用毕加索将图像加载到CircleImageView中毕加索居中并裁剪图像它对我有用...


0
投票

android:scaleType是您需要的。您也可以通过编程设置它。

© www.soinside.com 2019 - 2024. All rights reserved.