Is there a reliable way to lock screen orientation on all Android devices? The code below works for my Nexus S and other phones, but for some reason ROTATION_90 corresponds to SCREEN_ORIENTATION_REVERSE_PORTRAIT on the Xoom.
Is there any way to reliably map rotation to orientation?
private void lockScreenOrientation() {
if (!mScreenOrientationLocked) {
final int orientation = getResources().getConfiguration().orientation;
final int rotation = getWindowManager().getDefaultDisplay().getOrientation();
if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) {
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
els开发者_开发知识库e if (rotation == Surface.ROTATION_180 || rotation == Surface.ROTATION_270) {
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
}
else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
}
}
mScreenOrientationLocked = true;
}
}
private void unlockScreenOrientation() {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
mScreenOrientationLocked = false;
}
EDIT: This code is meant to get the current orientation and lock it. The orientation is locked temporarily, and then released to the user.
Here is my solution it works on phones and tablets in any Android SDK.
switch (getResources().getConfiguration().orientation){
case Configuration.ORIENTATION_PORTRAIT:
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.FROYO){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
int rotation = getWindowManager().getDefaultDisplay().getRotation();
if(rotation == android.view.Surface.ROTATION_90|| rotation == android.view.Surface.ROTATION_180){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
break;
case Configuration.ORIENTATION_LANDSCAPE:
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.FROYO){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else {
int rotation = getWindowManager().getDefaultDisplay().getRotation();
if(rotation == android.view.Surface.ROTATION_0 || rotation == android.view.Surface.ROTATION_90){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
}
}
break;
}
I modified diyism's answers slightly to compensate for the fact that you can't use reverse_landscape and reverse_portrait modes before version 2.3
private static void disableRotation(Activity activity)
{
final int orientation = activity.getResources().getConfiguration().orientation;
final int rotation = activity.getWindowManager().getDefaultDisplay().getOrientation();
// Copied from Android docs, since we don't have these values in Froyo 2.2
int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8;
int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9;
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.FROYO)
{
SCREEN_ORIENTATION_REVERSE_LANDSCAPE = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
SCREEN_ORIENTATION_REVERSE_PORTRAIT = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
}
if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90)
{
if (orientation == Configuration.ORIENTATION_PORTRAIT)
{
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
else if (orientation == Configuration.ORIENTATION_LANDSCAPE)
{
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
else if (rotation == Surface.ROTATION_180 || rotation == Surface.ROTATION_270)
{
if (orientation == Configuration.ORIENTATION_PORTRAIT)
{
activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_PORTRAIT);
}
else if (orientation == Configuration.ORIENTATION_LANDSCAPE)
{
activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
}
}
}
private static void enableRotation(Activity activity)
{
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
for a temporarily screen lock you can easily use:
//developing for android tablets **<uses-sdk android:minSdkVersion="12" />**
//works perfectly... **WATCH OUT**: look portrait to reverse-portrait on api level 13 :)
currentActivity.setRequestedOrientation(currentActivity.getResources().getConfiguration().orientation);
//to re-enable sensor, just do:
currentActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
used it for a temp screen lock during showing dialog and doing important background work..
be sure that currentActivity is valid at the time you try to access it, otherwise it wont work :)
good luck :)
// Works on all devices. The other solution only works on 1/2 of the devices.
// Lock orientation
int rotation = getWindowManager().getDefaultDisplay().getRotation();
lockOrientation(rotation, Surface.ROTATION_270);
// Ensure that the rotation hasn't changed
if (getWindowManager().getDefaultDisplay().getRotation() != rotation) {
lockOrientation(rotation, Surface.ROTATION_90);
}
// ...
private void lockOrientation(int originalRotation, int naturalOppositeRotation) {
int orientation = getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
// Are we reverse?
if (originalRotation == Surface.ROTATION_0 || originalRotation == naturalOppositeRotation) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
setReversePortrait();
}
} else {
// Are we reverse?
if (originalRotation == Surface.ROTATION_0 || originalRotation == naturalOppositeRotation) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else {
setReverseLandscape();
}
}
}
@SuppressLint("InlinedApi")
private void setReversePortrait() {
if (Build.VERSION.SDK_INT >= 9) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
@SuppressLint("InlinedApi")
private void setReverseLandscape() {
if (Build.VERSION.SDK_INT >= 9) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
Use: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR)
because Orientation is determined by a physical orientation sensor: the display will rotate based on how the user moves the device. This allows any of the 4 possible rotations, regardless of what the device will normally do (for example some devices won't normally use 180 degree rotation). And your code should work on Xoom too ...
This solution only builds on others. It is a different way to handle the problem enl8enmentnow tackled: on some devices landscape is ROTATION_90
, but on (a few) others it is ROTATION_270
. When I tried something like enl8enmentnow's solution on a Kindle Fire HD 7", it made the screen rotate upside down, then immediately back. I have seen no other ideas than to hard-code which devices consider landscape to be 270, so here is that hard-coded solution:
public static void unlockOrientation() {
activity.setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
public static void lockOrientation() {
if (Build.VERSION.SDK_INT < 18) {
activity.setRequestedOrientation(getOrientation());
} else {
activity.setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_LOCKED);
}
}
private static int getOrientation() {
int port = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
int revP = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
int land = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
int revL = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
if (Build.VERSION.SDK_INT < 9) {
revL = land;
revP = port;
} else if (isLandscape270()) {
land = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
revL = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
}
Display display = activity.getWindowManager().getDefaultDisplay();
boolean wide = activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
switch (display.getRotation()) {
case Surface.ROTATION_0:
return wide ? land : port;
case Surface.ROTATION_90:
return wide ? land : revP;
case Surface.ROTATION_180:
return wide ? revL : revP;
case Surface.ROTATION_270:
return wide ? revL : port;
default:
throw new AssertionError();
}
}
private static boolean isLandscape270() {
return android.os.Build.MANUFACTURER.equals("Amazon")
&& !(android.os.Build.MODEL.equals("KFOT") || android.os.Build.MODEL.equals("Kindle Fire"));
}
isLandscape270()
detects whether the device is a 2nd generation Kindle or later (refer to this link, getting the MODEL
from this link). I do not know if other devices should also be included; please comment if you know of any.
Also, on APIs >= 18 this simply uses setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED)
. I have only tested that on emulators; please comment if it has problems on real devices.
You can declare an Activity as being only landscape or portrait in your AndroidManifest.xml. Just add the screenOrientation attribute to the activity element:
http://developer.android.com/guide/topics/manifest/activity-element.html
My solution:
int orientation=act.getResources().getConfiguration().orientation;
int rotation=act.getWindowManager().getDefaultDisplay().getOrientation();
if (orientation==Configuration.ORIENTATION_PORTRAIT)
{if (rotation==Surface.ROTATION_0 || rotation==Surface.ROTATION_270) //0 for phone, 270 for tablet
{act.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
else
{act.setRequestedOrientation(9);//instead of SCREEN_ORIENTATION_REVERSE_PORTRAIT when <= android 2.2
}
}
else
{if (rotation==Surface.ROTATION_90 || rotation==Surface.ROTATION_0) //90 for phone, 0 for tablet
{act.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
else
{act.setRequestedOrientation(8);//instead of SCREEN_ORIENTATION_REVERSE_LANDSCAPE when <= android 2.2
}
}
精彩评论