Detect Android orientation: landscape-Left v. landscape-Right - android

How can I detect which one of 4 sides of the phone is up.
I can detect portrait/landscape mode, but how do I tell landscape-turned-on-left-side from landscape-turned-on-right-side?
Basically I want to make a nice transition animation when user turns phone. You know, like in iPhone's Safari: a swift 400ms rotation from the previous layout to the new.

Use an OrientationEventListener:
mOrientationEventListener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL)
{
#Override
public void onOrientationChanged(int orientation)
{
mDeviceOrientation = orientation;
}
};
if(mOrientationEventListener.canDetectOrientation())
{
mOrientationEventListener.enable();
}
mDeviceOrientation should then be an integer telling you the angle your device is rotated to, if you do some clever rounding you should be able to see which of the four orientations it is in:
// Divide by 90 into an int to round, then multiply out to one of 5 positions, either 0,90,180,270,360.
int orientation = 90*Math.round(mDeviceOrientation / 90);
// Convert 360 to 0
if(orientation == 360)
{
orientation = 0;
}
Enjoy!

Just came across :) 2.2+ put xml code to ur res/values(false) and res/values-xlarge(true)
<resources>
<bool name="isTablet">false</bool>
private void getScreenRotationOnPhone() {
final Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
switch (display.getRotation()) {
case Surface.ROTATION_0:
System.out.println("SCREEN_ORIENTATION_PORTRAIT");
break;
case Surface.ROTATION_90:
System.out.println("SCREEN_ORIENTATION_LANDSCAPE");
break;
case Surface.ROTATION_180:
System.out.println("SCREEN_ORIENTATION_REVERSE_PORTRAIT");
break;
case Surface.ROTATION_270:
System.out.println("SCREEN_ORIENTATION_REVERSE_LANDSCAPE");
break;
}
}
private void getScreenRotationOnTablet() {
final Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
switch (display.getRotation()) {
case Surface.ROTATION_0:
System.out.println("SCREEN_ORIENTATION_LANDSCAPE");
break;
case Surface.ROTATION_90:
System.out.println("SCREEN_ORIENTATION_REVERSE_PORTRAIT");
break;
case Surface.ROTATION_180:
System.out.println("SCREEN_ORIENTATION_REVERSE_LANDSCAPE");
break;
case Surface.ROTATION_270:
System.out.println("SCREEN_ORIENTATION_PORTRAIT");
break;
}
}
private boolean isTabletDevice(){
boolean tabletSize = getResources().getBoolean(R.bool.isTablet);
if (tabletSize) {
return true;
} else {
return false;
}
}

It seems like you should be able to tell from the screenOrientation, gotten via getRequestedOrientation

I was able to get landscape left vs right events using this code:
object : OrientationEventListener(this, SENSOR_DELAY_NORMAL) {
override fun onOrientationChanged(orientation: Int) {
afterGlobalLayout {
logInfoToast(if (screenRotation == LandscapeLeft)
"LandscapeLeft" else "LandscapeRight")
}
}
}.enable()
afterGlobalLayout uses viewTreeObserver.addOnGlobalLayoutListener
and screenRotation is calculated by Piotr Ślesarew code.

Related

Camera orientation can not change with display in Android?

