219

I would like tablets to be able to display in portrait and landscape (sw600dp or greater), but phones to be restricted to portrait only. I can't find any way to conditionally choose an orientation. Any suggestions?

Kenny Wyland
  • 20,844
  • 26
  • 117
  • 229
  • One way would be NOT to design landscape layouts for phones, as in using `layout-land` inside `res` folder. – Ghost Mar 09 '12 at 01:52
  • 12
    That would only cause the portrait layout to show in landscape. It won't actually prevent a phone from rotating to landscape. – radley Apr 06 '13 at 10:36
  • Here is an **XML-Only** but a hack solution which does not recreate an Activity as `setRequestedOrientation` does if has to change orientation: https://stackoverflow.com/a/27015879/1281930 – guness Nov 20 '14 at 09:06

14 Answers14

483

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.

Community
  • 1
  • 1
Brian Christensen
  • 5,076
  • 2
  • 16
  • 7
  • 2
    Do I need to use `xlarge` too or can I just use `sw600dp`? There probably aren't any tablets running < 3.2 these days. – theblang Jun 19 '14 at 14:39
  • @mattblang Totally up to you. There probably aren't many out there, but it's pretty easy to support the few there are. Sadly, [people still buy gingerbread tablets](http://www.amazon.com/VIZIO-8-Inch-Tablet-WiFi-VTAB1008/product-reviews/B005B9G79I/ref=cm_cr_pr_top_recent?ie=UTF8&showViewpoints=0&sortBy=bySubmissionDateDescending). – Brian Christensen Jun 23 '14 at 15:02
  • thanks +1 most easiest way, a small query- what about values-v11, values-v14, values-w820dp - i guess w820dp (set bool to false), and v11 & v14 no need to make any changes... am i right ? – Sun Jul 28 '14 at 12:23
  • This makes my build fail. I suppose I need to import ActivityInfo? Maybe define getResources and setRequestedOrientation? Could you give more details for those of use using cordova who don't know too much about Java? – Shawn Sep 24 '14 at 11:52
  • Ok, build works now, I had to add `import android.content.pm.ActivityInfo;`. – Shawn Sep 26 '14 at 08:14
  • 7
    Well, this potentially restarts the activity when started in landscape, see http://developer.android.com/reference/android/app/Activity.html#setRequestedOrientation%28int%29 – Bondax Apr 09 '15 at 08:59
  • 1
    @Bondax That comment only applies "If the activity is currently in the foreground or otherwise impacting the screen orientation" which can't be the case since we are in onCreate at this point. – Brian Christensen Apr 17 '15 at 20:32
  • 1
    @BrianChristensen I observed restarting an activity when setting requested orientation in `onCreate()`. When i moved the call to `setRequestedOrientation()` to a different position in time and context, the restart didn't happen any more. – Bondax Apr 20 '15 at 08:51
  • I don't have these res/values-sw600dp and res/values-xlarge folders in my app. Can I add those folders? – Gangadhar Jannu Mar 23 '16 at 09:31
  • I wanted to add some more info on this coming from https://developer.android.com/training/multiscreen/screensizes.html . In here they provide an elegant way to deal with large vs. sw600dp and to support both without adding too much trouble by using aliases. Scroll to the section: Use Layout Aliases to see how it is done. – JaviMar Dec 21 '16 at 11:35
  • can you help http://stackoverflow.com/questions/42172864/genymotion-screen-oriantation-issue-for-tablet – Aditya Vyas-Lakhan Feb 11 '17 at 06:19
  • I implemented the solution you provided but I'm facing an issue I described in this question: http://stackoverflow.com/questions/42936007/activity-orientation-changes-automatically-on-android – JJack_ Mar 21 '17 at 20:40
  • 14
    if I start the app in landscape mode, it still shows landscape mode for a brief moment. – 最白目 Jun 29 '17 at 07:54
  • if(getResources().getBoolean(R.bool.portrait_only)){ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); }else{ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); } – taran mahal Aug 28 '17 at 06:03
  • @dan Did you find the solution? I am facing the same issue. – Kiran K Sep 26 '17 at 09:51
  • @Kiran K unfortunately no – 最白目 Sep 26 '17 at 13:24
  • I have same problem like https://stackoverflow.com/questions/46427110/some-devices-are-taking-different-orientation-for-brief-moment-then-what-i-set – Kiran K Sep 27 '17 at 08:30
  • 3
    @dan I've found a solution to this problem by adding 'android:screenOrientation="behind"' to every activity in the manifest. See my full answer here: https://stackoverflow.com/questions/42936007/activity-orientation-changes-automatically-on-android/46565259#46565259 – Huby Oct 04 '17 at 12:58
  • But what about the first activity? we will still face the same issue with first activity – abhishek maharajpet Sep 06 '19 at 06:58
  • I made everything as described. Then I added the posted code below `public void onCreate(Bundle savedInstanceState) {` in `MainActivity.java`. But I'm getting `Cannot resolve symbol 'ActivityInfo'` for `ActivityInfo`. Why that? What am I doing wrong? – David Sep 06 '20 at 18:10
  • import also `com.[App_Name].app.R;` – Chawki Messaoudi Dec 04 '20 at 09:27
  • This is important to specify screenOrientation:"locked" in your Manifest's activities, otherwhise you may have the Activity in Landscape at Activity startup and then it will be forced to portrait. see https://stackoverflow.com/a/73893655/5437789 – TwiXter Sep 29 '22 at 10:21
  • Just thinking out loud here: with regards to launching a "portrait only" application from a currently landscape view... I think the fact that the splash screen shows _briefly_ in landscape orientation first is more of a feature than a bug. From a pure UX perspective, the rotating animation leaves no doubt in the user's mind that "oh, hey, this app is portrait only". IIRC, in Xcode (with simple project settings), disallowing "landscape" orientation on iPhone and then launching the app on a phone in landscape view gives a very similar animated experience. – Andre Greeff Dec 01 '22 at 07:18
