mcece
mcece

Reputation: 31

How to add padding in custom switch compat in android?

I am trying to implement a custom switch compat and I am referencing another stackoverflow answer: How to set width and track text in a Switch/SwitchCompat button and achieve this result? (Image and GIF attached)

My code is almost identical to this other than small updates.

class SwitchCompatEx : SwitchCompat {

companion object {

    val TRACK_COLOR = 0xFFFFFFFF.toInt()
    val TRACK_STROKE_WIDTH = 2f.dp2Px.toInt()
    val TRACK_STROKE_COLOR = 0xFF00A1FF.toInt()
    val TRACK_LABEL_COLOR = 0xFF00A1FF.toInt()
    val TRACK_LABEL_SIZE = 14f.sp2Px

    val THUMB_COLOR = 0xFF00A1FF.toInt()
    val THUMB_LABEL_COLOR = 0xFFFFFFFF.toInt()
    val THUMB_LABEL_SIZE = 14f.sp2Px

    fun drawLabel(canvas: Canvas,
                  bounds: Rect,
                  paint: Paint,
                  text: CharSequence?) {
        text ?: return

        val tb = RectF();
        tb.right = paint.measureText(text, 0, text.length)
        tb.bottom = paint.descent() - paint.ascent()
        tb.left += bounds.centerX() - tb.centerX()
        tb.top += bounds.centerY() - tb.centerY() - paint.ascent()

        canvas.drawText(text.toString(), tb.left, tb.top, paint)
    }

    private inline val Float.sp2Px
        get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                this,
                Resources.getSystem().displayMetrics)

    private inline val Float.dp2Px
        get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                this,
                Resources.getSystem().displayMetrics)
}

private val trackLabelPaint = Paint().apply {
    isAntiAlias = true
    textSize = TRACK_LABEL_SIZE
    color = TRACK_LABEL_COLOR
}

private val thumbLabelPaint = Paint().apply {
    isAntiAlias = true
    textSize = THUMB_LABEL_SIZE
    color = THUMB_LABEL_COLOR
}

private val thumbLabel
    get () = if (isChecked) textOn else textOff

constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

init {
    background = null
    trackDrawable = TrackDrawable()
    thumbDrawable = ThumbDrawable()
}

override fun onSizeChanged(w: Int,
                           h: Int,
                           oldw: Int,
                           oldh: Int) {
    super.onSizeChanged(w, h, oldw, oldh)

    (trackDrawable as GradientDrawable).setSize(w, h)
    (thumbDrawable as GradientDrawable).setSize(w / 2, h)
}

inner class TrackDrawable : GradientDrawable() {

    private val textOffBounds = Rect()
    private val textOnBounds = Rect()

    init {
        setColor(TRACK_COLOR)
        setStroke(TRACK_STROKE_WIDTH, TRACK_STROKE_COLOR)
    }

    override fun onBoundsChange(r: Rect) {
        super.onBoundsChange(r)

        cornerRadius = r.height() / 2f

        textOffBounds.set(r)
        textOffBounds.right /= 2

        textOnBounds.set(textOffBounds)
        textOnBounds.offset(textOffBounds.right, 0)
    }

    override fun draw(canvas: Canvas) {
        super.draw(canvas)

        drawLabel(canvas, textOffBounds, trackLabelPaint, textOff)
        drawLabel(canvas, textOnBounds, trackLabelPaint, textOn)
    }
}

inner class ThumbDrawable : GradientDrawable() {

    private val thumbLabelBounds = Rect()

    init {
        setColor(THUMB_COLOR)
    }

    override fun onBoundsChange(r: Rect) {
        super.onBoundsChange(r)

        cornerRadius = r.height() / 2f

        thumbLabelBounds.set(r)
    }

    override fun draw(canvas: Canvas) {
        super.draw(canvas)

        drawLabel(canvas, thumbLabelBounds, thumbLabelPaint, thumbLabel)
    }
}

}

I am trying to put padding between the thumb view and gray borders. How can I achieve that view?

This is what I want to do. enter image description here

This is what I currently have.

enter image description here

Upvotes: 0

Views: 1764

Answers (2)

mcece
mcece

Reputation: 31

I finally achieved the UI by changing

   inner class ThumbDrawable : GradientDrawable() {

    private val thumbLabelBounds = Rect()

    init {
        //Set color for selected items background
        setColor(ContextCompat.getColor(context, R.color.colorPrimary))
    }

    override fun onBoundsChange(r: Rect) {
        super.onBoundsChange(r)

        setupPadding(r)
        cornerRadius = r.height() / 2f
        thumbLabelBounds.set(r)
    }

    fun setupPadding(r: Rect) {
        val padding = 4f.dp2Px.toInt()
        r.top += padding
        r.right -= padding
        r.bottom -= padding
        r.left += padding
    }

    override fun draw(canvas: Canvas) {
        super.draw(canvas)

        drawLabel(canvas, thumbLabelBounds, thumbLabelPaint, thumbLabel)
        invalidate()
        requestLayout()
    }
}

Basically, added coordinates +padding for each side.

Upvotes: 1

Zain
Zain

Reputation: 40878

Try to override onMeasure()method and call setMeasuredDimension() with the measured width, and adding the a new value to the vertical/horizontal padding.

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    val paddingHorizontal = paddingLeft + paddingRight + 100
    val paddingVertical = paddingTop + paddingBottom + 100
    val height = resolveSizeAndState(paddingVertical, heightMeasureSpec, 0)
    val width = resolveSizeAndState(paddingHorizontal, widthMeasureSpec, 0)
    setMeasuredDimension(width, height)
}

Upvotes: 0

Related Questions