Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Mobile / Android

Handling screen layout changes in Android

4.80/5 (11 votes)
5 Sep 2012CPOL4 min read 139.1K   3  
How to handle screen orientation changes programmatically in Android.

Introduction

Handling screen layout programmatically, locking the screen layout, controlling the activity lifecycle when the device layout changes are topics every Android developer works on when developing an application. In this article I shortly share my experiences on programmatically managing screen layout in Android. Each section focuses on a different aspect of this topic.

Handle layout change manually

The first obvious discussion point is how to handle a layout change manually. When the layout change is handled manually for an activity:

  1. A new activity is not being created automatically when the layout of a device changes. Normally upon layout change, the current activity is destroyed automatically (the methods onPause(), onStop(), and onDestroy() are called) and a new activity is created (the methods onCreate(), onStart(), and onResume() are called) for the new layout.
  2. Any change to the GUI for the new layout, if necessary, should be done manually.

Next let's consider what should be done programmatically to handle a layout change manually. Suppose that inside your application you have an activity named InfoActivity for which you are going to programmatically handle the layout change. Inside your AndroidManifest.xml, you already have an entry similar to the one below for InfoActivity:

XML
<activity android:name=".InfoActivity" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
    </intent-filter>
</activity> 

As a first step you should add the attribute android:configChanges inside the activity tag.

XML
<activity android:name=".InfoActivity"
    android:configChanges="orientation|keyboardHidden" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
    </intent-filter>
</activity>

The extra line tells Android that whenever the device layout is changed or a hardware keyboard is opened, the implementation of InfoActivity has logic for handling the layout change. More information on this can be found on Android documentation.

Next it's necessary to implement the logic for handling this layout change manually. For this you need to override the method onConfigurationChanged() inside InfoActivity.

Java
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    .
    .
    .
}

The change in AndroidManifest.xml hinders the automatic creation of a new activity when the screen layout of a device changes. Should any change be done to the GUI for the new layout, this should be handled manually inside the overridden method onConfigurationChanged().

Beware! Even though these changes hinder creating a new activity every time the screen layout is changed, they don't lock the layout. In other words, visually you'll still see the screen rotating. Locking the screen layout is explained later in this article.

When to handle a layout change manually?

The next question to consider is, when to handle a screen layout change manually? The Android framework by default creates the displayed activity whenever the screen layout changes. Is this always necessary? If not, in which cases is it necessary? Based on personal experience my answer to the questions above is: When the screen layout changes, it's not always necessary to destroy the displayed activity and create it again for the new layout. This is only necessary when the portrait and landscape layouts are inherently different. Let's consider two simple examples.

The first example below shows the days of a week in a listview. In both portrait and landscape layouts, the view is the same. Hence it's not necessary to destroy and create this activity again whenever the screen layout changes.

XML
<activity android:name=".Main"
    android:configChanges="orientation|keyboardHidden" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
Java
public class Main extends ListActivity {
    private static final String[] MONTHS = new String[] {
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday",
        "Saturday",
        "Sunday"
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setListAdapter(new ArrayAdapter<String>(this, 
                android.R.layout.simple_list_item_1, MONTHS));
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // .
        // Add code if needed
        // .
    }
}

The second example displays two images; in the portrait layout, they are aligned vertically, and in the landscape layout, they are aligned horizontally.

Clearly, the layouts are inherently different, and the corresponding activity needs to be created again every time the screen layout changes. In this case, the activity lifecycle cannot be handled manually.

XML
<activity android:name=".Main" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
Java
public class Main extends ListActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getResources().getConfiguration().orientation ==
                    Configuration.ORIENTATION_PORTRAIT) {
            setContentView(R.layout.main_p);
        } else {
            setContentView(R.layout.main_l);
        }
    }
}
XML
--------------
| main_p.xml |
--------------
<?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" >

    <ImageView android:src="@drawable/image1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dip"
        android:layout_marginLeft="60dip" />

    <ImageView android:src="@drawable/image2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dip"
        android:layout_marginLeft="60dip" />

</LinearLayout>
XML
--------------
| main_l.xml |
--------------
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <ImageView android:src="@drawable/image1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dip"
        android:layout_marginLeft="20dip" />

    <ImageView android:src="@drawable/image2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dip"
        android:layout_marginLeft="40dip"/>

</LinearLayout>

Locking the screen layout

Programmatically

Programmatically locking the screen layout requires to specifically tell Android which screen layout it should display.

If you are not handling the screen layout change manually, you should do this inside the implementation of the onCreate() method:

Java
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    int orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
    // or = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
    setRequestedOrientation(orientation);
    .
    // Add code if needed
    .
}

If you are handling the screen layout change manually, you should specify the required screen layout inside the implementation of the onConfigurationChanged() method:

Java
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    int orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
    // or = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
    setRequestedOrientation(orientation);
    .
    // Add code if needed
    .
}

Statically

Alternatively, you can also lock the screen layout statically. This is done in AndroidManifest.xml, in the activity tag, using the android:screenOrientation attribute.

XML
<activity android:name=".InfoActivity"
    android:screenOrientation="portrait" >
    .
    .
    .
</activity>

or

XML
<activity android:name=".InfoActivity"
    android:screenOrientation="landscape" >
    .
    .
    .
</activity>

More information about statically locking the screen layout can be found in the Android documentation.

Related 

This study was done during the implementation of the two Android apps listed below. You are invited to check how smoothly screen layout change from portrait to landscape and vice versa works in these Android apps. Please click on the app name to download it from Google Play.

  • BeSocial - An innovative application where social networking and mobile navigation meet. Follow on Twitter 
  • Weather-Buddy - An innovative weather application for travelers and commuters. Follow on Twitter 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)