Question

I am trying to write an app where I want the phone to be locked to portrait, but allow the tablet version to have both landscape and portrait.

I have created something that almost works based on all the following questions...

How do I lock screen orientation for phone, but not for tablet? (Android) How to allow both landscape/portrait for tablets only Portrait for phone, landscape for Tablet (Android-Layout) landscape mode in tablet only Locking phone in portrait mode

What I've done so far is extend Activity into my own base Activity and to include orientation change code in both onCreate and an overwritten onConfigurationChanged

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        if(!(new DeviceHelper().isTablet(this)))
        {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
        super.onCreate(savedInstanceState);
        setupActionBar(getActivity());


    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        //don't reload the current page when the orientation is changed
        if(!(new DeviceHelper().isTablet(this)))
        {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
        super.onConfigurationChanged(newConfig);

    }

Everything with this works fine (I overwrote the onConfigurationChanged to avoid the activity being destroyed and recreated which lead to a black screen for a fraction of a second).

My main problem is that if you hold the phone in landscape, then the activity remains in portrait...perfect! However, because the phone is in actual landscape then the layout for landscape is used, which is a layout from the tablet.

My understanding was that when setRequestedOrientation is called, then it should fire onConfigurationChanged instantly, however, the fragment is called first, then the layout inflated incorrectly, before then calling onConfigurationChanged, which means the landscape layout is already set.

I understand that I could possibly set the layout in each of my activities, based on the configuration but I don't really want to do that.

So how can I get the app to use the appropriate layout file from the appropriate res folder, based on the setRequestedOrientation.

Thanks

Was it helpful?

Solution

If your landscape layout is just for tablets, I would suggest you put it in the tablet layout folders ie: layout-sw600dp-land (for 7in tablet landscape) and layout-sw720dp-land (for 10in tablet landscape). This way, the tablet layout will only be used in tablets. If you do not declare a landscape layout for the phone, it will use the regular portrait layout. Separating layout folders for the tablet and phone layouts helps for organization.

OTHER TIPS

Everything with this works fine (I overwrote the onConfigurationChanged to avoid the activity being destroyed and recreated which lead to a black screen for a fraction of a second).

I'm pretty sure this is the root of your problem. You should be able to accomplish what you are trying to do without overriding onConfigurationChanged. Let the OS handle the configuration changes and provide the correct layout files.

If you do this, you should be good on Tablets. They should not set a particular orientation and they should open to the correct orientation for each Activity. The phone devices will have that issue you are talking about with the quick black screen. What is happening is that the Activity will open first in the orientation the phone is held in, say Landscape. Then it will set its orientation to Portrait in code and undergo a configuration change, recreating the Activity and causing the momentary flash you are seeing.

There are ways you can mitigate this.

  • Use android:screenOrientation="behind" in the AndroidManifest.xml for each Activity. This will start the Activity in the orientation that the previous Activity was in (Portrait for phones, whatever for tablets). Then you never have to worry about the Activity getting created twice because it will always start itself in the correct orientation.

  • This does not fix your very first Activity however. You can either deal with the launcher Activity having that flash exactly once when the app launches, or you can set the launcher Activity to android:screenOrientation="portrait" in the manifest and make sure to set tablets to setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); in code. This may cause that flash to occur on startup for Tablets.

Using just the first bullet point should be good enough, but you should tailor your implementation to your app's user experience requirements.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top