0

I've created custom View which extends ConstraintLayout. I want to implement onMeasure() because I've notices issues with size customization on different components with different sizes and/or paddings/margins.

This is my View's layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:background="@android:color/transparent">

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/imageview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/transparent"
        android:button="@drawable/drawable_state"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
    <com.airbnb.lottie.LottieAnimationView
        android:id="@+id/animation"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:lottie_rawRes="@raw/animation_json"
        app:lottie_speed="2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:lottie_autoPlay="false"
        app:lottie_loop="false"/>

</androidx.constraintlayout.widget.ConstraintLayout>

I've came up with something like this:

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        val widthSize = MeasureSpec.getSize(widthMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)
        val heightSize = MeasureSpec.getSize(heightMeasureSpec)

        val width = when(widthMode) {
            MeasureSpec.EXACTLY -> widthSize
            MeasureSpec.AT_MOST -> min(STANDARD_WIDTH, widthSize)
            else -> STANDARD_WIDTH
        }

        val height = when(heightMode) {
            MeasureSpec.EXACTLY -> heightSize
            MeasureSpec.AT_MOST -> min(STANDARD_HEIGHT, heightSize)
            else -> STANDARD_HEIGHT
        }

        setMeasuredDimension(width, height);
    }

But it turns out since it is container with children I have to take care of it too. So I've searched for this here And found implementation which includes child Views:

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        val widthSize = MeasureSpec.makeMeasureSpec(widthMeasureSpec, MeasureSpec.EXACTLY)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)
        val heightSize = MeasureSpec.makeMeasureSpec(heightMeasureSpec, MeasureSpec.EXACTLY)

        for (index in 0 until childCount) {
            val child: View = getChildAt(index)
            child.measure(widthSize, heightSize)
        }

        val width = when (widthMode) {
            MeasureSpec.EXACTLY -> widthSize
            MeasureSpec.AT_MOST -> min(STANDARD_WIDTH, widthSize)
            else -> STANDARD_WIDTH
        }

        val height = when (heightMode) {
            MeasureSpec.EXACTLY -> heightSize
            MeasureSpec.AT_MOST -> min(STANDARD_HEIGHT, heightSize)
            else -> STANDARD_HEIGHT
        }

        setMeasuredDimension(width, height)
    }

It seems like this does nothing and still my Views are not visible so probably size is still 0 for them. I can't say I understand this and I don't feel good with layouts. onMeasure() is kinda new for me and I've never had to implement it.
I would be really grateful if someone could tell me what I am doing wrong.

SkypeDogg
  • 1,000
  • 2
  • 13
  • 28
  • ContraintLayouts [`onMeasure`](https://github.com/androidx/constraintlayout/blob/main/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayout.java#L1638) is more complex and calls through to other methods which resolve constraints to measure self and children. You cannot completely override it and expect layout to work properly. For a simple layout like yours (all children centered and have no relation between each other) you could try extending `FrameLayout` which is more basic view group and maybe won't break. – Pawel Jan 27 '21 at 22:03
  • What should I change then in onMeasure() if I want to make it inside FrameLayout. I am really confused about that method. Can I skip measuring children in that case? – SkypeDogg Jan 28 '21 at 08:20

0 Answers0