How to detect orientation change in layout in Android?
Asked Answered
B

11

127

I just implemented a orientation change feature - e.g. when the layout changes from portrait to landscape (or vice versa). How can I detect when the orientation change event finished.

The OrientationEventListener didn't work. How can I get notifications about layout orientation change events?

Biogen answered 20/4, 2011 at 7:4 Comment(1)
In my case, onCreate() was called when orientation changes.Evenhanded
P
326

Use the onConfigurationChanged method of Activity — as explained in the “Handling Runtime Changes” guide from the Android docs:

@Override public void onConfigurationChanged(@NotNull Configuration
newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    } }

You also have to edit the appropriate element in your manifest file to include the android:configChanges:

<activity android:name=".MyActivity"
          android:configChanges="orientation|keyboardHidden"
          android:label="@string/app_name">

NOTE: with Android 3.2 (API level 13) or higher, the "screen size" also changes when the device switches between portrait and landscape orientation. Thus, if you want to prevent runtime restarts due to orientation change when developing for API level 13 or higher, you must declare android:configChanges="orientation|screenSize" for API level 13 or higher.

Prospector answered 20/4, 2011 at 7:15 Comment(8)
This is good, but it doenst load the layout xml in layout-land folder it uses the portrait xml layout files.Degree
Aztec Coder, when you include "android:configChanges="orientation" you are declaring that you will handle the orientation change which means that your activity won't be recreated when you switch to landscape. Instead, onConfigurationChanged is called. If this is undesired, you could use a variable to remember your activity's orientation and every time you go though onPause (for example) to check if the orientation is still the same.Reeba
if several items are specified in android:configChanges, any way to distinguish between them?Dhole
If you are developing for API level 13 (3.2) or higher, you should specify android:configChanges="orientation|screenSize", otherwise onConfigurationChanged won't be called: developer.android.com/guide/topics/resources/…Marshmallow
Hi, I am building my app with API 10 (Android 2.3.3). And it recognises the orientation perfectly when i use android:configChanges="orientation|keyboardHidden". But my Nexus S which runs Android 4.1.2 does not detect the orientation change.What should i do?Can
use android:configChanges="orientation|screenSize" instead of android:configChanges="orientation|keyboardHidden" in your manifest file and check ... !!!Prospector
Unfortunately this does not work if using android:screenOrientation="landscape" or android:screenOrientation="sensorLandscape" in the AndroidManifest.xml. Any ideas what to do in these cases?Slovene
it doesn't detect landscape or landscape_inverseSusurrus
F
16

For loading the layout in layout-land folder means you have two separate layouts then you have to make setContentView in onConfigurationChanged method.

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        setContentView(R.layout.yourxmlinlayout-land);
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        setContentView(R.layout.yourxmlinlayoutfolder);
    }
}

If you have only one layout then no necessary to make setContentView in This method. simply

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}
Flax answered 6/11, 2012 at 6:52 Comment(4)
Instead of overriding, just use the layout/main.xml and layout-land/main.xml.Similarity
@JaredBurrows: Please see #23790105Diamagnetism
I wanted to detect that my activity was been terminated due to a screen rotation. I implemented the onConfigurationChanged(Configuration newConfig) method (as in this answer), but rather than handling it myself, I set a Boolean flag and then called the recreate() method so that Android recreated the activity in its normal fashion.Buddhism
One problem with the recreate() method is that it causes the screen to flash black briefly. For this reason I used another approach: (1) save the screen width in the onCreate(...), (2) compare the saved screen width to the current screen widtth in any life-cycle method when the activity is being terminated (e.g. onSaveInstanceState(...)).Buddhism
H
12

Just wanted to show you a way to save all your Bundle after onConfigurationChanged:

Create new Bundle just after your class:

public class MainActivity extends Activity {
    Bundle newBundy = new Bundle();

Next, after "protected void onCreate" add this:

@Override
public void onConfigurationChanged(Configuration newConfig) {
     super.onConfigurationChanged(newConfig);
     if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            onSaveInstanceState(newBundy);
        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            onSaveInstanceState(newBundy);
        }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBundle("newBundy", newBundy);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    savedInstanceState.getBundle("newBundy");
}

If you add this all your crated classes into MainActivity will be saved.

But the best way is to add this in your AndroidManifest:

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>
Horsepowerhour answered 23/6, 2013 at 17:26 Comment(1)
This is misleading. Implementing onConfigurationChanged() makes it so your instanceState is not destroyed when orientation changes, so you don't have to save it. You may want to save it for other events in the activity lifecycle, but I don't know.Brianbriana
N
7

use this method

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
    {
        Toast.makeText(getActivity(),"PORTRAIT",Toast.LENGTH_LONG).show();
       //add your code what you want to do when screen on PORTRAIT MODE
    }
    else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
    {
        Toast.makeText(getActivity(),"LANDSCAPE",Toast.LENGTH_LONG).show();
        //add your code what you want to do when screen on LANDSCAPE MODE
   }
}

And Do not forget to Add this in your Androidmainfest.xml

android:configChanges="orientation|screenSize"

like this

<activity android:name=".MainActivity"
          android:theme="@style/Theme.AppCompat.NoActionBar"
          android:configChanges="orientation|screenSize">

    </activity>
Nibelung answered 27/6, 2017 at 5:17 Comment(0)
H
5

