Saturday, March 26, 2011

How to handle Screen Orientation changes in Android - Part - 1

In one of my Android projects, we had a requirement that, when user changes the orientation of his phone from portrait to landscape or visa-a-versa, the GUI should adapt itself and render appropriately.

Android, is an awesome mobile development platform.  I have worked on iOS, Brew, Symbian and Android platforms but I can tell you one thing, the kind of productivity you get while developing apps for Android platform is higher than any other mobile platform.

Android does a lot of things automatically for you.  One of them is screen orientation change.  Android platform detects that the screen orientation has changed and adapts the GUI accordingly.  How does Android platform achieve this?

What happens when Android detects that the screen orientation has changed?

Android *destroys* the current activity and *recreates* the same activity all over again.  

Yes, you read it right!  And I will say it again, 

It *destroys* the current activity and *recreates* the same activity all over again.

Why does it do that?

Normally, in the portrait mode the screen has more hight than the width.  In landscape mode the scene is reversed.  The screen has more width than the height.  This means that if we go by the default behavior, user might see lot of blank spaces on the right side in the landscape mode.

Screen in Portrait mode
Screen in landscape mode

Have a look at the images of an activity in Portrait and Landscape mode.  In Portrait mode the screen looks decent, but in landscape mode the screen looks ugly. There is too much gap between the logo image on the left corner and "some screen" button on the right hand corner.  Moreover, the text box with the hint "Enter Zip or City, State" looks is way to long in the landscape mode.

Android has provided us a way to get around this problem.  We as developers can provide different layouts for landscape and portrait modes.

The layouts that should be used for landscape mode should be placed in a directory called layout-land


Landscape layout XML

Lets say we updated the layout for the landscape mode so that the icon, button, text box and the Search button appear all in one line.  The updated screen would look like

Updated screen in landscape layout
As you can see in the updated screenshot, the layout in the landscape mode looks much better now.  

Using different layouts for landscape and portrait mode enables us to effectively use the space.

Because of this reason, when screen orientation changes, Android destroys the current activity and recreates the activity all over again by choosing the correct layouts and configuration.  

This behavior lets you declare resources like layout's and drawable's based on the orientation, screen size, locale, etc.

This architectural choice, helps Android adapt the GUI easily and effectively when screen orientation changes. 

Think over this approach for a moment, do you think there are any problems with this approach?

What are the problems with this approach?
What if your activity performs some expensive operation when activity is created?
For example

As show in the above code when SomeActivity is created we creating an instance of SomeExpensiveObject class.  To indicate that creating the instance of this class is expensive, I have added a sleep of 5 seconds in the constructor of SomeExpensiveObject class.

Think about the user experience, when user changes screen orientation while viewing SomeActivity.
  • User has waited 5 seconds for the activity to load completely
  • He/She changes the screen orientation
  • Current activity is destroyed
  • New activity is re-created
  • User has to wait for 5 more seconds for the activity to be loaded completely with the new screen orientation.
How do we solve this problem?

In the next post I will show how effectively we can handle this problem.  Android provides not just one but two elegant solutions to the above problem.  All that and more in the next post.  Stay tuned! 

9 comments:

  1. excellent but how to handle this problem

    ReplyDelete
  2. yaa i got........ it great tutorial sir thanks

    ReplyDelete
  3. Nice work dude. I also facing the problem regarding the orientation change. When change the orientation, for a few milliseconds a blank screen is appear between th Landscape mode and portrait mode. How to avoid this or how to show some animation on same??

    ReplyDelete
  4. Thanks Dattatraya,

    About your problem of seeing a blank screen on orientation change, that should not happen. Are you doing some heavy processing in onCreate?

    Try and remove everything from your activity and see the behavior when you change the screen orientation. If there is no blank screen shown then start adding back your stuff. This way you will isolate the problem and probably fix it.

    Thanks

    Deep Shah

    ReplyDelete
  5. Would you mind me asking what have you used in ur website for the exterior cursor that makes such beautiful curls ?

    ReplyDelete
  6. Hi Deep,

    I have an issue with Honeycomb. Problem is I have a tow different layouts for lanscape and portrait. THe activity has two buttons when pressed we get an alert dialog. This dialog oges away when I change the orientatin. I tried with onConfigurationChanged but did not help.

    ReplyDelete
  7. Hello,

    The curls on the side is nothing but some HTML5 and javascript. You could save any page and get the javascript.

    When we change the orientation, as the activity is recreated, there is no way that it knows there was an alert dialog visible when the phone was in a previous state. If you want to show the dialog again when the orientation is changed then, you will have to remember that the dialog was visible and then when the activity is recreated show the alert dialog again. Its not done automatically.

    ReplyDelete
  8. hi, i think you can use new Thread
    public class Sr extends Activity {
    private TextView tv;
    @Override
    public void onCreate(Bundle b) {
    super.onCreate(b);
    setContentView(R.layout.sr);
    tv = (TextView) findViewById(R.id.sr_tv);
    }

    private static int i = 0;
    public void doBad(View v) {
    tv.setText("Bad " + ++i);
    tc();
    }
    public void doGood(View v) {
    tv.setText("Good " + ++i);
    new Thread(new Runnable() {
    public void run() {
    tc();
    }
    }).start();
    }
    private void tc() { // Time-consuming Tasks
    SystemClock.sleep(5000);
    // try { Thread.sleep(5000); } catch(Exception ex) { }
    }
    }

    ReplyDelete
  9. hi i have called two web services in oncreate methed and used buttons to start new activities.I have defined different layout for landscape and portrait mode and used onconfigurationchanged method but my application gets crashed when switching to other mode.please help me asap.

    Thanks

    ReplyDelete

Have some Fun!