Search code examples
androidandroid-textinputlayoutmaterial-componentsmaterial-components-androidandroid-textinputedittext

Get height of outline box in TextInputLayout


What I want :

I am building a component that looks like the following, where the height of the + & - buttons need to match the height of the outline of the TextInputLayout.

enter image description here

What I tried :

There seems to be no public api that lets me get the height of the outline. However, within the TextInputLayout there is private MaterialShapeDrawable boxBackground; but it is private.

How can I make my buttons match the height of the outline ?


Solution

  • I would suggest you start from the google material guidelines to find what the default size supposed to be.

    The following won't get the height of the outline, but it will align it anyways as I used something similar a while ago.

    In your component, you can add a GlobalLayoutListener to the viewTreeObserver in the init or wherever you are initialization your component, so you can get the correct size of your TextInputLayout otherwise you will get always 0. Inside the OnGlobalLayout() method you will have to make some calculations.

    1. You have to find out the size of the EditText inside the TextInputLayout.
    2. With the size of the EditText, you have to increase the Height/Width of your button
    3. By using the docs I’m assuming the Error/HelperText when visible will always increase the size of the widget by 16.
    4. So get the measured size of the textInputLayout and subtract the size of the EditText. That should be your button new top padding, but because when Error/HelperText is visible it will alter the size of the widget and misalign your layout, so you can check if the TextInputLayout helperText/error is null or empty and using the assumption above you can subtract 16dp when those views are visible and it pushes the view down correctly aligning with the EditText and not with the Hint.

    eg.

    Init or wherever you initialize it

    init {
    
        viewTreeObserver.addOnGlobalLayoutListener(object :
            ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                textInputLayout.editText?.measuredHeight?.let {           
                    val topMargin = 16.dpToPx() //Mentioned in the step #3
                    val value = if (!textInputLayout.helperText.isNullOrEmpty()) {
                        (textInputLayout.measuredHeight - topMargin) - it
                    } else {
                        textInputLayout.measuredHeight - it
                    }
    
                    increaseButtonSize(it, value)
    
                }
                viewTreeObserver.removeOnGlobalLayoutListener(this)
            }
        })
    
    }
    

    Increase size of buttons

    fun increaseButtonSize(size: Int, padding: Int) {
    
        val lessButtonParams: LayoutParams = lessButton.layoutParams as LayoutParams
        lessButtonParams.setMargins(lessButtonParams.leftMargin, padding, lessButtonParams.rightMargin, lessButtonParams.bottomMargin)
        lessButtonParams.height = size
    
        lessButton.layoutParams = lessButtonParams
    
        val moreButtonParams: LayoutParams = moreButton.layoutParams as LayoutParams
        params.setMargins(moreButtonParams.leftMargin, padding, moreButtonParams.rightMargin, moreButtonParams.bottomMargin)
        params.height = size
    
        moreButton.layoutParams = params
    
    }