andrei
andrei

Reputation: 2940

TextInputLayout error message size

Is there a way to force the TextInputLayout error message to take a single line ?

I tried to place app:errorTextAppearance="@style/error_appearance" on the TextInputLayout with the error_appearance style containing :

<item name="android:maxLines">1</item>
<item name="android:ellipsize">end</item>
<item name="android:inputType">text</item>

and it does not work. Changing the color works however. I don't get it, the mErrorView is just a TextView, it should work.

TextInputLayout error message

Upvotes: 5

Views: 6529

Answers (2)

Mike M.
Mike M.

Reputation: 39191

It's true the the error is a TextView, but a TextAppearance style affects only text, not the View that the text is in. The maxLines and ellipsize attributes belong to TextView, so they will be ignored in a TextAppearance style, which expects attributes like textColor, textSize, typeface, etc.1

Knowing this, we just need to find a way to set those attributes' values on the error TextView. kjurkovic's answer on this very question shows how to do that in code, for the current versions of TextInputLayout.2 It turns out that there's also a way we can do this in the layout XML, which might be preferable for some.

That error TextView is instantiated with the TextInputLayout's Context, which we can actually modify in the layout XML, to some extent, with the android:theme attribute. Using an overlay with this attribute, we can cause that Context's theme to have an android:textViewStyle – essentially, the basic settings for TextViews – that contains our desired attribute values.

In your theme/style resource XML:

<style name="ThemeOverlay.TextInputLayout.TextView" parent="">
    <item name="android:textViewStyle">@style/Widget.TextView.SingleLineEllipsized</item>
</style>

<style name="Widget.TextView.SingleLineEllipsized" parent="">
    <item name="android:maxLines">1</item>
    <item name="android:ellipsize">end</item>
</style>

On the <TextInputLayout> in the layout XML, simply add the android:theme attribute:

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/text_input_layout_phone"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Phone number"
    android:theme="@style/ThemeOverlay.TextInputLayout.TextView">

    <com.google.android.material.textfield.TextInputEditText
        android:id="@+id/edit_text_phone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</com.google.android.material.textfield.TextInputLayout>

Though the current TextInputLayout has different design details than the original, we can see that the maxLines and ellipsize settings have worked:

enter image description here


The main caveat with this approach is that all of TextInputLayout's internal TextViews will have these base attribute values. Currently, aside from the error, those comprise the helper, the counter, the prefix, and the suffix.

  • The helper occupies the same spot as the error, so if you want single-line-and-ellipsized on one, you very likely want it on the other as well, if you're even using it.
  • The counter is already being set up as single-line, and the extraneous ellipsize would only have effect if the counter were to grow wider than the EditText.
  • The prefix and the suffix, by their nature, are meant to be single-line anyway.

If any of that is undesired, then kjurkovic's findViewById() demonstration should work with all of those TextViews,3 though you must ensure to set the corresponding text first, as the TextViews are instantiated on demand.


1 You can find the full list of valid TextAppearance attributes in the platform's res/values/attrs.xml resource file. I don't believe there is any documentation or developer page that covers it; at least, there didn't used to be.

2 The very first versions of TextInputLayout did not assign IDs to the inner TextViews, so getting direct reference to the error TextView required reflection, or awkwardly searching the internal hierarchy. I've not tested the theme overlay solution on those ancient versions, but if for whatever reason you're stuck with one and this doesn't work, previous revisions of this answer have those other options for you.

3 Incidentally, the IDs for all of those are as follows: R.id.textinput_error, R.id.textinput_helper_text, R.id.textinput_counter, R.id.textinput_prefix_text, and R.id.textinput_suffix_text.

Upvotes: 7

kjurkovic
kjurkovic

Reputation: 4104

you can fetch error TextView by id

TextView errorView = textInputLayout.findViewById(R.id.textinput_error);
errorView.setMaxLines(1);
errorView.setSingleLine(true);

Upvotes: 9

Related Questions