如何在运行时锁定方向

有没有在运行时锁定方向的方法?例如,我想允许用户锁定屏幕横向,如果用户当前在横向和切换菜单选项。

77590 次浏览
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Called on an activity, will lock it to landscape. Look for the other flags in the ActivityInfo class. You can lock it back to portrait or make it sensor/slider driven.

More info here: http://www.devx.com/wireless/Article/40792

I seemed to had have a similar case. I wanted to support any orientation, but I needed to stay in the current orientation after a certain point in the workflow. My solution was:

At entry of the protected workflow:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

At exit of the protected workflow:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

Be careful of the difference between what getConfiguration returns and what setRequestedOrientation wants - they are both int, but they are coming from different constant definitions.

Here's how to lock the current orientation, while allowing 180 degree flips

int currentOrientation = getResources().getConfiguration().orientation;
if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}

This works on devices with reverse portrait and reverse landscape.

Lock orientation:

    int orientation = getActivity().getRequestedOrientation();
int rotation = ((WindowManager) getActivity().getSystemService(
Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
switch (rotation) {
case Surface.ROTATION_0:
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
case Surface.ROTATION_90:
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
case Surface.ROTATION_180:
orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
break;
default:
orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
break;
}


getActivity().setRequestedOrientation(orientation);

Unlock orientation:

   getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

Alternative to @pstoppani answer with support for tablets (As with @pstoppani answer, this will only work on devices >2.2)
-Tested on Samsung Galaxy SIII and Samsung Galaxy Tab 10.1

public static void lockOrientation(Activity activity) {
Display display = ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int rotation = display.getRotation();
int tempOrientation = activity.getResources().getConfiguration().orientation;
int orientation = 0;
switch(tempOrientation)
{
case Configuration.ORIENTATION_LANDSCAPE:
if(rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90)
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
else
orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
break;
case Configuration.ORIENTATION_PORTRAIT:
if(rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270)
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
else
orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
}
activity.setRequestedOrientation(orientation);
}

Here is my code, you could lock with one of these methods your screen and once finished the task unlock it with unlockOrientation:

/** Static methods related to device orientation. */
public class OrientationUtils {
private OrientationUtils() {}


/** Locks the device window in landscape mode. */
public static void lockOrientationLandscape(Activity activity) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}


/** Locks the device window in portrait mode. */
public static void lockOrientationPortrait(Activity activity) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}


/** Locks the device window in actual screen mode. */
public static void lockOrientation(Activity activity) {
final int orientation = activity.getResources().getConfiguration().orientation;
final int rotation = ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();


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


// Build.VERSION.SDK_INT <= Build.VERSION_CODES.FROYO
if (!BuildVersionUtils.hasGingerbread()) {
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);
}
}
}


/** Unlocks the device window in user defined screen mode. */
public static void unlockOrientation(Activity activity) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
}


}

Here is the Xamarin conversion of @pstoppani 's answer above.

NOTE: this is for a Fragment, replace Activity. with this. if used within an activity.

public void LockRotation()
{
ScreenOrientation orientation;


var surfaceOrientation = Activity.WindowManager.DefaultDisplay.Rotation;


switch (surfaceOrientation) {
case SurfaceOrientation.Rotation0:
orientation = ScreenOrientation.Portrait;
break;
case SurfaceOrientation.Rotation90:
orientation = ScreenOrientation.Landscape;
break;
case SurfaceOrientation.Rotation180:
orientation = ScreenOrientation.ReversePortrait;
break;
default:
orientation = ScreenOrientation.ReverseLandscape;
break;
}


Activity.RequestedOrientation = orientation;
}


public void UnlockRotation()
{
Activity.RequestedOrientation = ScreenOrientation.Unspecified;
}

This is untested as went with a different approach before used it, but may be of use.