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:
- 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 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
:
<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 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
.
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.
<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));
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
}
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 |
--------------
="1.0"="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 |
--------------
="1.0"="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:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
setRequestedOrientation(orientation);
.
.
}
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;
setRequestedOrientation(orientation);
.
.
}
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 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