0

I have a layout which contains 4 TextInputEditText views:

  • А. TextInputEditText defined with parametes in XML inside TextInputLayout
  • B. TextInputEditText defined with parametes in XML without TextInputLayout
  • C. TextInputEditText created w constructor and added to TextInputLayout
  • D. TextInputEditText created w constructor without TextInputLayout

A:

<com.google.android.material.textfield.TextInputLayout
        android:id="@+id/til_from_xml_2_elements2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginHorizontal="16dp"
        android:hint="w input from_xml_2_elements"
        app:endIconMode="clear_text"
        android:descendantFocusability="beforeDescendants"
        android:focusableInTouchMode="true">

        <com.google.android.material.textfield.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/et_from_xml_2_elements2"
            android:text = "text"
            android:maxLines="1"
            android:inputType="textCapSentences"
            android:imeOptions="actionDone"
            tools:ignore="TextContrastCheck">
        </com.google.android.material.textfield.TextInputEditText>
    </com.google.android.material.textfield.TextInputLayout>

B:

<com.google.android.material.textfield.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/et_from_xml2"
        android:layout_marginTop="16dp"
        android:layout_marginHorizontal="16dp"
        android:text = "w input edit text from xml"
        android:maxLines="1"
        android:inputType="textCapSentences"
        android:imeOptions="actionDone"
        tools:ignore="TextContrastCheck">
    </com.google.android.material.textfield.TextInputEditText>

C:

<com.google.android.material.textfield.TextInputLayout
        android:id="@+id/til_only_group_w_input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginHorizontal="16dp"
        android:hint="w input only til"
        app:endIconMode="clear_text"
        android:descendantFocusability="beforeDescendants"
        android:focusableInTouchMode="true">
    </com.google.android.material.textfield.TextInputLayout>

code for C and D:

private fun getEditText(): View {
        return TextInputEditText(
            this,
            null,
            androidx.appcompat.R.attr.editTextStyle
        ).apply {
            val layoutParams = LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.WRAP_CONTENT
            )

            val margin16dp = this@MainActivity.dipToPixels(16f).toInt()

            layoutParams.setMargins(
                margin16dp,
                margin16dp,
                margin16dp,
                0
            )

            this@apply.layoutParams = layoutParams
            this@apply.maxLines = 1
            this@apply.imeOptions = EditorInfo.IME_ACTION_DONE
            this@apply.inputType = android.text.InputType.TYPE_CLASS_TEXT or
                        android.text.InputType.TYPE_TEXT_VARIATION_NORMAL

            this.setText("from constructor")
        }
    }

test project: https://github.com/MirnykhK/NestedVewsAttributeSet

At the first sight the parameters for all TextInputEditTexts are defined differently but they should be similar. However these TextInputEditText fields have different presentation and I have no idea why.

enter image description here

Presentation for B and D is similar - as expected. However it differs for A, B, C. I've focused on TextInputEditText - paddingLeft parameter at first to find a reason. Log prints this:

  1. et_from_xml_2_elements 44
  2. et_from_xml 11
  3. et from constructor inside TIL 11
  4. et from constructor w input 11

PaddingLeft value for TextInputEditText defined with parametes in XML inside TextInputLayout is much more. So I've started to find where this parameter is obtained. View attributes can be setted up in XML layout directly as value, in XML layout as style, as default theme attribute and as default style in constructor.

There are no paddings in layout, no paddings in styles, no paddings in default theme attribute (TextInputLayout - R.attr.editTextStyle) and its ancesstors. Default style is not used in constructor in this case. In the next step I've travelled through TextInputEditText constructors call stack to find where paddingLeft is assigned w this strange value = 44. It happens on View constructor call - View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes). Attribute value (44) is obtained in line:

final TypedArray a = context.obtainStyledAttributes(
                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);

I can't go deeper w debugger to see what happens in context.obtainStyledAttributes() as it has JNI call. So how it's possible that view attributes depend on view nesting level? Is it possible to debug JNI calls?

Botje
  • 26,269
  • 3
  • 31
  • 41
Kubick
  • 61
  • 3
  • 1
    Those values are coming ultimately from the `TextInputLayout`'s style setup, which specifies a `materialThemeOverlay` that sets an `editTextStyle` for its children, and that's where that extra padding comes from (though the specific values logged don't seem quite right). You clearly have a good handle on this stuff so I won't go through each step, but if you look at `TextInputLayout`'s styles, [you can see how the overlay is set initially](https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/textfield/res/values/styles.xml#L20)... – Mike M. Jun 12 '22 at 13:40
  • 1
    ...and overridden for various styles. If you follow through any of those (for an `EditText` setup), you end up at [this style](https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/textfield/res/values/styles.xml#L168), where you can see the values for the horizontal padding. Make sense? – Mike M. Jun 12 '22 at 13:40
  • After thinking about this again, those values you logged for the paddings do make sense – for a density of 2.75 – so please just ignore that parenthetical in my comment above. – Mike M. Jun 12 '22 at 17:39
  • Much appreciated! Your comments are the answer. Theme overlay is a new word for me. So I have to use theme overlay like current style of TextInputLayout use to get result similar to A. case. Thus constructor call must be like: TextInputEditText(ContextThemeWrapper(this, R.style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox_Dense), null, R.attr.editTextStyle ) Indeed, now presentation of EditText in case C. is similar to case A. And i'm currious if I can wrap this overlay to get another one with nested overlay to get overriden attributes?.. – Kubick Jun 12 '22 at 17:53
  • Yep, you can; that's kinda what's happening internally already. Also, the `TextInputLayout`'s `Context` (which is actually a `ContextThemeWrapper` itself) already has that stuff set on its theme, so you could simply do `TextInputEditText(binding.tilOnlyGroupWInput.context)` for the same effect, though you'd have to juggle your setup a little bit. That's what's happening automatically during inflation, btw; the `TextInputEditText` is being instantiated by `LayoutInflater` with its parent `ViewGroup`'s `Context`. – Mike M. Jun 12 '22 at 18:04

0 Answers0