I get ask this question a lot when I speak “My activities always bomb when the user switches to Landscape mode from Portrait, or visa versa. How can I fix this?” Indeed this is a very common problem new Android developers face. The good news is, this is very easy to solve with minimal code.
To start with, the most important thing is to identify what activities in your app you WANT the user to be able to view in any orientation. The truth is, there are certain activities where this doesn’t make sense (lists for example).
The first step is the Manifest. Each Activity must be listed so that it can be loaded during execution. This tag supports a screenOrientation attribute which locks that activity into a particular orientation. Below is a sample from the PayItSquare app I recently wrote:
In this case, the screen orientation will be locked as Portrait, which makes sense for this activity. My general rule of thumb is you can usually get away with locking activities that require no input from the user in portrait, since the user wont be entering any data in and therefore will have no use for the hard or the enlarged soft keyboard.
However, it will often be the case that you will want to handle the user changing your layout in various states. Android does, by default, handle this for you by essentially recreating the Activity. However, as one usually finds, this has undesirable consequences. The trick is to tell Android to NOT handle the orientation and notify the OS that the Activity will handle it itself. This is a two step process.
First, access the Manifest file and define android:configChanges property. The values here are bit flags that denote which config changes the activity will handle. The following values (or combination of them) are acceptable here:
- mcc
- mnc
- locale
- touchscreen
- keyboard
- keyboardHidden
- navigation
- orientation
- screenLayout
- uiMode
- fontScale
A complete reference of these values is located in the Android Docs here, regardless the ones we are most concerned with are orientation and keyboardHidden. In essence, orientation means we want to handle screen orientation changes (i.e. the user has rotated the screen), and keyboardHidden means entry accessibility has changed (i.e. the user has slid out a hard keyboard, which will always force the screen orientation). Note that while you may think that you don’t need keyboardHidden, however, my experience has proven otherwise.
To start with we add this information to the Manifest (shown below):
It is important to understand exactly what this is doing. This is effectively telling the OS that when this sort of config change happens WE will handle it and NOT the OS. This means we will override the default behavior, which is Activity Recreation.
To handle it, we override the following method in our Activity:
1: // use this method to handle the screen orientation change
2: @Override
3: public void onConfigurationChanged(Configuration configuration) {
4: super.onConfigurationChanged(configuration);
5: }
For the case of suppressing the Activity Recreation on the change of orientation, this is all you will need. You can simply leave this method as it is and the rest will be taken care of for you. The Configuration instance passed to this method can help you determine what configuration changed occurred. For example, you could determine the user changed the orientation and thus load a new layout file using setContentView for the updated orientation.
What I have done in Pay It Square is define this method in the super class. Then I defined either configChanges or screenOrientation for each Activity in the Manifest. Generally, if the user was going to provide input I would define configChanges, otherwise screenOrientation.
Remember, the onConfigurationChanged method will ONLY be called for config changes that you have told the activity to listen for.
Hopefully, this should help a lot of people overcome this very common problem.