Sometimes the same layout doesn’t scale well for both the orientations i.e landscape and portrait. It’s always suggested to have different layout file for different screen orientation. Managing two layout for different orientations is quite easy. You can manage in two different ways.

  1. By using resource/layout folder.
  2. By dynamically set the layout.

resource/layout folder

This is the preferred way of managing the layouts. By convention, Android expects landscape specific layout file in res/layout-land and portrait layout file in res/layout-port.

Dynamically set the layout

Configuration class helps to determine the current orientation. Configuration class object is being passed as an argument in onConfigurationChanged method. This method is a callback method and gets called whenever there is change in configuration specified in the Activity attribute in AndroidManifest.xml file. This android:configChanges attribute should be set to orientation in the Manifest file. If you don’t include this attribute in Android Manifest file, then the onConfigurationChanged will not get invoked when there is change in the orientation.

Restricted layout

Sometimes we may need to restrict the layout to specific orientation. For example, if you are displaying a list of items, then you would prefer to display in portrait mode because here more number of list items can be displayed as compared to landscape mode. You can restrict the activity layout to the portrait mode with the help of android:screenOrientation attribute. You can notice this attribute in the AndroidManifest.xml file below. This attribute android:screenOrientation="landscape" of activity will restrict the activity in landscape mode whereas android:screenOrientation="portrait" will restrict the activity in Portrait mode. When you define this attribute in the AndroidManifest file, make sure to put the xml layout file in res/layout folder.

Source code

Create a project, give an appropriate project and package name for this project. In the main layout file add three buttons. These three buttons will launch different Activities and these Activities handle layout in a specific way. Attach onClick method to each button.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
<Button
    android:id="@+id/btAutomatic"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/bt_automatic_orientation"
    android:onClick="autoOrientationDetection"
    tools:context=".MainActivity"
    />
<Button
    android:id="@+id/btDynamic"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/bt_dynamic_orientation"
    android:onClick="dynamicOrientationDetection"
    tools:context=".MainActivity"
    />
<Button
    android:id="@+id/btRestricted"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/bt_restricted_orientation"
    android:onClick="restrictedOrientation"
    tools:context=".MainActivity"
    />
</LinearLayout>

Define the MainActivity class which contains OnClick() methods’ definition.

package com.code4reference.orientationspecificlayout;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    
    /**
     *Starts Automatic Orientation detection Activity.  
     * @param view
     */
    public void autoOrientationDetection(View view){
    	Intent intent = new Intent(this, AutomaticOrientation.class);
    	startActivity(intent);
    }
    /**
     * Starts the dynamic orientation detection Activity.
     * @param view
     */
    public void dynamicOrientationDetection(View view){
    	Intent intent = new Intent(this, DynamicOrientationDetection.class);
    	startActivity(intent);
    }
    /**
     * Starts the activity which has restricted layout.
     * @param view
     */
    public void restrictedOrientation(View view){
    	Intent intent = new Intent(this, RestrictedOrientation.class);
    	startActivity(intent);
    }
    
}

Create a layout file named activity_automatic.xml in res/layout-land. This layout file is landscape specific and gets automatically picked up when the phone is in landscape orientation.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:padding="@dimen/padding_medium"
        android:text="@string/landscape_orientation"
        android:textColor="#000808"
        android:textSize="20dp"
        android:textStyle="bold|italic"
        tools:context=".AutomaticOrientation" />

</RelativeLayout>

Now create another layout file with the same name(activity_automatic.xml) in res/layout-port folder. Notice that the different values have been set for color and text of the TextView in these layout files.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:padding="@dimen/padding_medium"
        android:text="@string/portrait_orientation"
        android:textColor="#FA00FA"
        android:textSize="20dp"
        android:textStyle="bold|italic"
        tools:context=".MainActivity" />

</RelativeLayout>

Create another class called AutomationOrientation which extends Activity class. In this class we just set the view of the Activity with the layout file.

package com.code4reference.orientationspecificlayout;

import android.app.Activity;
import android.os.Bundle;

