我希望平板电脑能够显示肖像和景观(sw600dp或更大),但手机仅限于肖像。我找不到任何有条件地选择方向的方法。有什么建议吗?


当前回答

我知道这是个老问题。为了让你的应用程序总是在纵向模式下运行,即使方向可能会被交换(例如在平板电脑上),我设计了这个功能,用于将设备设置在正确的方向上,而不需要知道设备上的纵向和横向功能是如何组织的。

   private void initActivityScreenOrientPortrait()
    {
        // Avoid screen rotations (use the manifests android:screenOrientation setting)
        // Set this to nosensor or potrait

        // Set window fullscreen
        this.activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        DisplayMetrics metrics = new DisplayMetrics();
        this.activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);

         // Test if it is VISUAL in portrait mode by simply checking it's size
        boolean bIsVisualPortrait = ( metrics.heightPixels >= metrics.widthPixels ); 

        if( !bIsVisualPortrait )
        { 
            // Swap the orientation to match the VISUAL portrait mode
            if( this.activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT )
             { this.activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); }
            else { this.activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ); }
        }
        else { this.activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); }

    }

效果好极了!

注意: 改变这种情况。活动由您的活动或添加到主活动,并删除此。活动;-)

如果你想做相反的事情,你必须将代码更改为横向(但我认为这是很清楚的)。

其他回答

我在提供的解决方案中遇到了一些问题,最后这对我来说是有效的:

在AndroidManifest.xml中设置Activity的方向为“锁定”:

<activity
    android:name="com.whatever.YourActivity"
    android:screenOrientation="locked"
    ... />

在Activity中的OnCreate(…)方法中,使用以下方法:

@SuppressLint("SourceLockedOrientationActivity")
override fun onCreate(savedInstanceState: Bundle?) {
    if (isTablet(resources)) {
        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
    } else if (resources.configuration.orientation != Configuration.ORIENTATION_PORTRAIT) {
        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
    }
    super.onCreate(savedInstanceState)
}

注意,你不需要在资源中使用布尔值的hack解决方案,你可以使用DeviceProperties类中的isTablet(资源)方法,除了其他东西之外,它检查是否smallstscreenwidthdp >= 600。

以下是接受的答案,我正在添加解决方案的kotlin文件,希望它能帮助到某人

将这个bool资源放在res/values中,作为bools.xml或其他文件(文件名在这里不重要):

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="portrait_only">true</bool>
</resources>

把这个放在res/values-sw600dp和res/values-sw600dp-land中:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="portrait_only">false</bool>
</resources>

然后,将其添加到您的活动或碎片的以下行中

class MyActivity : Activity() {

    @SuppressLint("SourceLockedOrientationActivity")
    override fun onCreate(savedInstanceState: Bundle?) {
        if (resources.getBoolean(R.bool.portrait_only)) {
            requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        }
        super.onCreate(savedInstanceState)
    }

    @SuppressLint("SourceLockedOrientationActivity")
    override fun onConfigurationChanged(newConfig: Configuration) {
        if (resources.getBoolean(R.bool.portrait_only)) {
            requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        }
        super.onConfigurationChanged(newConfig)
    }
}

下面是使用资源和大小限定符的好方法。

将这个bool资源放在res/values中,作为bools.xml或其他文件(文件名在这里不重要):

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <bool name="portrait_only">true</bool>
    </resources>

把这个放在res/values-sw600dp和res/values-xlarge中:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <bool name="portrait_only">false</bool>
    </resources>

有关在Android Studio中添加这些目录和文件的帮助,请参阅补充答案。

然后,在你的活动的onCreate方法中,你可以这样做:

    if(getResources().getBoolean(R.bool.portrait_only)){
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }

在最小宽度方向上超过600dp的设备,或者在android 3.2之前的设备(基本上是平板电脑)上的x-large设备将会像正常的设备一样,基于传感器和用户锁定旋转等。其他所有东西(手机,几乎)都只能是竖屏。

不幸的是,使用setRequestedOrientation(…)方法会导致活动重新启动,所以即使你在onCreate方法中调用这个,它也会经历活动生命周期,然后它会在请求的方向上重新创建相同的活动。所以在@Brian Christensen的回答中,你应该考虑到活动代码可能会被调用两次,这可能会产生不良影响(不仅是视觉上,而且在网络请求、分析等方面也会产生不良影响)。

此外,在清单中设置configChanges属性在我看来是一个很大的权衡,这可能会花费大量的重构成本。Android开发者不建议改变这个属性。

最后,尝试以不同的方式设置screenOrientation(以避免重新启动问题)是不可能的,静态不可能,因为静态manifest不能被改变,编程上只可能在已经启动的活动中调用该方法。

总结:在我看来,@Brian Christensen的建议是最好的权衡,但要注意重新启动活动的问题。

对已接受答案的补充

您可以在Android Studio中执行以下步骤来添加res/values-sw600dp和res/values-large目录及其bools.xml文件。

values-sw600dp

首先,在Project选项卡中选择导航器中的Project(而不是Android)过滤器。

然后右键单击app/src/main/res目录。选择“新建> Android资源目录”。

选择最小屏幕宽度,然后按>>按钮。

输入600作为最小的屏幕宽度。目录名称将自动生成。说好的。

然后右键单击新创建的values-sw600dp文件。选择“新建>值资源文件”。为名称键入bool。

values-large

只有在支持Android 3.2 (API级别13)之前,才需要添加一个值很大的目录。否则,您可以跳过此步骤。values-large目录对应于values-sw600dp。(values-xlarge对应values-sw720dp。)

要创建values-large目录,请执行与上面相同的步骤,但在本例中选择“大小”而不是“最小屏幕宽度”。选择大。目录名称将自动生成。

像以前一样右键单击该目录以创建bools.xml文件。