20

Supplement to the accepted answer

You can do the following steps in Android Studio to add the res/values-sw600dp and res/values-large directories with their bools.xml files.

values-sw600dp

First of all, from the Project tab select the Project (rather than Android) filter in the navigator.

enter image description here

Then right click the app/src/main/res directory. Choose New > Android Resource Directory.

Select Smallest Screen Width, and then press the >> button.

enter image description here

Type in 600 for the smallest screen width. The directory name will be automatically generated. Say OK.

enter image description here

Then right click on the newly created values-sw600dp file. Choose New > Values resource file. Type bools for the name.

values-large

Adding a values-large directory is only necessary if you are supporting pre Android 3.2 (API level 13). Otherwise you can skip this step. The values-large directory corresponds to values-sw600dp. (values-xlarge corresponds to values-sw720dp.)

To create the values-large directory, follow the same steps as above, but in this case choose Size rather than Smallest Screen Width. Select Large. The directory name will be automatically generated.

enter image description here

Right click the directory as before to create the bools.xml file.

Community
  • 1
  • 1
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
10

Following Ginny's answer, I think the most reliable way to do it is as follows:

As described here, put a boolean in resources sw600dp. It must have the prefix sw otherwise it won't work properly:

in res/values-sw600dp/dimens.xml

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

in res/values/dimens.xml

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

Then make a method to retrieve that boolean:

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

And a base activity to extend from the activities where you want this behaviour:

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

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

So each activity would extend BaseActivity:

public class LoginActivity extends BaseActivity //....

Important: even if you extend from BaseActivity, you must add the line android:configChanges="orientation|screenSize" to each Activity in your AndroidManifest.xml:

    <activity
        android:name=".login.LoginActivity"
        android:configChanges="orientation|screenSize">
    </activity>
Community
  • 1
  • 1
RominaV
  • 3,335
  • 1
  • 29
  • 59
9

Here's how I did it (inspired by http://androidblogger.blogspot.com/2011/08/orientation-for-both-phones-and-tablets.html ):