I know there are already questions like this, but none solved it. I took some help and figured out basic code that I need to change the camera with respect to the display.
cameraInfo=new Camera.CameraInfo();
camera.getCameraInfo(camId,cameraInfo);
int angle=0;
int rotation = getActivity().getWindowManager().getDefaultDisplay()
.getRotation();
switch(rotation)
{
case Surface.ROTATION_0:
parameters.setPreviewSize(s.width, s.height);
Log.i(TAGR, "THE ROATTION IS 0");
camera.setDisplayOrientation(90);
break;
case Surface.ROTATION_90:
parameters.setPreviewSize(s.width, s.height);
Log.i(TAGR, "THE ROATTION IS 90");
camera.setDisplayOrientation(0);
break;
case Surface.ROTATION_180:
parameters.setPreviewSize(s.width, s.height);
Log.i(TAGR, "THE ROATTION IS 180");
camera.setDisplayOrientation(0);
break;
case Surface.ROTATION_270:
parameters.setPreviewSize(s.width, s.height);
Log.i(TAGR, "THE ROATTION IS 270");
camera.setDisplayOrientation(180);
break;
default:
camera.setDisplayOrientation(0);
break;
}
}
However, I am unable to get the correct display preview with respect to the rotation of the device. I have tried several different combination of angles. However, none gave me the correct output. I am attaching the images of my preview. Please explain the solution to the problem. Moreover, I want to know what position of my device corresponds to angles 0,90,180, and 270. In other words, is 0 corresponds to portrait or landscape orientation?.
Images :
The landscape is inverted in this one. I tried setting the rotation by 180 when ROTATION_180. Doing so did not work out, as the other orientation (in landscape) became inverted
The upside down orientation does not do anything. The desired result is to bring the click button down with correct preview. I don't have any idea why this is not working. I have tried several values in each rotation, but none solved this issue.
I am a beginner, so please explain in detail. Thanks.
You should check CameraInfo.orientation for the device. Note that this property gives rotation from the natural display orientation, given for the device by Display.getRotation().
If your custom camera app uses android.hardware.camera2 API, this compensation will happen automatically.
If your custom camera activity does not lock the screen orientation, then it will be subject to "reverse landscape" glitch, and needs special treatment which involves OrientationEventListener.
You can rotate the image like this before preview:
public static Bitmap rotateImage(Bitmap bitmapSrc) {
Matrix matrix = new Matrix();
matrix.postRotate(previewRotation);
return Bitmap.createBitmap(bitmapSrc, 0, 0,
bitmapSrc.getWidth(), bitmapSrc.getHeight(), matrix, true);
}
"previewRotation" can be got from:
private static void setCameraDisplayOrientation(Context mContext, android.hardware.Camera.CameraInfo info) {
int rotation = ((CameraActivity) mContext).getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
previewRotation = (info.orientation + degrees) % 360;
previewRotation = (360 - previewRotation) % 360; // compensate the mirror
} else { // back-facing
previewRotation = (info.orientation - degrees + 360) % 360;
}
mCameraInstance.setDisplayOrientation(previewRotation);
}

Android: how to ignore rotation around single axis?

