Accessibility (Java)
Accessibility means making sure people who use screen readers, switch devices, or have low vision can actually use your app — not as an optional extra, but as a real requirement for reaching the full range of your users. This lesson covers the handful of practical, cheap fixes that make the biggest difference for a Java Android app: content descriptions, touch target sizing, contrast, and testing tools.
1. contentDescription for Screen Readers
TalkBack, Android's built-in screen reader, reads a View's content aloud so a user who cannot see the screen still knows what's there. A plain ImageView or ImageButton, however, has no text of its own — without a description, TalkBack has nothing meaningful to say about it. android:contentDescription (introduced alongside ImageView and ImageButton in ImageView & ImageButton) fills that gap.
<!-- Missing description: TalkBack says nothing useful -->
<ImageButton
android:id="@+id/btnFavorite"
android:src="@drawable/ic_favorite_heart"
android:layout_width="48dp"
android:layout_height="48dp" />
<!-- With a description: TalkBack reads it aloud -->
<ImageButton
android:id="@+id/btnFavorite"
android:src="@drawable/ic_favorite_heart"
android:contentDescription="@string/add_to_favorites"
android:layout_width="48dp"
android:layout_height="48dp" />
Since RecipeBox's favorite icon changes meaning depending on state, the description should update in Java to match:
// RecipeDetailActivity.java
ImageButton btnFavorite = findViewById(R.id.btnFavorite);
void updateFavoriteIcon(boolean isFavorite) {
btnFavorite.setImageResource(isFavorite
? R.drawable.ic_favorite_filled
: R.drawable.ic_favorite_heart);
btnFavorite.setContentDescription(getString(isFavorite
? R.string.remove_from_favorites
: R.string.add_to_favorites));
}
- A static XML description is enough for icons that never change meaning; a stateful icon like RecipeBox's favorite heart needs its description updated in Java alongside the image itself.
- Purely decorative images that convey no information (a background pattern, for instance) should set android:contentDescription="@null" so TalkBack skips them instead of reading something meaningless.
2. Touch Target Size
Android's accessibility guidelines recommend every tappable element be at least 48dp by 48dp — the same dp unit covered in depth in Dimensions & Density. Below that size, a target becomes genuinely hard to hit accurately, and the effect compounds for users with limited fine motor control, a shaking hand, or simply a large fingertip. This isn't a cosmetic guideline — it measurably affects whether people can complete an action at all.
<!-- Too small: visually fine, but hard to tap reliably -->
<ImageButton
android:id="@+id/btnFavorite"
android:contentDescription="@string/add_to_favorites"
android:layout_width="24dp"
android:layout_height="24dp" />
<!-- Better: 48dp touch target, icon itself can stay smaller with padding -->
<ImageButton
android:id="@+id/btnFavorite"
android:contentDescription="@string/add_to_favorites"
android:padding="12dp"
android:layout_width="48dp"
android:layout_height="48dp" />
3. Color Contrast
Text needs enough contrast against its background to be readable, especially for users with low vision or color blindness. This connects directly back to Colors & Typography: when choosing text and background color pairs — including the light and dark variants from Light/Dark Theme — favor combinations with a clear brightness difference (dark text on a light background, or light text on a dark background) rather than similarly-toned colors that look fine to designers with good vision but wash out for others.
4. Testing with TalkBack and Accessibility Scanner
The most reliable way to know whether an app is actually accessible is to test it the way an affected user would. Turning on TalkBack in device Accessibility settings and navigating RecipeBox by swipe gestures alone quickly reveals which buttons have no description, or which screens are confusing without sight.
Accessibility Scanner is a free tool (available from the Play Store, or built into some Android Studio tooling) that automatically scans a running screen and flags concrete issues — missing content descriptions, touch targets under 48dp, and low contrast text — with specific, actionable suggestions. It won't catch everything a human tester would, but it's a genuinely fast way to find the most common mistakes before they reach real users.
5. Focus Order for Keyboard / Switch Access
Some users navigate entirely without touch, using a hardware keyboard, a D-pad, or switch-access hardware that steps focus between elements. By default, Android guesses a reasonable focus order based on layout position, but a custom layout can override it explicitly with attributes like android:nextFocusDown, android:nextFocusUp, android:nextFocusLeft, and android:nextFocusRight when the automatic order doesn't match the visual/logical flow.
<!-- Forcing focus to move from the title field down to ingredients -->
<EditText
android:id="@+id/etRecipeTitle"
android:nextFocusDown="@id/etIngredients"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Accessibility Checklist
| Concern | Fix | Cost to implement |
|---|---|---|
| Screen reader can't describe an icon | android:contentDescription | Very low |
| Small tap targets | Minimum 48dp width/height, add padding around a small icon | Low |
| Low contrast text | Choose color pairs with clear brightness difference | Low |
| Confusing keyboard/switch navigation | nextFocusDown and related attributes | Low, only where needed |