In AndroidManifest.xml , for each activity you want to be able to change between portrait and landscape (make sure you add screenSize - you didn't used to need this!) You don't need to set a screen orientation here. :

android:configChanges="keyboardHidden|orientation|screenSize"

Methods to add in each Activity:

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

and: (if you don't override this method, the app will call onCreate() when changing orientations)

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

In onCreate() of each Activity :

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

The only thing I can't seem to figure out is how to to get the app to change layout files when switching from landscape to portrait or vice versa. I assume the answer is doing something similar to what the above link does, but I couldn't get that to work for me - it deleted all my data. But if you have a simple enough app that you have the same layout file for portrait and landscape, this should work.

Ginny
  • 3,111
  • 2
  • 18
  • 12
7

I had issues with provided solutions, finally this is what worked for me:

  1. In AndroidManifest.xml set Activity's orientation to "locked":
<activity
    android:name="com.whatever.YourActivity"
    android:screenOrientation="locked"
    ... />
  1. In OnCreate(...) method in your Activity, use the following:
@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)
}

Note that you don't need to use hacky solutions with boolean values in resources, you can use isTablet(resources) method from DeviceProperties class, which apart from other things checks if smallestScreenWidthDp >= 600.

Micer
  • 8,731
  • 3
  • 79
  • 73
5

I recently came across this requirement but didn't want to use any of these solutions. All of them have in common that they call setRequestedOrientation programmatically. The problem with this is it sets the orientation too late and causes slight UI glitches. If your device is in landscape when you launch the app it loads in landscape then rotates. This is particularly noticeable if you use a theme to create a splash screen effect as you will see the background image in the wrong orientation. This can also have a side effect on how your app is shown in the recent apps and issues with configuration change as noted in other answers comments.

Conclusion the correct orientation NEEDS to be set in the manifest so the system knows the orientation without launching your app.

Here is a solution on how to do this (it is quite a bit of effort, but you will sleep better)

First set the orientation in the manifest as a placeholder

<activity
      android:screenOrientation="${screenOrientation}"
     ...
</activity>

We then need to add a normal/tablet flavour to set the value in the app/build.gradle. (Could be achieved with a new build type if your already using flavours)

android {
    ...
    productFlavors {
        normal {
            manifestPlaceholders = [screenOrientation: "portrait"]
        }
        tablet {
            manifestPlaceholders = [screenOrientation: "unspecified"]
        }
    }
}

Now we need to tell the tablet build that it is just for large devices. This can be done by adding a tablet only manifest to merge with the default one. Add a new manifest file at->

app
 src
  tablet
   AndroidManifest.xml

Below is all this manifest needs, because it is merged with the default one is ->

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

    <supports-screens
        android:smallScreens="false"
        android:normalScreens="false"
        android:largeScreens="true"
        android:xlargeScreens="true"
        android:requiresSmallestWidthDp="600"
        />

</manifest>

The final trick is we need to differentiate builds by version code because the Playstore can not have two uploads with matching codes. We want to make sure the tablet (the more restrictive build) has the higher code. An easy way is to take a base code, then for tablet base * 2 and normal base * 2 - 1. I use CI for this with base code being build number but easy enough to hard code in your flavours.

Now build both flavours to create

 app-normal.apk/aab (v1.0.0, version code 1)
 app-tablet.apk/aab (v1.0.0, version code 2)

Upload them to Playstore as multiple apk/aab uploads then if downloaded on a tablet the Playstore serves them the apk that rotates and if downloaded on a phone the portrait only one.

Note: only works if distributing via the Google Playstore/Amazon Kindle

Further reading https://developer.android.com/google/play/publishing/multiple-apks https://developer.amazon.com/docs/fire-tablets/ft-screen-layout-and-resolution.html

Stuart Campbell
  • 1,141
  • 11
  • 13
  • where does the product flavors go? You missed some context there. – wesley franks Aug 04 '20 at 19:09
  • 1
    @wesleyfranks added a little more context. You may want to read up on flavours https://developer.android.com/studio/build/build-variants as the answer does assume some experience with them as dependent on your apps current set up may require tweaks. The concept is use gradle to configure manifest at build time vs the other answer of configuring at run time. – Stuart Campbell Aug 05 '20 at 09:13
  • This solution worked for me: https://stackoverflow.com/a/60381441/7826494 – David Elmasllari Sep 14 '21 at 15:05
  • It means that you will have 2 different APKs while using screenOrientation:'nosensor' would do the same in a single APK. https://stackoverflow.com/a/73893655/5437789 – TwiXter Sep 29 '22 at 10:17
  • That would lock tablets to landscape, which might be what you want, but I want any orientation on tablets. Question title "Android: allow portrait and landscape for tablets" – Stuart Campbell Sep 29 '22 at 10:54
