Center an element horizontally in a ConstraintLoyout via onLayout

29 views Asked by At

I have a custom view based on ConstraintLayout. This view has dynamic width depending on actual content width. I am doing manual measuring of my custom view via onMeasure. I also have a button which I expect to be centered horizontally. It not actually centering so I try to center programmically in onLayout. It seems layout method does not work as expected:

enter image description here

How to fix this?

This is my Custom view code:

class SgBox(context: Context, attrs: AttributeSet): ConstraintLayout(context, attrs) {

    private val binding: ViewSgBoxBinding
    private val titles: List<TextView>
    private val values: List<TextView>
    private val centerable: List<View>

    init {
        binding = ViewSgBoxBinding.inflate(LayoutInflater.from(context), this)
        titles = listOf(binding.title1, binding.title2)
        values = listOf(binding.value1, binding.value2)
        centerable = listOf(binding.bntMore)
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val desiredWidth = titles.maxWidth+
                values.maxWidth +
                paddingStart+paddingEnd+20
        setMeasuredDimension(desiredWidth, measuredHeight)
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        values.forEach {
            val r = measuredWidth - paddingEnd
            it.layout(r-it.measuredWidth, it.top, r, it.bottom)
        }
        centerable.forEach {
            val s = measuredWidth/2 - it.measuredWidth/2
            it.layout(it.left+s, it.top, it.right+s, it.bottom)
        }
    }

    private val List<View>.maxWidth get() = maxOf { it.measuredWidth }
}

By the way. Notice that "2.1" has different color, while I expect it to be the same color as "P2" or "Param 1" - both TextView just do not have a color specified. Why the color is different?

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <TextView
        android:id="@+id/title1"
        android:text="Param 1:"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <TextView
        android:id="@+id/value1"
        android:text="-464.44"
        android:textColor="@color/black"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBaseline_toBaselineOf="@id/title1"
        app:layout_constraintStart_toStartOf="parent"/>
    <View
        android:id="@+id/divider1"
        android:layout_width="wrap_content"
        android:layout_height="2dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/title1"
        android:background="@color/teal_700"/>

    <TextView
        android:id="@+id/title2"
        android:text="P2:"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/divider1" />
    <TextView
        android:id="@+id/value2"
        android:text="2.1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBaseline_toBaselineOf="@id/title2"
        app:layout_constraintStart_toEndOf="@id/barrier_titles"
        app:layout_constraintEnd_toEndOf="parent"/>
    <View
        android:id="@+id/divider2"
        android:layout_width="wrap_content"
        android:layout_height="2dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/title2"
        android:background="@color/teal_700"/>

    <androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrier_titles"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingHorizontal="2dp"
        app:barrierDirection="end"
        app:constraint_referenced_ids="title1,title2"/>

    <Button
        android:id="@+id/bnt_more"
        android:text="More"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/divider2" />

</merge>
0

There are 0 answers