Androidinput-navigationIntermediate

Device Orientation in Android Development

Learn how to handle device orientation changes gracefully, preserving user input and maintaining accessibility for users who depend on a specific device orientation due to their disability.

🎯 Why It Matters

As users rotate their devices between portrait and landscape modes, your app must adapt gracefully to maintain usability and preserve important information. Poor orientation handling can break layouts, lose user input, and create significant barriers for users who rely on specific device orientations due to their disabilities. Many users with motor impairments mount their devices in fixed positions and depend on apps working correctly in a particular orientation, making seamless orientation handling a critical accessibility requirement.

đź’» Implementation

Correct Code Example: Supporting All Orientations

Demo Description

Rather than locking orientation, support all orientations to ensure accessibility for users who mount their devices in fixed positions or rely on a specific orientation due to a disability:

<!-- AndroidManifest.xml - Support all orientations -->
<activity
    android:name=".MainActivity"
    android:screenOrientation="fullSensor"
    android:configChanges="orientation|screenSize|screenLayout">
</activity>

Code Explanation

This XML sets screenOrientation to "fullSensor" in the AndroidManifest, allowing the activity to respond to all physical orientations. Locking orientation should be avoided as it creates accessibility barriers for users who depend on a specific device orientation. The configChanges attribute ensures orientation and screen size changes are handled gracefully without restarting the activity.

Correct Code Example: Orientation-Specific Layouts

Demo Description

For complex UIs, consider creating separate layouts for portrait and landscape orientations by placing them in their respective resource directories:


res/layout/activity_main.xml          (Portrait)
res/layout-land/activity_main.xml     (Landscape)

<!-- res/layout-land/activity_main.xml -->
<!-- Android - Landscape-specific layout -->
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Rearranged UI elements optimised for landscape -->

</androidx.constraintlayout.widget.ConstraintLayout>

Code Explanation

Android automatically selects the correct layout based on the current orientation. Placing a layout file in the layout-land directory tells Android to use it when the device is in landscape mode, while the layout directory is used for portrait mode. This allows you to optimise the UI for each orientation without complex code.

Correct Code Example: Using ConstraintLayout for Flexible Layouts

Demo Description

Here is an example of using ConstraintLayout for flexible positioning of UI elements:

<!-- Android - Flexible layout using ConstraintLayout -->
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Your UI elements here -->

</androidx.constraintlayout.widget.ConstraintLayout>

Code Explanation

This XML snippet defines a ConstraintLayout that fills the entire screen. ConstraintLayout allows UI elements to be positioned flexibly and responsively, adapting naturally to both portrait and landscape orientations without requiring separate layouts.

Correct Code Example: Handling Configuration Changes

Demo Description

Here is an example of handling orientation changes without restarting the activity:

// Android - Handle orientation changes gracefully
override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        // Handle landscape orientation
        counterTextView.textSize = 30f
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        // Handle portrait orientation
        counterTextView.textSize = 20f
    }
}

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putInt("counter", counter)
}

Code Explanation

This Kotlin code overrides onConfigurationChanged to respond to orientation changes without restarting the activity. Text size is adjusted based on the current orientation. onSaveInstanceState saves the counter value so it is preserved across configuration changes.

Correct Code Example: Preserving State During Orientation Changes

Demo Description

Here is an example of preserving important user data during orientation changes:

// Android - Save and restore user input across orientation changes
override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putString("userInput", userInputEditText.text.toString())
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    savedInstanceState?.let {
        userInputEditText.setText(it.getString("userInput"))
    }
}

Code Explanation

This Kotlin code saves the user's text input in onSaveInstanceState when an orientation change occurs. When the activity is recreated, onCreate checks for a saved state and restores the user's input, ensuring no data is lost during rotation.

Correct Code Example: Using NestedScrollView Responsibly

Demo Description

Rather than relying on two-dimensional scrolling, use NestedScrollView with a single scroll direction to keep content accessible in both orientations:

