Reputation: 2940
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.
Upvotes: 5
Views: 6529
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 TextView
s – 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:
The main caveat with this approach is that all of TextInputLayout
's internal TextView
s will have these base attribute values. Currently, aside from the error, those comprise the helper, the counter, the prefix, and the suffix.
ellipsize
would only have effect if the counter were to grow wider than the EditText
.If any of that is undesired, then kjurkovic's findViewById()
demonstration should work with all of those TextView
s,3 though you must ensure to set the corresponding text first, as the TextView
s 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 TextView
s, 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
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