Home > Software engineering >  How to scale a drawable to center crop in a custom view programmatically
How to scale a drawable to center crop in a custom view programmatically

Time:04-10

I have a custom view that I am using as an imageview. Its parent is a constraint layout but I have to extend that layout(parent) to get some other implementation.

I want to Center-crop the drawable in the custom view just like in the normal ImageView

I have only been able to achieve the fitXY, how can I make the drawable Center-Crop in the custom view?

class CustomImageView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : CustomShimmerView(context, attrs, defStyleAttr) {
    

    var mDrawable:Drawable?=null


    @RequiresApi(Build.VERSION_CODES.O)
    override fun dispatchDraw(canvas: Canvas?) {
        if (isLoading && mDrawable == null) {
            background = ContextCompat.getDrawable(context, android.R.color.black)
            super.dispatchDraw(canvas)
        }

    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        mDrawable?.setBounds(0, 0, width, height)
    }
    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        if (mDrawable == null) return

        if (mDrawable!!.intrinsicWidth == 0 || mDrawable!!.intrinsicHeight == 0) return

        if (canvas != null) {
            canvas.save()
            canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
            mDrawable!!.draw(canvas)
            background = null
            canvas.restore()
        }
    }
    fun setImage(bitmap: Bitmap){
        mDrawable = BitmapDrawable(resources, bitmap)
        invalidate()
    }
    
    


}

CodePudding user response:

Translate the canvas before you draw the drawable

override fun onDraw(canvas: Canvas?) {
    ...
        if (canvas != null) {
            canvas.save()
            ...
            canvas.translate(-mDrawable.width/4f,-mDrawable.height/4f)
            mDrawable!!.draw(canvas)
            ...
            canvas.restore()
        }
    }

CodePudding user response:

I was able to achieve the center crop method with the code below. Though, I tried to use matrix as seen on the imageview source code it did not work but the one below works well as center crop.

class CustomImageView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : CustomShimmerView(context, attrs, defStyleAttr) {
   
    var mDrawable:Drawable?=null


    @RequiresApi(Build.VERSION_CODES.O)
    override fun dispatchDraw(canvas: Canvas?) {
        if (isLoading && mDrawable == null) {
            background = ContextCompat.getDrawable(context, android.R.color.black)
            super.dispatchDraw(canvas)
        }

    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        if (mDrawable?.intrinsicWidth == 0 || mDrawable?.intrinsicHeight == 0) return
        mDrawable?.setBounds(0, 0, mDrawable!!.intrinsicWidth, mDrawable!!.intrinsicHeight )
    }
    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        if (mDrawable == null) return

        if (mDrawable!!.intrinsicWidth == 0 || mDrawable!!.intrinsicHeight == 0) return

        val dWidth = mDrawable!!.intrinsicWidth
        val dHeight = mDrawable!!.intrinsicHeight
        val scale:Float = if (dWidth * height > width * dHeight){
            (height.toFloat()/dHeight)
        } else{
            (width.toFloat()/dWidth)
        }

        val dx = (width-dWidth * scale) * 0.5f

        if (canvas != null) {
            canvas.save()
            canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
            canvas.concat(matrix)
            canvas.translate(dx, 0f)
            canvas.scale(scale, scale)
            mDrawable!!.draw(canvas)
            background = null
            canvas.restore()

            requestLayout()
        }
    }
    fun setImage(bitmap: Bitmap){
        mDrawable = BitmapDrawable(resources, bitmap)
        invalidate()
    }
}

  • Related