Monday, December 7, 2009

Dealing with orientation change in Android Widgets

As you know, i had some issues with the MineSweeper Widget in G1 devices (and, indeed, in all Android mobiles with physical keyboards).

This issue was related to switching between portrait and landscape modes.

First, i trusted in Android auto-resize, and it resulted in an acore crash when people switched to landscape mode (for example, putting out the physical keyboard), although it didn't crash in the Android emulator (it did a weird resize though).

In this particular case, it was no point on supporting landscape mode (too small buttons = unplayable), so i decided to show an error advice when landscape mode was activated. And this wasn't as easy as expected.

First of all, i realised that i needed buttons references in both portrait and landscape layouts, why? Because the user could add the widget while being in landscape mode, and MineSweeper's data and buttons needed to be assigned to their PendingIntents, otherwise it'll result in an unexpected behaviour, and user would see how widget didn't response when switching to portrait! So i left the buttons part of the layout in the "error layout" setting visibility to "gone".

Then, next problem appeared. Each time the layout changes from portrait to landscape, the view is re-inflated, so you need to re-assign PendingIntents to all layout elements before each updateAppWidget call (and reassign all viewResources too!).

And that's it!

And remember, don't trust Android Emulator and test your app in all devices as posible.

I suppose there are better ways to solve this issue, you can share them with us in the comments!

8 comments:

  1. How do you detect screen orientation in a widget?

    ReplyDelete
  2. If you need to know which orientation the device has in some part of your code, use:

    Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();

    display.getOrientation() will return you the orientation of the device (i think 0 is for landscape, 1 for portrait, not sure, so check it out)

    You must specify a different layout for each orientation in case you need it, and if you want your code doing different things depending on the orientation, use the code i've written :P

    ReplyDelete
  3. context.getResources().getConfiguration().orientation also works.

    ReplyDelete
  4. Hi, I'm facing a problem with a WIDGET
    android.intent.action.CONFIGURATION_CHANGED works for detecting orientation changes, but only from 1.5 to 2.0. It does not work in 2.01 and 2.1.
    Any tips?

    ReplyDelete
    Replies
    1. after 2.0 you cannot do it, android dev doc says:

      You can not receive CONFIGURATION_CHANGED through components declared in manifests, only by explicitly registering for it with Context.registerReceiver().

      Delete
  5. Hi, I have same problem with widget stopping reacting after orientation change, and I do not actually understand how i can "re-assign PendingIntents to all layout elements before each updateAppWidget call (and reassign all viewResources too!).". Can you please provide more details how to do this?

    ReplyDelete
  6. @Dejan, before you call updateAppWidget, wherever is in your code, you have to update all the elements in the RemoteViews object. This means assigning again PendingIntents to all elements in the RemoteViews, and all the image resources (if you change them in code, if not, it is not neccessary).

    What i usually do is making a method like assignButtons() that do all the PendingIntent assignments, and i call this method before each updateAppWidget call.

    Contact me on twitter if you need more help! http://twitter.com/luiskap

    ReplyDelete
  7. Hi really very well information for android development.

    Honeycomb continues where the mobile phone Android os left off with enhanced multitasking, rich notifications, home screen customization, widgets, and more. But Honeycomb transforms the user interface with a vibrant, 3D experience and deeper interactivity, making them feel familiar but even better than before.

    ReplyDelete