Update – August 2016
I first wrote this post shortly after textinputlayout was introduced and there was a distinct lack of documentation. My original code example for setting the error was incorrect. Per Victor Tsaran:
There is no such attribute as android:setError. There is a method called setError in the View class that can set the error message dynamically. That method actually works with TalkBack.
I will be updating the code examples soon. For now, do not include the android:seterror line shown below. I’m leaving it right now for archival purposes.
Google has done an admirable job defining the Material Design style guide. They’ve also begun rolling out new APIs that make it much easier to implement the interaction designs within Android and HTML. However, there are still some gaps. This article looks at the popular Text Input for Android interaction. Please note: the code in this article is not fully documented and the best practice may change as the Google Accessibility team updates their documentation. Consider this a beta pattern and I will gladly update it as we learn better practices.
Breakdown of Design
The basic code uses a new parent container <TextInputLayout> which contains the <EditText>. The
EditText includes an
android:hint for the visual label and
android:setError for the subsequent error message. (note: android:hint is not the same as iOS accessibilityHint)
<textinputlayout> <edittext android:id="@id/signupemail" android:hint="Email" android:seterror="Create a valid email address" …/> </textinputlayout>
Making it Accessible
My current testing shows the hint is announced by TalkBack when the user first enters the input. However, the hint is ignored when the input contains a value. Also, the error message is not being announced by TalkBack when it appears. In the above image, TalkBack would announce “edit text 100 days of ice cream“. We need to assign a label to the input that will be announced along with the value.
To understand this suggested solution, I like to think about a much simpler coding pattern: the label/input relationship in HTML. It’s possible to wrap an input with a label.
<label> Name <input type="text"> </label>
Now, we could also add a placeholder to the input (
android:hint) and apply a hidden label to the input by using aria-label on the label tag.
I’m not suggesting this as a best practice, but it’s possible and easy to see the relationship. The label’s now using an attribute to provide the text node to the input. The input has a
placeholder attribute that provides a visual label, but is lost when the user adds value to the input.
<label aria-label="Name"> <input type="text" placeholder="John Doe"> </label>
Going back to the Android pattern, we can define the
TextInputLayout as the label for the
EditText by using android:labelFor and provide a
contentDescription. This is essentially defining a solid label for the input that will remain after the user adds a value to the input. The
contentDescription has no visual impact, so the
android:hint will continue to be your visual label.
<textinputlayout android:labelfor="@id/signupemail" android:contentdescription="Email" android:accessibilityliveregion="polite"> <edittext android:id="@id/signupemail" android:hint="Email" android:seterror="Create a valid email address" …/> </textinputlayout>
We also need to trigger TalkBack to announce the error message when it appears. Fortunately, Android has adopted the ARIA live region pattern. We can place
android:accessibilityLiveRegion="polite" on the TextInputLayout to trigger the announcement. Please note: I haven’t been able to trigger this to work yet. It may be that the live region belongs on the input or this could be a TalkBack bug.
The pattern for creating an accessible text input is fairly simple. I like how they’ve removed the label functionality from android:hint and treat it as just a placeholder value. The
labelFor attribute is much stronger. The Google Accessibility team is working on improved documentation and I hope this post helps to understand the issue, but I point back to the Android documentation as the final resource. I’m not an Android developer, but I know enough to be dangerous.
Please leave your comments with suggestions for improvements.
There is a serious bug with wrapping an editText within a textInputLayout with Lollipop and KitKat. The android:hint is not appearing on load and the hints appear as a user places focus in one of the inputs. This is not necessarily affecting TalkBack accessibility, but certainly affects the visual experience.