I have an app for Android, I want to force tablet (sw600dp and higher) to display in Landscape mode and phone to display in Portrait mode, so I handle in onCreate of my BaseActivity class
boolean isTablet= getResources().getBoolean(R.bool.isTablet);
if (isTablet) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
And the way I put "isTablet" in bools.xml file and put it in
values folder for phone
<resources>
<bool name="isTablet">false</bool>
</resources>
values-sw600dp for tablet
<resources>
<bool name="isTablet">true</bool>
</resources>
And in AndroidManifest I use
android:screenOrientation="nosensor"
just ensure to disable device orientation's sensor.
It seems to be my approach works fine (Landscape for tablet and Portrait for phone) BUT the problem happens when I run my app on Nexus 7 - my activities create twice. These steps are:
I find that the problem is the method setRequestedOrientation() (with 2 steps above). So I don't want to call that method anymore. I try to set orientation in AndroidManifest like:
android:screenOrientation="@integer/orientation"
Because: SCREEN_ORIENTATION_LANDSCAPE = 0 SCREEN_ORIENTATION_PORTRAIT = 1
I declare "orientation" in integers.xml file and put it in
values folder for phone
<resources>
<integer name="orientation">1</integer>
</resources>
values-sw600dp for tablet
<resources>
<integer name="orientation">0</integer>
</resources>
Again, my approach tends to works fine BUT I find that AndroidMenifest just understands "orientation" in values folder, not in values-sw600dp folder. I don't want my activities to call 2 times. Did you have a problem like that?? Could you solve it? Thanks.
When you rotate your device and the screen changes orientation, Android usually destroys your application's existing Activities and Fragments and recreates them . Android does this so that your application can reload resources based on the new configuration.
The screenOrientation is the attribute of activity element. The orientation of android activity can be portrait, landscape, sensor, unspecified etc. You need to define it in the AndroidManifest.
Android Settings Start by going to Settings => Display and locate the “Device rotation” setting. On my personal cell phone, tapping this will reveal two options: “Rotate the contents of the screen,” and “Stay in portrait view.”
From the docs setRequestedOrientation(int):
If the activity is currently in the foreground or otherwise impacting the screen orientation, the screen will immediately be changed (possibly causing the activity to be restarted)
It's not being re-created, it's just being restarted to account for the change of orientation.
So just move the functionality that shouldn't be run twice to onCreate
and you're done.
Simas answer is sort of correct, let me explain.
Let's say you are holding your device in a portrait position, you then start your Activity
and in onCreate
you call the following:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
Then, you are basically telling the device it should rotate (since you are holding the device in portrait mode).
But if you hold the device in landscape before launching your Activity
and call the same as above, your device doesn't need to rotate since it is already in landscape mode.
As we all know, rotating your device causes the Activity
to be destroyed and created again. The same goes for when calling setRequestedOrientation
(if the device is currently not in the requested position).
So.. How to deal with it.
setRequestedOrientation
. Instead handle your rotation by using
onSaveInstanceState
to store your values and
onRestoreInstanceState
to restore the values that were stored in
bundle, etc..In my case, because of the design of my application, I had to use
setRequestedOrientation
because I'm rotating the device based on the
selected video dimensions.
Here is how I accomplished this.
Since I want to handle rotation myself, I first had to add the following in my manifest:
android:configChanges="orientation|screenSize|keyboardHidden"
By doing this you are overriding configuration changes. As
mentioned in the docs - This technique should be considered a last
resort
Next, I created a different layout for when I want to rotate the device to landscape and called the following:
private void rotateScreen(Uri vidUri) {
try {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
Bitmap bmp;
retriever.setDataSource(this, vidUri);
bmp = retriever.getFrameAtTime();
videoWidth = bmp.getWidth();
videoHeight = bmp.getHeight();
if (videoWidth > videoHeight) {
setContentView(R.layout.activity_video_player_land);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
if (videoWidth < videoHeight) {
setContentView(R.layout.activity_video_player);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
} catch (RuntimeException ex) {
Log.e("MediaMetadataRetriever", "- Failed to rotate the screen");
}
}
Since everything in my portrait layout is in my landscape layout, I do not have to worry about resources not being found.
The solution I went with will not work for all applications (if you have different resources for different orientations) but in my case, I use all the same resource, resized and moved around to better fit the landscape view.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With