CodeFlys
12/20/2019 - 12:15 PM

CircleAvatarView

class CircleAvatarView @JvmOverloads constructor(
    context: Context, @Nullable attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
    defStyleRes: Int = 0
) : View(context, attrs, defStyleAttr, defStyleRes) {
    private val paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val bitmapTargetWidth: Float = dp2px(300F)
    private val offset: Float = dp2px(50F)
    private lateinit var bitmap: Bitmap
    private val bounds: RectF = RectF()

    init {
        bitmap = getTargetWidthBitmap(bitmapTargetWidth.toInt())
        bounds.set(offset, offset, offset + bitmapTargetWidth, offset + bitmapTargetWidth)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        val radius = bitmapTargetWidth / 2
        canvas.drawCircle(offset + radius, offset + radius, radius + dp2px(3F), paint)
        val saveCount: Int = canvas.saveLayer(bounds, paint)
        canvas.drawCircle(offset + radius, offset + radius, radius, paint)
        paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
        canvas.drawBitmap(bitmap, offset, offset, paint)
        paint.xfermode = null
        canvas.restoreToCount(saveCount)
    }

    private fun getTargetWidthBitmap(targetWidth: Int): Bitmap {
        val options: BitmapFactory.Options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        BitmapFactory.decodeResource(resources, R.drawable.wechat, options)
        options.inJustDecodeBounds = false
        options.inDensity = options.outWidth
        options.inTargetDensity = targetWidth
        return BitmapFactory.decodeResource(resources, R.drawable.wechat, options)
    }

    private fun dp2px(dp: Float) = TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        dp,
        Resources.getSystem().displayMetrics
    )
}