Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Manifest fallbacks for screen orientation

Tags:

android

In the documentation for the Android manifest, there are multiple different ways to specify screenOrientation:

  • landscape
  • sensorLandscape added in API 9
  • userLandscape added in API 18

How can I specify userLandscape, but on older versions of Android, have it fallback to sensorLandscape, and on even older versions fall back to landscape? I couldn't find how to do this in the documentation.

like image 609
Tenfour04 Avatar asked Feb 18 '15 03:02

Tenfour04


1 Answers

I don't think that there's a way to implement the fallback mechanism in the manifest itself.

I would suggest that you specify one of { userLandscape, sensorLandscape, landscape } in the manifest. Then, check for the version at runtime and improvise.

Say, you decide to go with android:screenOrientation="userLandscape" in the manifest.

In your activity's onCreate(Bundle), before setting the content:

int sdkInt = Build.VERSION.SDK_INT;

// if we're running on some API level within [9, 18), use `sensorLandscape`
if (sdkInt >= Build.VERSION_CODES.GINGERBREAD /* 9 */ 
        && sdkInt < Build.VERSION_CODES.JELLY_BEAN_MR2 /* 18 */) {
    setRequestedOrientation(
            ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
} else if (sdkInt < Build.VERSION_CODES.GINGERBREAD /* 9 */) {
    setRequestedOrientation(
            ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}

// API 18 or above - handled in manifest

setContentView(R.layout.whatever);

Hope that someone comes up with a better solution than this. This seems brute-force.

Edit:

Tried a different approach - from what I know (and I could be wrong here), enums such as userLandscape, sensorLandscape etc. won't change values. As they currently stand:

<attr name="screenOrientation">
    <enum name="unspecified" value="-1" />
    <enum name="landscape" value="0" />
    <enum name="portrait" value="1" />
    <enum name="user" value="2" />
    <enum name="behind" value="3" />
    <enum name="sensor" value="4" />
    <enum name="nosensor" value="5" />
    <enum name="sensorLandscape" value="6" />
    <enum name="sensorPortrait" value="7" />
    <enum name="reverseLandscape" value="8" />
    <enum name="reversePortrait" value="9" />
    <enum name="fullSensor" value="10" />
    <enum name="userLandscape" value="11" />
    <enum name="userPortrait" value="12" />
    <enum name="fullUser" value="13" />
    <enum name="locked" value="14" />
</attr>

So, if you were to define an integer such as:

<!-- `0` for `landscape` -- defined in values/integers.xml -->
<integer name="customScreenOrientation">0</integer>

<!-- `6` for `sensorLandscape` -- defined in values-v9/integers.xml -->
<integer name="customScreenOrientation">6</integer>

<!-- `11` for `userLandscape` -- defined in values-v18/integers.xml -->
<integer name="customScreenOrientation">11</integer>

You could then use @integer/customScreenOrientation as the value for android:screenOrientation in your activity's tag.

Needless to say its a hack at best. If someone could confirm the steady status of enum values for screenOrientation, this could be a viable workaround - preferable to including code from my earlier suggestion in multiple activities.

Yet another edit:

The second approach I mentioned earlier can be improved upon:

Instead of multiple integers.xml files, create 3 styles.xml files. I guess you already have one - values/styles.xml. Create values-v9/styles.xml & values-v18/styles.xml.

<!-- values/styles.xml -->
<style name="AppTheme" parent="@style/BaseTheme">
    <item name="android:screenOrientation">landscape</item>
</style>

<!-- values-v9/styles.xml -->
<style name="AppTheme" parent="@style/BaseTheme">
    <item name="android:screenOrientation">sensorLandscape</item>
</style>

<!-- values-v18/styles.xml -->
<style name="AppTheme" parent="@style/BaseTheme">
    <item name="android:screenOrientation">userLandscape</item>
</style>

Following this, create values/integers.xml(one file) and define an integer customScreenOrientation:

<integer name="customScreenOrientation">?android:attr/screenOrientation</integer>

You activity tag will look like:

<activity
    ....
    android:theme="@style/AppTheme"
    android:screenOrientation="@integer/customScreenOrientation"/>

The advantage of this approach over the second one is that we get to use the enums in place of hard-coded values. Again, these two approaches are equivalent if enum-values are set in stone. If they do change, the second approach will fail while the third one keeps on going.

like image 65
Vikram Avatar answered Oct 03 '22 16:10

Vikram