Logo Icon Logo
A Crowd-sourced Cookbook on Writing Great Android® Apps
GitHub logo Twitter logo OReilly Book Cover Art

Portrait or Landscape? Both!

Published? false
FormatLanguage: WikiFormat

Problem:

An Activity's screen should be useable in both portrait and landscape modes.

Solution:

Use layouts for each mode or add a ScrollView.

Discussion:

Most Android devices can support both a portrait and a landscape screen. Therefore an Application needs to work in both screen formats. Here is a screen from a simple App that converts a loan's annual interest rate to the monthly rate and vice versa.

Here is the layout for the screen.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <TextView android:layout_width="120dp" 
            android:layout_height="wrap_content" 
            android:text="Interest Rate (%): "/>
        <EditText android:id="@+id/inputRate" 
            android:layout_width="120dp" 
            android:layout_height="wrap_content" />
    </LinearLayout>
    <RadioGroup android:id="@+id/radioGroup"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <RadioButton android:id="@+id/radioToMonthly"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Yearly to Monthly"
            android:checked="true"/>
        <RadioButton android:id="@+id/radioToYearly"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Monthly to Yearly"/>
    </RadioGroup>
    <Button android:id="@+id/convert"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Convert"/>
    <LinearLayout android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <TextView android:layout_width="120dp" 
            android:layout_height="wrap_content" 
            android:text="Result (%): "/>
        <EditText android:id="@+id/result"
            android:layout_width="120dp" 
            android:layout_height="wrap_content"/>
    </LinearLayout>
</LinearLayout>

When the device is rotated (Ctrl-F11 on the emulator) the bottom of the screen is no longer visible and is not accessible.

One solution is to restrict Android to not switch the screen to landscape for the Activity. Open the AndroidManifest.xml file in the activity declaration element add the attribute screenOrientation and set it to portrait.

...<activity android:name=".main"
    android:label="@string/app_name"
    android:screenOrientation="portrait">...

This is not very user friendly. Instead of using the screenOrientation attibute a quick fix is to drop the entire layout into a ScrollView (remember to move the xmlns:android attribute from the first LinearLayout element to the ScrollView element). It has to be the entire layout because ScrollView is derived from FrameLayout which only accepts a single child.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
<LinearLayout 
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
        .
        .
        .
</LinearLayout>
</ScrollView>

A better solution is to explicitly support the landscape orientation. To do this create a folder under the res directory called layout-land. Copy the existing layout XML file from the res/layout folder into the new folder.

Then change the copied file in layout-land to suit the landscape orientation.

This is the modified layout file.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <TextView android:layout_width="120dp" 
            android:layout_height="wrap_content" 
            android:text="Interest Rate (%): "/>
        <EditText android:id="@+id/inputRate" 
            android:layout_width="120dp" 
            android:layout_height="wrap_content" />
    </LinearLayout>
    <RadioGroup android:id="@+id/radioGroup"
    	android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <RadioButton android:id="@+id/radioToMonthly"
            android:layout_width="160dp"
            android:layout_height="wrap_content"
            android:text="Yearly to Monthly"
            android:checked="true"/>
        <RadioButton android:id="@+id/radioToYearly"
            android:layout_width="160dp"
            android:layout_height="wrap_content"
            android:text="Monthly to Yearly"/>
    </RadioGroup>
    <LinearLayout android:layout_width="fill_parent"
            android:layout_height="wrap_content">
        <Button android:id="@+id/convert"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Convert"/>
        <TextView android:layout_width="100dp" 
            android:layout_height="wrap_content" 
            android:text="Result (%): "
            android:gravity="right"/>
        <EditText android:id="@+id/result"
            android:layout_width="120dp" 
            android:layout_height="wrap_content"/>
    </LinearLayout>
</LinearLayout>

There were no code changes required to support the landscape orientation, only copying and reworking the original portrait screen design.