Search code examples
androidandroid-canvasandroid-custom-viewdrawtextstaticlayout

StaticLayout positioning center of canvas not working like canvas.drawText?


While drawing with usual drawText the text is positioning to the center of canvas. But my requirment is to place multiline text, so I've to use StaticLayout, but StaticLayout is not getting placed like drawText Here's what I've tried so far.

class TestView : View {

private lateinit var staticLayout: StaticLayout
private lateinit var ststicTextPaint: TextPaint
private lateinit var textPaint: TextPaint
private val helloworld = "Hello world!"

constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
  
}

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

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(
    context,
    attrs,
    defStyleAttr,
    defStyleRes
) {
}

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

private fun setUp(w: Int, h: Int) {
    textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)
    textPaint.color = Color.BLUE
    textPaint.textSize = 40f
    textPaint.textAlign = Paint.Align.CENTER

    ststicTextPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)
    ststicTextPaint.color = Color.GREEN
    ststicTextPaint.textSize = 40f
  //  textPaint.textAlign = Paint.Align.CENTER

    staticLayout = StaticLayout(
        helloworld,
        ststicTextPaint,
        w,
        Layout.Alignment.ALIGN_CENTER,
        0f,
        0f,
        false
    )
}

override fun onDraw(canvas: Canvas?) {
    super.onDraw(canvas)
    //Just drawn a rect with cross-hair to know the relative position
    val rect = Rect(0, 0, width, height)
    val paint = Paint(Paint.ANTI_ALIAS_FLAG)
    paint.style = Paint.Style.STROKE
    paint.color = Color.RED
    paint.strokeWidth = 5f
    canvas?.drawRect(rect, paint)
    canvas?.drawLine((width/2).toFloat(), 0F, (width/2).toFloat(), height.toFloat(),paint)
    canvas?.drawLine(0F, (height/2).toFloat(),width.toFloat(), (height/2).toFloat(),paint)

    canvas?.drawText(helloworld, (width / 2).toFloat(), (height / 2).toFloat(), textPaint)
    //   canvas?.drawText(helloworld, (width / 2).toFloat(), (height / 2).toFloat(), textPaint)
    staticLayout.draw(canvas, (width / 2).toFloat(), (height / 2).toFloat())
}

fun StaticLayout.draw(canvas: Canvas?, x: Float, y: Float) {
    canvas?.withTranslation(x, y) {
        draw(canvas)
    }
  }
}

Here's what I'm getting with both enter image description here The blue one is done using normal drawText and the Green one is using StaticLayout


Solution

  • I figured out the issue guys. It was because i was ignoring the width of the StaticLayout text's width while placing it to the centre.

    Here I'm giving the StaticLayout the entire width of the View.

        staticLayout = StaticLayout(
            "Hello world is helloworld",
            ststicTextPaint,
            w,
            Layout.Alignment.ALIGN_CENTER,
            1f,
            0f,
            false
        )
    

    While drawing the view

    staticLayout.draw(canvas, ((width / 2)-staticLayout.width/2).toFloat(), (height / 2).toFloat())
    

    I substracted the half of the width of the `StaticLayout width so that it'll place in the exact centre. enter image description here