Android

时间:2017-03-21 19:01:56

标签: java android android-activity mobile android-orientation

我正在使用minSdkVersion=15开发基于Android的移动应用程序。我想支持平板电脑的两种方向,只支持智能手机的肖像。一切都像魅力一样,但我遇到了一个让我发疯的小虫子。 当智能手机处于横向模式并且我尝试触发新的活动时,它会以横向模式打开一段时间,然后自动切换到纵向。 我的每个活动都扩展了一个GeneralActivity类:

public class GeneralActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // If smartphone lock orientation to portrait
        if (!Helper.isTablet(this.getApplicationContext())){
            this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
    }
}

我检测到具有此功能的平板电脑:

public class Helper {
    public static boolean isTablet(Context context){
        Configuration config = context.getResources().getConfiguration()
        return config.smallestScreenWidthDp >= 600;
    }
}

我选择不在Manifest.xml中指定android:screenOrientation,因为这样我就可以支持平板电脑的所有界面方向。 我错过了什么吗?

修改

我决定应用Jonathan在答案中提出的最佳做法,但我所描述的问题仍然存在。这是我在github上的回购:https://github.com/giacmarangoni/Android-Orientation-Test

7 个答案:

答案 0 :(得分:12)

我在Android N& amp; O并找到了解决方案。

我仍然在onCreate方法中使用setRequestedOrientation,但我已经为清单中的每个活动添加了这个:

android:screenOrientation="behind"

这可确保活动以与上一个活动相同的方向启动。之后的setRequestedOrientation将覆盖它,但如果它与上一个活动相同,则您不会看到任何更改为用户。

答案 1 :(得分:3)

我找到了使用以下方法解决此问题的正确方法:

android:screenOrientation="locked"

在此问题的清单中声明的​​每个活动中。

并继续以编程方式使用setRequestedOrientation()来定义onCreate()方法中的横向或纵向方向,

顺便说一下,在你的GitHub项目中,我刚刚更改了清单,添加了locked这样的方向,它最终起作用了:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.giacomomarangoni.orientationtest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            android:screenOrientation="locked">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".OtherActivity"
            android:screenOrientation="locked">
        </activity>
    </application>
</manifest>

希望它也能帮到你:)

答案 2 :(得分:0)

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

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

在最小宽度方向上超过600 dp的设备,或在Android 3.2之前的设备(平板电脑,基本上)上的x-large将基于传感器和用户锁定旋转等行为正常。其他所有(电话,差不多)只是肖像。

来源:Original answer

答案 3 :(得分:0)

我有这个解决方案适合我。 在您的清单声明屏幕方向肖像

<activity android:name=".activities.MainActivity"
        android:screenOrientation="portrait">

        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>

            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>

然后在您onCreate的基本活动中,在调用super.onCreate之前,如果设备是平板电脑,则将方向设置为未指定。

@Override
protected void onCreate(Bundle savedInstanceState) {
    if (!getResources().getBoolean(R.bool.portrait_only)) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
    }
    super.onCreate(savedInstanceState);
}

来自文档:

  

未指定:   没有指定偏好:让系统决定最佳方向。这将是下面活动选择的方向,或者如果此活动是任务的底部,则是用户的首选方向。如果用户通过基于设置传感器明确关闭基于传感器的方向,则将忽略设备旋转。如果不是默认情况下,将考虑基于传感器的方向,并且将根据用户旋转设备的方式更改方向。

这对我有用,到目前为止我还没有发现任何缺点。我只是在模拟器中对此进行了测试,并且看起来应用程序从纵向开始然后像手机上的其他解决方案一样旋转。无论如何,我更喜欢手机比平板电脑更好用,因为它们使用得更多。

如果您发现任何不能使用此解决方案的任何内容,请点击我!

答案 4 :(得分:0)

