Android:允许平板电脑使用人像和风景,但在手机上强制使用人像吗?


191

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


一种方法是不像在layout-land内部res文件夹中那样设计手机的横向布局。
幽灵

12
那只会导致人像布局以横向显示。它实际上并不会阻止手机旋转到横向。
radley

Answers:


446

这是使用资源大小限定符的好方法。

将此bool资源作为bools.xml或其他内容(在这里文件名无关紧要)放入res / values中:

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

在最小宽度方向上大于600 dp的设备,或在Android 3.2之前的设备(基本上是平板电脑)上为x-large的设备,将根据传感器和用户锁定的旋转等情况表现出正常的行为。其他所有内容(电话,几乎全部)将仅是肖像。


1
我也需要使用xlarge还是可以使用sw600dp?这些天,可能没有任何平板电脑的运行时间低于3.2。
theblang 2014年

7
那么,这有可能重新启动时,在景观开始活动,请参阅developer.android.com/reference/android/app/...
Bondax

1
@Bondax该注释仅适用于“如果活动当前处于前台或以其他方式影响屏幕方向”,但由于我们此时处于onCreate中,所以情况并非如此。
Brian Christensen 2015年

1
@BrianChristensen我观察到在中设置请求的方向时重新开始活动onCreate()。当我setRequestedOrientation()在时间和上下文中将呼叫移至其他位置时,重新启动不再发生。
Bondax

8
如果我以横向模式启动该应用程序,它仍然会短暂显示横向模式。
最白目

29

您可以先尝试以这种方式获取设备的屏幕尺寸

if ((getResources().getConfiguration().screenLayout &      Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) {     
    Toast.makeText(this, "Large screen",Toast.LENGTH_LONG).show();

}
else if ((getResources().getConfiguration().screenLayout &      Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_NORMAL) {     
    Toast.makeText(this, "Normal sized screen" , Toast.LENGTH_LONG).show();

} 
else if ((getResources().getConfiguration().screenLayout &      Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_SMALL) {     
    Toast.makeText(this, "Small sized screen" , Toast.LENGTH_LONG).show();
}
else {
    Toast.makeText(this, "Screen size is neither large, normal or small" , Toast.LENGTH_LONG).show();
}

然后根据它设置方向

setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

4
我应该使用哪种方法setRequestedOrientation()方法?一旦onCreate开始,它已经选择了想要的方向。
肯尼·怀兰德

肯尼(Kenny)检查一下,我认为这可能会对您有所帮助stackoverflow.com/questions/2833474/…–
阿维·库马尔·曼库

我看到这个答案被赞成,但是我不确定它是否可以解决问题。Configuration提供screenLayout信息-DPI。问题与物理设备的屏幕尺寸有关-手机VS平板电脑。意思是,您可以拥有一个Configuration.SCREENLAYOUT_SIZE_NORMAL,它将是MDPI平板电脑。
固定


10

补充已接受答案

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

值-sw600dp

首先,从“项目”选项卡中,在导航器中选择“项目”(而不是Android)过滤器。

在此处输入图片说明

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

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

在此处输入图片说明

键入600的最小屏幕宽度。目录名称将自动生成。说OK。

在此处输入图片说明

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

值大

values-large仅当您支持Android 3.2之前的版本(API级别13)时,才需要添加目录。否则,您可以跳过此步骤。该values-large目录对应于values-sw600dp。(values-xlarge对应于values-sw720dp。)

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

在此处输入图片说明

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


2
让我知道这是否无效,我会解决。它为我工作。我只有一张选票,但没有评论,所以我不知道要解决什么。
苏拉奇

9

这是我的操作方式(受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;
} 

和:(如果您不重写此方法,则应用程序将在更改方向时调用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 
}

我似乎无法弄清的唯一一件事是,当从横向切换为纵向时,如何使应用程序更改布局文件,反之亦然。我认为答案的作用与上述链接相似,但我无法解决该问题-它删除了我的所有数据。但是,如果您有一个足够简单的应用程序,并且具有用于纵向和横向的相同布局文件,则应该可以使用。


2
将景观布局放置在您的layout-land文件夹中
radley 2013年

如果您不调用超级onConfigurationChanged,则会收到异常消息
-RominaV

8

遵循Ginny的回答,我认为最可靠的方法如下:

如上所述这里,投入资源sw600dp一个布尔值。它必须具有前缀sw,否则将无法正常工作:

在res / values-sw600dp / dimens.xml中

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

在res / values / dimens.xml中

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

然后创建一个方法来检索该布尔值:

public class ViewUtils {
    public static boolean isTablet(Context context){
        return context.getResources().getBoolean(R.bool.isTablet);
    }
}

从您想要此行为的活动扩展的基本活动:

public abstract class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (!ViewUtils.isTablet(this)) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
    }
}

因此,每个活动都会扩展BaseActivity:

public class LoginActivity extends BaseActivity //....

重要提示:即使您从扩展BaseActivity,也必须在AndroidManifest.xml中android:configChanges="orientation|screenSize"向每行添加以下行Activity

    <activity
        android:name=".login.LoginActivity"
        android:configChanges="orientation|screenSize">
    </activity>

5

好吧,这有点晚了,但是这里是一个仅XML的黑客解决方案,它不会像setRequestedOrientation必须更改方向那样重新创建活动:

https://stackoverflow.com/a/27015879/1281930


1
不起作用,平板电脑始终采用手机的方向。显然,在应用任何资源修饰符之前,清单中所有活动的android:screenOrientation都设置了一次。
0101100101

2

接受答案之后,我将在kotlin文件中添加解决方案,希望它对某人有帮助

将此bool资源res/values作为bools.xml或其他内容放入(文件名在这里无关紧要):

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

将这个一个在res/values-sw600dpres/values-sw600dp-land

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

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

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

1

其他解决方案对我不起作用。我仍然在对话和娱乐方面遇到一些奇怪的定向问题。我的解决方案是扩展活动,将其强制为清单中的肖像。

例:

public class MainActivityPhone extends MainActivity {}

manifest.xml:

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

在splashcreen活动中:

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

0

我知道的老问题。为了即使在方向可能改变或交换方向等情况下(例如在平板电脑上)也始终以纵向模式运行您的应用,我设计了此功能,该功能用于将设备设置为正确的方向,而无需了解纵向和横向功能在设备上组织。

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

    }

奇迹般有效!

注意:this.activity根据您的活动进行更改或将其添加到主要活动中并删除this.activity;-)

如果您想做相反的事情,则必须将代码更改为横向(但我认为很清楚如何做到这一点)。


0

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

而且,在我看来,在清单中设置configChanges属性是一个很大的折衷,这可能会花费大量的重构成本。Android开发人员不建议更改该属性

最后,尝试将screenOrientation设置为某种不同(以避免重新启动问题)是不可能的,由于静态清单不能更改,因此在静态上是不可能的,以编程方式只能在已经开始的活动中调用该方法。

简介:在我看来,@ Brian Christensen的建议是最好的折衷方案,但请注意重新开始的活动问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.