屏幕方向的清单回退

9
Android清单文件的文档中,有多种不同的方法来指定screenOrientation
  • landscape
  • 在API 9中添加了sensorLandscape
  • 在API 18中添加了userLandscape
如何指定userLandscape,但在旧版本的Android上,它会回退到sensorLandscape,甚至更旧版本的则回退到landscape? 我在文档中找不到如何做到这一点的方式。
1个回答

11

我认为不能在清单文件本身中实现后备机制。

我建议在清单文件中指定其中之一 { userLandscape、sensorLandscape、landscape },然后在运行时检查版本并进行创新。

比如,在清单文件中选择android:screenOrientation="userLandscape"

在您的活动的onCreate(Bundle)中,在设置内容之前:

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);

希望有人能提出比这更好的解决方案。这似乎是一种暴力方法。

编辑:

尝试了另一种方法 - 根据我的了解(我可能会错),像 userLandscapesensorLandscape 等枚举类型不会改变值。因为它们目前的状态是:

<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>

因此,如果您要定义一个像这样的整数(integer)

<!-- `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>

你可以在你的活动标签中,将 @integer/customScreenOrientation 用作 android:screenOrientation 的值。

毋庸置疑,这只是一个半吊子的解决方法。如果有人能够确认 screenOrientation 枚举值的稳定状态,那么这种方法可能是可行的 - 与我的早期建议中包含多个活动的代码相比更为优越。

另一次编辑:

我之前提到的第二种方法可以改进:

不要使用多个 integers.xml 文件,而是创建 3 个 styles.xml 文件。我想你已经有了一个 - values/styles.xml。创建 values-v9/styles.xmlvalues-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>

接下来,创建values/integers.xml(一个文件),并定义一个整数customScreenOrientation:

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

您的活动标签将如下所示:

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

相比于第二种方法,这种方法的优势在于我们可以使用枚举代替硬编码的值。同样,如果枚举值已经确定,这两种方法是等效的。但是,如果它们发生了变化,第二种方法将会失败,而第三种方法将继续执行。


这个可以运行。我很想看到更优雅的解决方案,但也许没有更好的了。 - Tenfour04
@Tenfour04 我又玩了一下,发现另一个解决方法 - 在我看来它不太优雅,但可以用更少的代码提供解决方案。 - Vikram
@Tenfour04 添加了另一种(希望是最后一种)实现回退机制的方式。 - Vikram
1
我认为紧凑性方面,我仍然最喜欢第一个。实际上,我认为也许可以完全避免清单,只需在一个地方有一个三条件if-else块。 - Tenfour04
@Tenfour04 我同意。第一种方法加上你的更改是最好的。我正在检查是否可能有一个仅限于XML的解决方案,并为完整起见添加了其他方法。 - Vikram

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接