我也面临Android N设备的同样问题。因此,为了支持平板电脑的方向和仅手机的肖像,我做了以下技巧:

  1. 为Manifest中的每个活动设置肖像。看起来很糟糕,但在这种情况下屏幕不会自动旋转: android:screenOrientation="portrait"

  2. 在您的BaseActivity集中:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (isTablet(){  
           setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
        }
    }
    
    protected boolean isTablet() {
       return getResources().getBoolean(R.bool.tablet);
    }
    

答案 5 :(得分:0)

在您的基础活动中,您可以输入以下内容:

/*  Device types. */
static int MOBILE_DEVICE = 0;
static int SEVEN_INCH_TABLET = 1;
static int TEN_INCH_TABLET = 2;

private static int deviceType = MOBILE_DEVICE;
private boolean deviceTypeDetermined = false;


@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
@Override
protected void onCreate(Bundle savedInstanceState) {

    if ( ! deviceTypeDetermined) setDeviceType();

    /* Screen rotation only for tablets. */
    if (getDeviceType() < SEVEN_INCH_TABLET) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        lockScreenOrientation();

    ......
}



// ---------------------------------------------------------------------------------------------
static int getDeviceType() {
    return deviceType;
}
// ---------------------------------------------------------------------------------------------


// ---------------------------------------------------------------------------------------------
private void setDeviceTypeDetermined() {
    this.deviceTypeDetermined = true;
}
// ---------------------------------------------------------------------------------------------


// ---------------------------------------------------------------------------------------------
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
private void setDeviceType() {

    /*
        Let's invest on what kind of screen our APP is invited...

        We only make a difference in 10", 7" tablets and the rest...
    */

    Display mDisplay = getWindowManager().getDefaultDisplay();
    Point mScreenResolution = new Point();

    mDisplay.getRealSize(mScreenResolution);

    int mWidthPixels = mScreenResolution.x;
    int mHeightPixels = mScreenResolution.y;

    DisplayMetrics mMetrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(mMetrics);

    float mWidthDpi = mMetrics.xdpi;
    float mHeightDpi = mMetrics.ydpi;

    float mWidthInches = mWidthPixels / mWidthDpi;
    float mHeightInches = mHeightPixels / mHeightDpi;



    double mDiagonalInches = Math.sqrt(
            (mWidthInches * mWidthInches)
                    + (mHeightInches * mHeightInches));


    if (mDiagonalInches >= 9) {

        /*
            A tablet with 8" x 5" is called a 10", but it is in fact
            9.43398". Interesting that this kind of things happens in
            the world of informatics.... ;)
        */

        MyBaseAppCompatActivity.deviceType = TEN_INCH_TABLET;
    }

    else if (mDiagonalInches >= 7) {
        MyBaseAppCompatActivity.deviceType = SEVEN_INCH_TABLET;
    }

    else
    {
        MyBaseAppCompatActivity.deviceType = MOBILE_DEVICE;
    }


    setDeviceTypeDetermined();
}
// ---------------------------------------------------------------------------------------------


// ---------------------------------------------------------------------------------------------
void lockScreenOrientation() {

    /*  Screen rotation only for tablets. */
    if (deviceType < SEVEN_INCH_TABLET ) return;

    setRequestedOrientation(getResources().getConfiguration().orientation);
}
// ---------------------------------------------------------------------------------------------


// ---------------------------------------------------------------------------------------------
void unlockScreenOrientation() {

    /*  Screen rotation only for tablets. */
    if (deviceType < SEVEN_INCH_TABLET ) return;

    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
// ---------------------------------------------------------------------------------------------

在你的onCreate活动中:

// ---------------------------------------------------------------------------------------------
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
protected void onCreate(Bundle savedInstanceState) {
    // -----------------------------------------------------------------------------------------
    super.onCreate(savedInstanceState);

    if (getDeviceType() >= SEVEN_INCH_TABLET) unlockScreenOrientation();

    setContentView(R.layout.main_activity);

    .........

// ---------------------------------------------------------------------------------------------

答案 6 :(得分:-1)

在清单文件中的所有活动代码中添加此行...

 android:screenOrientation="portrait"