<!-- Android - Single-direction scrolling with NestedScrollView -->
<androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <!-- Your UI elements here -->

    </LinearLayout>

</androidx.core.widget.NestedScrollView>

Code Explanation

This XML wraps content in a NestedScrollView with vertical scrolling only. Avoiding two-dimensional scrolling is important for accessibility—horizontal and vertical scrolling simultaneously can fail WCAG criteria and create a difficult experience for users with motor impairments or those using assistive technologies. Content should reflow vertically to accommodate different screen sizes and orientations.

âś… Best Practices

Do's

  • âś“Use ConstraintLayout for flexible, responsive layouts
  • âś“Create orientation-specific layouts in layout and layout-land directories
  • âś“Override onConfigurationChanged to handle orientation changes gracefully
  • âś“Use onSaveInstanceState or ViewModel to preserve user data
  • âś“Support all orientations using fullSensor to accommodate users with disabilities
  • âś“Use single-direction NestedScrollView to keep content accessible
  • âś“Test with TalkBack in both portrait and landscape orientations
  • âś“Ensure touch targets remain at least 48x48dp in all orientations

Don'ts

  • âś—Lock screen orientation—this creates barriers for users who depend on a specific orientation
  • âś—Use two-dimensional scrolling—this fails WCAG criteria and hinders assistive technology users
  • âś—Allow user input to be lost during orientation changes
  • âś—Use fixed pixel dimensions that break in different orientations
  • âś—Assume landscape layouts are unnecessary—some users always operate in landscape
  • âś—Forget to test across multiple device sizes and orientations

🔍 Common Pitfalls

Locking Orientation

Restricting an app to one orientation creates serious accessibility barriers for users who mount devices in fixed positions or have motor impairments that require a specific orientation

Two-Dimensional Scrolling

Allowing both horizontal and vertical scrolling simultaneously fails WCAG success criteria and makes content extremely difficult to navigate for users with motor impairments or assistive technology users

Lost User Input

Failing to save state during orientation changes forces users to re-enter data, which is particularly frustrating for users with motor or cognitive impairments

Broken Layouts

Using fixed dimensions instead of flexible layouts causes UI elements to overlap or become unreachable after rotation

Inconsistent Navigation Order

Changing the layout without updating the accessibility traversal order can cause TalkBack to navigate elements in a confusing sequence

Untested Landscape Mode

Many developers only test in portrait mode, leaving landscape layouts broken or inaccessible

TalkBack

Navigates elements in the order they appear in the layout. When orientation changes, the traversal order should remain logical. If using orientation-specific layouts, verify TalkBack reads elements in a sensible sequence in both orientations.

Switch Control

Switch users rely on a consistent and predictable focus order. Orientation changes should not disrupt the navigation sequence or cause focus to be lost.

Dynamic Type

Ensure text scales correctly in both orientations. Landscape mode has less vertical space, so larger text sizes should still be fully readable and not truncated.

Voice Control

Element labels should remain consistent across orientations so voice commands work reliably regardless of how the device is held.

đź§Ş Testing Steps

  1. 1Enable TalkBack: Settings → Accessibility → TalkBack
  2. 2Test portrait orientation: Navigate through the full interface and verify all elements are accessible
  3. 3Rotate to landscape: Verify the layout adapts correctly and TalkBack navigation remains logical
  4. 4Check state preservation: Enter data in a form, rotate the device, and verify no input is lost
  5. 5Verify touch targets: Confirm all interactive elements remain at least 48x48dp in both orientations
  6. 6Test with Android Emulator: Use different screen configurations to quickly test various device sizes
  7. 7Check scroll behaviour: Verify content scrolls in a single direction only and all content is reachable
  8. 8Test without screen reader: Verify layout and usability for sighted users in both orientations

Become a member to read this solution, and all of Ma11y.

This resource is part of our member knowledge base. Log in or create an account to unlock:

  • Complete accessibility guidance and implementation examples
  • Curated compliance frameworks and checklists
  • Early access to new tools and features