Activity orientation changes automatically on Android

前端 未结 7 2064
天命终不由人
天命终不由人 2020-12-10 01:50

I\'m developing a mobile application based on Android with minSdkVersion=15. I would like to support both orientations for tablets and only portrait for smartph

相关标签:
7条回答
  • 2020-12-10 02:34

    Here's a good way using resources and size qualifiers.

    Put this bool resource in res/values as bools.xml or whatever (file names don't matter here):

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

    Put this one in res/values-sw600dp and res/values-xlarge:

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

    See this supplemental answer for help adding these directories and files in Android Studio.

    Then, in the onCreate method of your Activities you can do this:

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

    Devices that are more than 600 dp in the smallest width direction, or x-large on pre-Android 3.2 devices (tablets, basically) will behave like normal, based on sensor and user-locked rotation, etc. Everything else (phones, pretty much) will be portrait only.

    Source: Original answer

    0 讨论(0)
  • 2020-12-10 02:41

    I found the right way to solve this issue by using:

    android:screenOrientation="locked"
    

    in every activity declared in the manifest with this issue.

    And keep using setRequestedOrientation() programatically to define if landscape or portrait orientation within onCreate() method,

    Btw, in your GitHub project, I just changed the manifest adding locked orientation like this and it finally worked:

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

    Hope it will help you too :)

    0 讨论(0)
  • 2020-12-10 02:42

    I have this solution working for me. In your manifest declare screen orientations portrait

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

    Then in your base activity in your onCreate before you call super.onCreate if the device is a tablet set the orientation to unspecified.

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

    From the docs:

    Unspecified: No preference specified: let the system decide the best orientation. This will either be the orientation selected by the activity below, or the user's preferred orientation if this activity is the bottom of a task. If the user explicitly turned off sensor based orientation through settings sensor based device rotation will be ignored. If not by default sensor based orientation will be taken into account and the orientation will changed based on how the user rotates the device.

    This worked for me and so far i haven't found any drawbacks. I have only tested this in emulators and it doesn't seem that the app is starting in portrait and then rotating like it happened with the other solutions on phones. Anyway, i'd prefer phones to be working better than tablets just because they're used more.

    If you find anything not working with this solution hit me up!

    0 讨论(0)
  • 2020-12-10 02:44

    Add this line in all activity tags in menifest file...

     android:screenOrientation="portrait"
    
    0 讨论(0)
  • 2020-12-10 02:48

    I had the same problem on Android N & O and found a solution.

    I still use setRequestedOrientation in the onCreate method, but I've added this for every activity in the manifest:

    android:screenOrientation="behind"
    

    This makes sure that the activity launches with the same orientation as the previous activity. The setRequestedOrientation afterwards will override it, but if it's the same as the previous activity you don't see anything change as the user.

    0 讨论(0)
  • 2020-12-10 02:52

    In your base activity you can put something like this:

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

    And in your activities in the 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);
    
        .........
    
    // ---------------------------------------------------------------------------------------------
    
    0 讨论(0)
提交回复
热议问题