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


当前回答

其他的解决方案对我都不起作用。在对话和娱乐方面,我仍然有一些奇怪的方向问题。我的解决方案是扩展活动,迫使它作为肖像在manifest。

例子:

public class MainActivityPhone extends MainActivity {}

manifest.xml:

        <activity
        android:screenOrientation="portrait"
        android:name=".MainActivityPhone"
        android:theme="@style/AppTheme.NoActionBar" />

在溅屏活动中:

    Intent i = null;
    boolean isTablet = getResources().getBoolean(R.bool.is_tablet);
    if (!isTablet)
        i = new Intent(this, MainActivityPhone.class);
    else
        i = new Intent(this, MainActivity.class);
    startActivity(i);

其他回答

以下是我的做法(灵感来自http://androidblogger.blogspot.com/2011/08/orientation-for-both-phones-and-tablets.html):

在AndroidManifest.xml中,对于每个你想要在纵向和横向之间改变的活动(确保你添加了screenSize -你不需要这个!)你不需要在这里设置屏幕方向。:

android:configChanges="keyboardHidden|orientation|screenSize"

在每个活动中添加的方法:

public static boolean isXLargeScreen(Context context) {
    return (context.getResources().getConfiguration().screenLayout
    & Configuration.SCREENLAYOUT_SIZE_MASK)
    >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
} 

and:(如果你不重写这个方法,应用程序将在改变方向时调用onCreate())

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

    if (!isXLargeScreen(getApplicationContext()) ) {            
        return; //keep in portrait mode if a phone      
    }

    //I set background images for landscape and portrait here
}

在每个Activity的onCreate()中:

if (!isXLargeScreen(getApplicationContext())) { //set phones to portrait; 
   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);            
}
else {
  //I set background images here depending on portrait or landscape orientation 
}

我唯一不明白的是如何让应用程序改变布局文件时,从横向到纵向或反之亦然。我假设答案是做类似于上面的链接,但我不能让它为我工作-它删除了我所有的数据。但如果你有一个足够简单的应用,你有相同的纵向和横向布局文件,这应该是可行的。

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

在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)
    }
}

建议的方法是不锁定任何窗口维度的方向,但您可以通过遵循这里的指南来实现。

在步骤中,要做的第一件事是解锁舱单上的方向

<activity
    android:name=".MyActivity"
    android:screenOrientation="fullUser">

接下来,你可以使用Jetpack窗口管理器来确定应用程序在屏幕上有多少空间:

/** Determines whether the device has a compact screen. **/
fun compactScreen(): Boolean {
    val screenMetrics = WindowMetricsCalculator
                        .getOrCreate()
                        .computeMaximumWindowMetrics(this)
    val shortSide = min(screenMetrics.bounds.width(),
                        screenMetrics.bounds.height())
    return shortSide / resources.displayMetrics.density < 600
}

最后,当空间变小时,锁定方向,通常在手机上:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    requestedOrientation = if (compactScreen())
        ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else
        ActivityInfo.SCREEN_ORIENTATION_FULL_USER
    ...
}

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

将这个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设备将会像正常的设备一样,基于传感器和用户锁定旋转等。其他所有东西(手机,几乎)都只能是竖屏。