4

Following accepted answer, I am adding the kotlin file with the solution hope it helps someone

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-sw600dp-land:

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

Then, add it in below lines in your activity or 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)
    }
}
Rahul
  • 3,293
  • 2
  • 31
  • 43
1

Other solutions didn't work for me. I still had some weird orientation problem with dialogs and recreation issues. My solution was to extend the Activity, forcing it as portrait in manifest.

Example:

public class MainActivityPhone extends MainActivity {}

manifest.xml:

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

in splashcreen activity:

    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);
mengoni
  • 248
  • 3
  • 8
1

From developer.android.com you should declare your screen Orientation in your manifest with value 'nosensor':

The orientation is determined without reference to a physical orientation sensor. The sensor is ignored, so the display will not rotate based on how the user moves the device.

The rotation will then be the 'natural' device behaviour (For phones: Portrait / for Tablets: landscape).

Advandage is that you can mix up different rotations per activity, for example, if you have an activity showing database records, then you can set this activity orientation to "fullUser" while others are using "nosensor". "fullUser" Activity will rotate depending user selection (rotation enabled: uses sensor otherwhise uses user preference).

<activity android:name=".scanner.ScannerPropertiesActivity" 
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/title_activity_scanner_properties"
android:screenOrientation="${screenOrientation}"/>

${screenOrientation} is a ManifestPlaceHolder so i could switch easily all the Activities i wish to test between all orientation behaviours using this:

//module's build.gradle
defaultConfig {
//...
    manifestPlaceholders = [applicationName:appName,screenOrientation:'nosensor']
//...
}

If you need something more complex (ie: Allow Screen rotation only in a tablet and fix phone orientation to portrait) then you should use locked:

android:screenOrientation="locked" I have noticed that if you force orientation to portrait while sensor sends that phone is rotated in landscape, your Activity will start in landscape and then rotate to portrait once your code is executed, with almost any other orientation. lock keeps the previous rotation, so you may be already locked in portrait from your previous activity. Then you must know when a device is a tablet or a phone: To do so i recommend you to use this:

Detect tablet using resource overload

//normal tablet_detection file content:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="isTablet" type="bool">false</item>
</resources>
//sw600dp tablet_detection file content:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="isTablet" type="bool">true</item>
</resources>
//Now in your code you can detect if it's a tablet or not by calling following function in your Activity's **onCreate** and apply screen orientation by code:
protected  void updateScreenOrientation(){
boolean isTablet =context.getResources().getBoolean(R.bool.isTablet);
//And select the orientation you wish to set:
int defaultOrientation=isTablet? ActivityInfo.SCREEN_ORIENTATION_FULL_USER:ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
        if(getRequestedOrientation()== ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
            //Apply this only on Activities where you set the orientation to 'locked' in the manifest
            this.setRequestedOrientation(defaultOrientation);
        }
}
TwiXter
  • 181
  • 2
  • 9
0

Old question I know. In order to run your app always in portrait mode even when orientation may be or is swapped etc (for example on tablets) I designed this function that is used to set the device in the right orientation without the need to know how the portrait and landscape features are organised on the device.

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

    }

Works like a charm!

NOTICE: Change this.activity by your activity or add it to the main activity and remove this.activity ;-)

If you want to do the opposite, you must change the code to landscape (but I think it is clear how to this).

