Как сделать круговое изображение в пользовательском представлении изображения с центральным кадрированием? - PullRequest
0 голосов
/ 13 октября 2019

Я хочу создать пользовательский вид изображения для аватаров, который может работать в двух режимах:

  1. Если android: src - пустой круг отображения с первой буквой имени
  2. Другой круг отображенияavatar

В настоящее время, если я использую android: src, мой нарисованный объект не в центре, как я могу сделать его центральным кадром?

Пример

Вот код пользовательского представления:

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>

ОБНОВЛЕНО: я знаю о других библиотеках, но я хочу сделать это без них.

Ответы [ 2 ]

0 голосов
/ 14 октября 2019

решено: теперь я использую этот код для обрезки моего изображения из https://stackoverflow.com/a/12089127/12209565:

private fun getCircleBitmap(bitmap: Bitmap): Bitmap {
        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)

        paint.isAntiAlias = true
        canvas.drawARGB(0, 0, 0, 0)
        paint.color = color

        canvas.drawCircle(
            bitmap.width / 2f, bitmap.height / 2f,
            bitmap.width / 2f, paint
        )
        paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
        canvas.drawBitmap(bitmap, rect, rect, paint)

        return output
    }
0 голосов
/ 13 октября 2019

Я использовал CircleImageView для отображения изображений и Picasso для загрузки изображений в центры CircleImageView Picasso и обрезал изображение, которое мне помогло ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...