I'm developing application, where activity starts after phone's rotation. When you rotate phone backward that activity have to finish. Is it possible to ignore rotation around other axes?
You can check which way the phone is held with this:
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int rotation = display.getRotation();
Then you can check the orientation like this:
switch (rotation)
{
case Surface.ROTATION_90:
...
break;
case Surface.ROTATION_180:
...
break;
case Surface.ROTATION_270:
...
break;
default:
...
break;
}
(Note that for pre-API 8 versions you'd need to use display.getOrientation() instead of display.getRotation())

locking screen orientation to its (natural) default orientation

I wanted to lock orientation of screen to its default orinetation. I have having problem on achieving this. Initially i locked screen to portrait from manifest. It works fine for portrait defaultdevices. But many tablets have landscape as default so in these devices locking to portrait is not suitable, i want to detect this default orientation and lock it. I mean if landscape is default orientation i want to lock the orientation to landscape and if its portrait then lock it to port. How to do this. I am stuck in this part. I don't want to support both orientation(auto). Please help
Thanks.
There is a default orientation for different devices for example the default orientation on a galaxy 10 tablet is different from a nexus 7 tablet. when you get the orientation of the display you get the following values :
said so, what you have to do in your locking method is the following:
public void mLockScreenRotation(FA_Padre actividad){
int buildVersionSDK = Build.VERSION.SDK_INT;
Display display = ((WindowManager) actividad.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int orientation=0;
if(buildVersionSDK >= 8){
orientation=display.getRotation();
}
/****************Phone*************************************/
if(buildVersionSDK < 8){// older Android versions with only two orientations
switch (actividad.getResources().getConfiguration().orientation){
case Configuration.ORIENTATION_PORTRAIT:
actividad.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
case Configuration.ORIENTATION_LANDSCAPE:
actividad.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
}
}else if((buildVersionSDK > 7 ) && (!GlobalInfo.isTablet())){// Newer Android phones with more than two orientations
switch(orientation){
case Surface.ROTATION_0:
actividad.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
case Surface.ROTATION_90:
actividad.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
case Surface.ROTATION_180:
actividad.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
case Surface.ROTATION_270:
actividad.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
break;
}
/****************TABLET*************************************/
}else{
int width = 0;
int height = 0;
switch(orientation){
/*If the default orientation of the device is landscape Rotation_0 and rotation_180 will be the case if the device is being held in landscape. if the default orientation of the device is portrait rotation_0 or 180 will only be the case if the device is in portrait mode*/
case Surface.ROTATION_0:
case Surface.ROTATION_180:
width = display.getWidth();
height = display.getHeight();
break;
/*the opposite in here*/
case Surface.ROTATION_90: //
case Surface.ROTATION_270:
width = display.getHeight();
height = display.getWidth();
break;
default:
break;
}
if(width > height){//Default ORIENTATION = LANDSCAPE, lock the screen in the current orientation
switch(orientation){
case Surface.ROTATION_0:
actividad.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
case Surface.ROTATION_90:
actividad.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
break;
case Surface.ROTATION_180:
actividad.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
break;
case Surface.ROTATION_270:
actividad.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
}
} else {//Default ORIENTATION = PORTRAIT, lock the screen in the current orientation
switch(orientation){
case Surface.ROTATION_0:
actividad.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
case Surface.ROTATION_90:
actividad.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
case Surface.ROTATION_180:
actividad.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
break;
case Surface.ROTATION_270:
actividad.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
break;
}
}
}
}
try this one lock screen to default
Lockorientationactivity :
public class Lockorientationactivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int getConf=this.getResources().getConfiguration().orientation;
if(getConf==Configuration.ORIENTATION_PORTRAIT)
{
this.setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Toast.makeText(getBaseContext(), "ORIENTATION_PORTRAIT", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getBaseContext(), "ORIENTATION_LANDSCAPE", Toast.LENGTH_SHORT).show();
this.setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
setContentView(R.layout.main);
}
}
But you must set android:configChanges="orientation" for activity.
To lock the screen by code you have to use the actual rotation of the screen (0, 90, 180, 270) and you have to know the natural position of it, in a smartphone the natural position will be portrait and in a tablet, it will be landscape.
Here's the code (lock and unlock methods), it has been tested in some devices (smartphones and tablets) and it works great.
public static void lockScreenOrientation(Activity activity)
{
WindowManager windowManager = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
Configuration configuration = activity.getResources().getConfiguration();
int rotation = windowManager.getDefaultDisplay().getRotation();
// Search for the natural position of the device
if(configuration.orientation == Configuration.ORIENTATION_LANDSCAPE &&
(rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) ||
configuration.orientation == Configuration.ORIENTATION_PORTRAIT &&
(rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270))
{
// Natural position is Landscape
switch (rotation)
{
case Surface.ROTATION_0:
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
case Surface.ROTATION_90:
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
break;
case Surface.ROTATION_180:
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
break;
case Surface.ROTATION_270:
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
}
}
else
{
// Natural position is Portrait
switch (rotation)
{
case Surface.ROTATION_0:
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
case Surface.ROTATION_90:
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
case Surface.ROTATION_180:
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
break;
case Surface.ROTATION_270:
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
break;
}
}
}
public static void unlockScreenOrientation(Activity activity)
{
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}

android universal landscape check

OK I have an app the uses the magneometer to display a graphic that rotates with the phone (basically a compass).
I have a check that subtracts 90 degrees if it is in landscape mode, but this only works if it is in the default landscape mode. With 2.1 we now have a universal landscape that you can rotate both ways so I now don't know how to figure out which landscape mode it is in.
Here is my code:
int test = getResources().getConfiguration().orientation;
if(Configuration.ORIENTATION_LANDSCAPE == test) {
rotation = -90f;
}
else {
rotation = 0f;
}
canvas.rotate((float) (-Math.toDegrees(mOrientation[0]) + rotation ));
Any suggestions on how to tell which landscape mode the phone is in?
Please see this: http://android-developers.blogspot.com/2010/09/one-screen-turn-deserves-another.html
private static final int ORIENTATION_90 = 1;
private static final int ORIENTATION_0 = 0;
private static final int ORIENTATION_180 = 2;
private static final int ORIENTATION_270 = 3;
switch (orientation)
{
default:
case ORIENTATION_0: // Portrait
//dostuff
break;
case ORIENTATION_90: // Landscape left
//do stuff
break;
case ORIENTATION_180: // Upside down.
//do stuff
break;
case ORIENTATION_270: // Landscape right
//do stuff
break;
}

Android: Temporarily disable orientation changes in an Activity

My main activity has some code that makes some database changes that should not be interrupted. I'm doing the heavy lifting in another thread, and using a progress dialog which I set as non-cancellable. However, I noticed that if I rotate my phone it restarts the activity which is REALLY bad for the process that was running, and I get a Force Close.
What I want to do is programatically disable screen orientation changes until my process completes, at which time orientation changes are enabled.
As explained by Chris in his self-answer, calling
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
and then
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
really works like charm... on real devices !
Don't think that it's broken when testing on the emulator, the ctrl+F11 shortcut ALWAYS change the screen orientation, without emulating sensors moves.
EDIT: this was not the best possible answer. As explained in the comments, there are issues with this method. The real answer is here.
None of the other answers did the trick perfectly for me, but here's what I found that does.
Lock orientation to current...
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
When changing orientation should be allowed again, set back to default...
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
Here is a more complete and up to date solution that works for API 8+, works for reverse portrait and landscape, and works on a Galaxy tab where the "natural" orientation is landscape (call activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) to unlock the orientation):
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
public static void lockActivityOrientation(Activity activity) {
Display display = activity.getWindowManager().getDefaultDisplay();
int rotation = display.getRotation();
int height;
int width;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) {
height = display.getHeight();
width = display.getWidth();
} else {
Point size = new Point();
display.getSize(size);
height = size.y;
width = size.x;
}
switch (rotation) {
case Surface.ROTATION_90:
if (width > height)
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
else
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
break;
case Surface.ROTATION_180:
if (height > width)
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
else
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
break;
case Surface.ROTATION_270:
if (width > height)
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
else
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
default :
if (height > width)
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
else
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
Use setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); for
locking current orientation whether it be landscape or portrait.
Use setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); for unlocking orientation.
In order to manage also the reverse orientation modes, I have used that code to fix the activity orientation:
int rotation = getWindowManager().getDefaultDisplay().getRotation();
switch(rotation) {
case Surface.ROTATION_180:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
break;
case Surface.ROTATION_270:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
break;
case Surface.ROTATION_0:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
case Surface.ROTATION_90:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
}
And to allow again the orientation:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
I found the answer. To do this, in an Activity you can call setRequestedOrientation(int) with one of the values specified here: http://developer.android.com/reference/android/R.attr.html#screenOrientation
Before I kicked off my thread I called setRequestedOrientation(OFF) (OFF = nosensor) and when the thread was done I called setRequestedOrientation(ON) (ON = sensor). Works like a charm.
Thanks all. I modified Pilot_51's solution, to make sure I restored to the previous state. I also threw in a change to support non-landscape and non-portrait screens (but haven't tested it on such a screen).
prevOrientation = getRequestedOrientation();
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
}
Then to restore it
setRequestedOrientation(prevOrientation);
protected void setLockScreenOrientation(boolean lock) {
if (Build.VERSION.SDK_INT >= 18) {
setRequestedOrientation(lock?ActivityInfo.SCREEN_ORIENTATION_LOCKED:ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
return;
}
if (lock) {
switch (getWindowManager().getDefaultDisplay().getRotation()) {
case 0: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; // value 1
case 2: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); break; // value 9
case 1: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); break; // value 0
case 3: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; // value 8
}
} else
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); // value 10
}
Here is a solution which works every time and preserves current orientation (using Activity.Info.SCREEN_ORIENTATION_PORTRAIT sets to 0° for instance, but user can have a 180° orientation as current one).
// Scope: Activity
private void _lockOrientation() {
if (super.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT);
} else {
super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
}
}
private void _unlockOrientation() {
super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
use ActivityInfo.SCREEN_ORIENTATION_USER if you want to rotate screen only if its enabled on device.
This works prefect for me. It solves problem with different "natural orientation" of tablet/phone ;)
int rotation = getWindowManager().getDefaultDisplay().getRotation();
Configuration config = getResources().getConfiguration();
int naturalOrientation;
if (((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) &&
config.orientation == Configuration.ORIENTATION_LANDSCAPE)
|| ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) &&
config.orientation == Configuration.ORIENTATION_PORTRAIT)) {
naturalOrientation = Configuration.ORIENTATION_LANDSCAPE;
} else {
naturalOrientation = Configuration.ORIENTATION_PORTRAIT;
}
// because getRotation() gives "rotation from natural orientation" of device (different on phone and tablet)
// we need to update rotation variable if natural orienation isn't 0 (mainly tablets)
if (naturalOrientation == Configuration.ORIENTATION_LANDSCAPE)
rotation = ++rotation % 4;
switch (rotation) {
case Surface.ROTATION_0: //0
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
case Surface.ROTATION_90: //1
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
case Surface.ROTATION_180: //2
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
break;
case Surface.ROTATION_270: //3
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
break;
}
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
I have come up with a solution which depends on the display rotation and then decides the orientation of the device. From knowing the orientation we can lock the orientation and release it later when needed. This solution also can determine if the device in reverse landscape mode.
private void lockOrientation(){
switch (((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation()) {
// Portrait
case Surface.ROTATION_0:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
//Landscape
case Surface.ROTATION_90:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
// Reversed landscape
case Surface.ROTATION_270:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
break;
}
}
Then later if we need to release the orientation we can call this method:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
I think this code is easier to read.
private void keepOrientation() {
int orientation = getResources().getConfiguration().orientation;
int rotation = getWindowManager().getDefaultDisplay().getRotation();
switch (rotation) {
case Surface.ROTATION_0:
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
break;
case Surface.ROTATION_90:
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
break;
case Surface.ROTATION_180:
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
}
break;
default:
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
}
}
}
I have found a combination of existing rotation/orientation values are needed to cover the four possibilities; there's the portrait/landscape values and the natural orientation of the device. Let's say the devices' natural orientation will have a rotation value of 0 degrees when the screen is in it's "natural" portrait or landscape orientation. Similarly, there will be a rotation value of 90 degrees when it's in landscape or portrait (notice it's opposite of the orientation # 0 degrees). So the rotation values that are not 0 or 90 degrees will imply "Reverse" orientation. Ok, here's some code:
public enum eScreenOrientation
{
PORTRAIT (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT),
LANDSCAPE (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE),
PORTRAIT_REVERSE (ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT),
LANDSCAPE_REVERSE (ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE),
UNSPECIFIED_ORIENTATION (ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
public final int activityInfoValue;
eScreenOrientation ( int orientation )
{
activityInfoValue = orientation;
}
}
public eScreenOrientation currentScreenOrientation ( )
{
final int rotation = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
final int orientation = getResources().getConfiguration().orientation;
switch ( orientation )
{
case Configuration.ORIENTATION_PORTRAIT:
if ( rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90 )
return eScreenOrientation.PORTRAIT;
else
return eScreenOrientation.PORTRAIT_REVERSE;
case Configuration.ORIENTATION_LANDSCAPE:
if ( rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90 )
return eScreenOrientation.LANDSCAPE;
else
return eScreenOrientation.LANDSCAPE_REVERSE;
default:
return eScreenOrientation.UNSPECIFIED_ORIENTATION;
}
}
public void lockScreenOrientation ( )
throws UnsupportedDisplayException
{
eScreenOrientation currentOrientation = currentScreenOrientation( );
if ( currentOrientation == eScreenOrientation.UNSPECIFIED_ORIENTATION )
throw new UnsupportedDisplayException("Unable to lock screen - unspecified orientation");
else
setRequestedOrientation( currentOrientation.activityInfoValue );
}
public void unlockScreenOrientation ( )
{
setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED );
}
I didn't like most of the answers here, since in the unlock they set it to UNSPECIFIED as opposed to the previous state. ProjectJourneyman did take it into account, which was great, but I preferred the locking code by Roy. So, my recommendation would be a mix of the two:
private int prevOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
private void unlockOrientation() {
setRequestedOrientation(prevOrientation);
}
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
private void lockOrientation() {
prevOrientation = getRequestedOrientation();
Display display = getWindowManager().getDefaultDisplay();
int rotation = display.getRotation();
int height;
int width;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) {
height = display.getHeight();
width = display.getWidth();
} else {
Point size = new Point();
display.getSize(size);
height = size.y;
width = size.x;
}
switch (rotation) {
case Surface.ROTATION_90:
if (width > height)
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
else
setRequestedOrientation(9/* reversePortait */);
break;
case Surface.ROTATION_180:
if (height > width)
setRequestedOrientation(9/* reversePortait */);
else
setRequestedOrientation(8/* reverseLandscape */);
break;
case Surface.ROTATION_270:
if (width > height)
setRequestedOrientation(8/* reverseLandscape */);
else
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
default :
if (height > width)
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
else
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
You can use
public void swapOrientaionLockState(){
try{
if (Settings.System.getInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 1) {
Display defaultDisplay = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
Settings.System.putInt(mContext.getContentResolver(), Settings.System.USER_ROTATION, defaultDisplay.getRotation());
Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0);
} else {
Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 1);
}
Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, !orientationIsLocked() ? 1 : 0);
} catch (Settings.SettingNotFoundException e){
e.printStackTrace();
}
}
public boolean orientationIsLocked(){
if(canModifiSetting(mContext)){
try {
return Settings.System.getInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 0;
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
}
return false;
}
public static boolean canModifiSetting(Context context){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return Settings.System.canWrite(context);
} else {
return true;
}
}
use that line of code
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
in ur activity oncreate method

Categories

Resources