Codebeat
  • 6,501
  • 6
  • 57
  • 99
  • You may not detect if it's a tablet or a phone nawadays with growing screen resolutions. – TwiXter Sep 29 '22 at 10:13
  • @TwiXter This is not about detecting if it is a phone or tablet, this is about detecting the real orientation (to your eyes). Read the text carefully. As long as there are no square screens this is a perfect solution. – Codebeat Sep 29 '22 at 15:49
  • the question is **Android: allow portrait and landscape for tablets, but force portrait on phone?** ... Anyway, the best solution to get the orientation is: **context.getResources().getConfiguration().orientation** which will return **ORIENTATION_PORTRAIT** / **ORIENTATION_LANDSCAPE** / **ORIENTATION_SQUARE** (Watches mostly) or **ORIENTATION_UNDEFINED** – TwiXter Sep 30 '22 at 08:59
  • @TwiXter In the question: " I can't find any way to conditionally choose an orientation. " That is what my answer is about. Also, portrait and landscape can be swapped on some tablet models, it depends on how it is implemented on the device. That is why I made this function to find out it is really portrait or landscape to the eyes of the user. I don't care what the device reports because it can be visually wrong. This method never fail. – Codebeat Sep 30 '22 at 23:34
0

Unfortunately, using the method setRequestedOrientation(...) will cause the activity to restart, so even if you call this in the onCreate method it will go through the activity lifecycle and then it will recreate the same activity in the requested orientation. So at @Brian Christensen's answer you should consider that the activity code might be called twice, this could have bad effects (not only visual, but also at network requests, analytics, etc.).

Furthermore, to set the configChanges attribute in the manifest is in my opinion a big trade-off, which could take massive refactoring cost. Android Devs are not recommending to change that attribute.

Finally, trying to set the screenOrientation somehow different (to avoid the restarting problem) is impossible, statically impossible due to the static manifest which can't be changed, programmatically it is only possible to call that method in the already started activity.

Summary: In my opinion, @Brian Christensen suggestion is the best trade-off, but be aware of the restarting activity issue.

mathew11
  • 3,382
  • 3
  • 25
  • 32
  • using screenorientation:"lock" in the manifest should fix this issue. https://stackoverflow.com/a/73893655/5437789 – TwiXter Sep 29 '22 at 10:08
0

In the manifest file you add following code:

android:screenOrientation="fullSensor"

and XML file create under layout-land folder

iknow
  • 8,358
  • 12
  • 41
  • 68
Soumen Das
  • 1,292
  • 17
  • 12
0

I added this code part inside toMainActivity.java file. Its worked for my case.

 @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            handleOrientationConfiguration();
        }

        private void handleOrientationConfiguration() {

            if (isTablet()) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            }
        }

        private boolean isTablet() {
            Configuration configuration = this.getContext().getResources()
                    .getConfiguration();/*from   www .j ava  2  s. c  o  m*/
            return (configuration.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
        }
ikbalkazanc
  • 161
  • 1
  • 8
  • If you just need that, then you should use android:screenOrientation="nosensor" in your manifest... for all your activities this is what it does. https://stackoverflow.com/a/73893655/5437789 – TwiXter Sep 29 '22 at 10:11
  • actually that code provides to start landscape for tablet and portrait for mobile. when i use android:screen Orientation="no sensor", maybe app can start as portrait screen on tablet. is't right? – ikbalkazanc Oct 06 '22 at 22:32
  • Normally no, it uses the **"natural"** device orientation. Natural orientation for tablet is Landscape while for Phone it's Portrait. Your code is fine, but you should put **android:screenOrientation="locked"** in your manifest's activities, otherwhise on phones for example if you are landscape oriented, then your activity will be shown first in landscape and then restart to be shown in portrait when your code is executed. – TwiXter Oct 07 '22 at 08:04
  • Sorry unable to edit my comment anymore: when you use **"locked"**, then the previous activity orientation is kept for your new activity until you may change it by calling your code. – TwiXter Oct 07 '22 at 08:12
  • thanks for useful info. I will change code in next feature. after all these is unnecessary ^^ – ikbalkazanc Oct 07 '22 at 14:35
0

Suggested approach would be to not lock orientation for any window dimension, but you can achieve it by following the guide here.

In steps, first thing to do would be to unlock orientation on the manifest

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

Next, you can use Jetpack Window Manager to determine how much space the app has on screen:

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

and finally you lock the orientation when the space is smaller, usually on phones:

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