Handle layout change manually
The first obvious discussion point is how to handle layout change manually. When the layout change is handled manually for an activity:
- 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.
- 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 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:
<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.
<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 here: http://developer.android.com/guide/topics/manifest/activity-element.html
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.
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 should be done to the GUI for the new layout, this should be handled manually inside the overriden 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 layout change manually?
The next question to consider is, when to handle screen layout change manually? Android framework by default creates the displayed activity whenever the screen layout changes. Is this always necessary? If not, in which cases it is necessary? Based on personal experience my answer to these 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 only when the portrait and landscape layouts are inherently different. Let's consider two simple examples.
The first example below shows the days of 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.
<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>
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));
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.
<activity android:name=".Main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
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);
}
}
}
--------------
| 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>
--------------
| 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 telling 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 onCreate() method:
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:
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.
<activity android:name=".InfoActivity"
android:screenOrientation="portrait" >
.
.
.
</activity>
or
<activity android:name=".InfoActivity"
android:screenOrientation="landscape" >
.
.
.
</activity>
More information about statically locking the screen layout can be found at the following link:
Suggestions or comments?
For suggestions and comments please contact:
Ali Chousein
Apps
SocialNav
Geo-Filtered Assistant
Blogs
Android contacts: CONTACT_ID vs RAW_CONTACT_ID
Email addresses in Android contacts
Support knowledge sharing
To support free knowledge sharing please visit one of our sponsors below.