public class AutomaticOrientation extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_automatic);
	}

}

Now, create the landscape and portrait layout files which will be selected and populated programmatically. In this part, we are going to detect the orientation of the phone and manually set the appropriate layout. As you can notice, I have named the layout files as activity_dynamic_land.xml and activity_dynamic_port.xml. These layout files are same as the above counterparts.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:padding="@dimen/padding_medium"
        android:text="@string/landscape_orientation"
        android:textColor="#000808"
        android:textSize="20dp"
        android:textStyle="bold|italic"
        tools:context=".MainActivity" />
</RelativeLayout>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:padding="@dimen/padding_medium"
        android:text="@string/portrait_orientation"
        android:textColor="#FA00FA"
        android:textSize="20dp"
        android:textStyle="bold|italic"
        tools:context=".MainActivity" />

</RelativeLayout>

Now define the DynamicOrientationDetection class which detects the current orientation and set the appropriate view with help of layout file. Notice that onConfigurationChanged method has been overridden in the class. This method gets called when the specified configuration changes for the activity. As you will notice android:configChanges="orientation" has been added in the AndroidManifest.xml file while including the DynamicOrientationDetection class. Now whenever orientation changes, the onConfigurationChanged method gets called.

package com.code4reference.orientationspecificlayout;

import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;

public class DynamicOrientationDetection extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//The below code provide the current orientation of the screen.
		setSpecificLayout(this.getResources().getConfiguration().orientation);
	}
    
	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
		setSpecificLayout(newConfig.orientation);
	}
	
	/**
	 * Set the specific layout based on the orientation.
	 * @param orientation
	 */
	public void setSpecificLayout(int orientation){
		//Based on the current orientation, the specific 
		//layout is set.
    	if (orientation == Configuration.ORIENTATION_LANDSCAPE){
    		setContentView(R.layout.activity_dynamic_land);
    	}
    	else if (orientation == Configuration.ORIENTATION_PORTRAIT){
    		setContentView(R.layout.activity_dynamic_port);
    	}
    }
}

We are going to restrict the orientation of the Activity below in landscape mode by defining this attribute android:screenOrientation="landscape" in AnroidManifest.xml file. Define the layout file in res/layout

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:padding="@dimen/padding_medium"
        android:text="@string/restricted_orientation"
        android:textColor="#000808"
        android:textSize="20dp"
        android:textStyle="bold|italic"
        tools:context=".RestrictedOrientation"/>
</RelativeLayout>

Define the RestrictedOrientation and set the layout in onCreate method.

package com.code4reference.orientationspecificlayout;

import android.app.Activity;
import android.os.Bundle;

public class RestrictedOrientation extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_restricted);
	}

}

After adding the three Activities in it, the AndroidManifest.xml file should look similar to the one given below:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.code4reference.orientationspecificlayout"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />  
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
         <activity
            android:name=".AutomaticOrientation"
            android:configChanges="orientation"
            android:label="@string/title_activity_automatic" >
            <intent-filter>
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".DynamicOrientationDetection"
            android:configChanges="orientation"
            android:label="@string/title_activity_dynamic" >
            <intent-filter>
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- screenOrientation restricts the Orientation 
        of the screen to specific one. As shown below, it 
        is restricted to landscape orientation.
         -->
         <activity
            android:name=".RestrictedOrientation"
            android:screenOrientation="landscape"
            android:label="@string/title_acivity_restricted" >
            <intent-filter>
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Once you are done with coding, just execute the project and you will see the application as shown below.
You can download the source code from github/Code4Reference

Orientation options for an Activity Portrait orientation specific layout
Landscape orientation specific layout

Please feel free to leave comments about post or website.Thanks ;-)

,
Trackback

2 comments untill now

  1. heyy nice tutorial,

    I have similar situation on my code
    In that, when i open alert Dialog box and change orientation from portrait to landscape dialogbox automatically dismiss..

    What to do?

    Thanks

  2. Good stuff! Thanks :)

Add your comment now