In case this is of use to some newer dev's because its not specified above. Just to be very explicit:

You need two things if using onConfigurationChanged:

  1. An onConfigurationChanged method in your Activity Class

  2. Specify in your manifest which configuration changes will be handled by your onConfigurationChanged method

The manifest snippet in the above answers, while no doubt correct for the particular app that manifest belongs to, is NOT exactly what you need to add in your manifest to trigger the onConfigurationChanged method in your Activity Class. i.e. the below manifest entry may not be correct for your app.

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>

In the above manifest entry, there are various Android actions for android:configChanges="" which can trigger the onCreate in your Activity lifecycle.

This is very important - The ones NOT Specified in the manifest are the ones that trigger your onCreate and The ones specified in the manifest are the ones that trigger your onConfigurationChanged method in your Activity Class.

So you need to identify which config changes you need to handle yourself. For the Android Encyclopedically Challenged like me, I used the quick hints pop-out in Android Studio and added in almost every possible configuration option. Listing all of these basically said that I would handle everything and onCreate will never be called due to configurations.

<activity name= ".MainActivity" android:configChanges="screenLayout|touchscreen|mnc|mcc|density|uiMode|fontScale|orientation|keyboard|layoutDirection|locale|navigation|smallestScreenSize|keyboardHidden|colorMode|screenSize"/>

Now obviously I don't want to handle everything, so I began eliminating the above options one at a time. Re-building and testing my app after each removal.

Another important point: If there is just one configuration option being handled automatically that triggers your onCreate (You do not have it listed in your manifest above), then it will appear like onConfigurationChanged is not working. You must put all relevant ones into your manifest.

I ended up with 3 that were triggering onCreate originally, then I tested on an S10+ and I was still getting the onCreate, so I had to do my elimination exercise again and I also needed the |screenSize. So test on a selection of platforms.

<activity name= ".MainActivity" android:configChanges="screenLayout|uiMode|orientation|screenSize"/>

So my suggestion, although I'm sure someone can poke holes in this:

  1. Add your onConfigurationChanged method in your Activity Class with a TOAST or LOG so you can see when its working.

  2. Add all possible configuration options to your manifest.

  3. Confirm your onConfigurationChanged method is working by testing your app.

  4. Remove each config option from your manifest file one at a time, testing your app after each.

  5. Test on as large a variety of devices as possible.

  6. Do not copy/paste my snippet above to your manifest file. Android updates change the list, so use the pop-out Android Studio hints to make sure you get them all.

I hope this saves someone some time.

My onConfigurationChanged method just for info below. onConfigurationChanged is called in the lifecycle after the new orientation is available, but before the UI has been recreated. Hence my first if to check the orientation works correctly, and then the 2nd nested if to look at the visibility of my UI ImageView also works correctly.

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        // Checks the orientation of the screen
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        }
    }
Homogenize answered 28/7, 2019 at 9:20 Comment(0)
O
2

Override activity's method onConfigurationChanged

Overtax answered 20/4, 2011 at 7:13 Comment(1)
I would like to point out that without the following line inside the <activity> tag in the manifest, onConfigurationChanged() call back would not even get triggered. android:configChanges="orientation"Dipteran
C
1

Create an instance of OrientationEventListener class and enable it.

OrientationEventListener mOrientationEventListener = new OrientationEventListener(YourActivity.this) {
    @Override
    public void onOrientationChanged(int orientation) {
        Log.d(TAG,"orientation = " + orientation);
    }
};

if (mOrientationEventListener.canDetectOrientation())
    mOrientationEventListener.enable();
Complected answered 29/3, 2018 at 11:40 Comment(1)
Please do not vandalise your answer. If you want to delete it, you can find the delete button at the bottom left of your answer.Theater
M
1

I just want to propose another alternative that will concern some of you, indeed, as explained above:

android:configChanges="orientation|keyboardHidden" 

implies that we explicitly declare the layout to be injected.

In case we want to keep the automatic injection thanks to the layout-land and layout folders. All you have to do is add it to the onCreate:

    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
        getSupportActionBar().hide();

    } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        getSupportActionBar().show();
    }

Here, we display or not the actionbar depending on the orientation of the phone

Microprint answered 7/2, 2019 at 9:17 Comment(0)
F
1

for Kotilin implementation in the simplest form - only fires when screen changes from portrait <--> landscape if need device a flip detection (180 degree) you'll need to tab in to gravity sensor values

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

val rotation = windowManager.defaultDisplay.rotation

    when (rotation) {            
        0 -> Log.d(TAG,"at zero degree")
        1 -> Log.d(TAG,"at 270 degree")
        2 -> Log.d(TAG,"at 180 degree")
        3 -> Log.d(TAG,"at 90 degree")


    }
}
Fluoroscopy answered 19/5, 2020 at 3:0 Comment(0)
B
1

In case anyone else spends way too long on this like I did - it doesn't work on the emulator. Has to be real device.

Badinage answered 1/11, 2021 at 17:48 Comment(1)
Same here. This only worked when running on an actual device. I could not get it to work in the Emulator with a Pixel 3a API 30 VM.Erlineerlinna
F
0

If accepted answer doesn't work for you, make sure you didn't define in manifest file:

android:screenOrientation="portrait"

Which is my case.

Frontpage answered 31/5, 2019 at 6:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.