Accessible Android Inputs with Material Design

Material Design for an input

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.
Victor Tsaran

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

Material Design specification for an input
The text input includes a label that moves up above the input when the user places focus in the input. If the user enters invalid data, the error message appears at the bottom of the input.

Basic Code

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.

Conclusion

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.

Updates

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.

2 thoughts on “Accessible Android Inputs with Material Design”

  1. Any further updates on this? Trying to design an accessible simple log-in form without visible labels using, and can’t have the hint hidden from visual users.

  2. Good question. I haven’t tested lately. I pinged my friend at Google to see if there has been an update on the error message announcing via TalkBack. Also, the bug mentioned in the Update section is still open.

Leave a Reply

Your email address will not be published. Required fields are marked *