如何在Android上检查设备自然(默认)方向(例如,获取横向,例如,Motorola Charm或Flipout)

时间:2010-12-29 11:26:10

标签: android

我有一个显示相机预览的活动,因此需要将其设置为仅景观。在底部(无论设备旋转)我想显示文本视图。我正在使用OrientationEventListener,它从自然位置给出设备的方向。我可以实现一个在纵向默认设备上运行良好的解决方案,但是为了使它在横向默认设备上工作,我需要知道在这样的设备上运行。那么问题是如何检查它?

15 个答案:

答案 0 :(得分:73)

此方法有助于: -

public int getDeviceDefaultOrientation() {

    WindowManager windowManager =  (WindowManager) getSystemService(Context.WINDOW_SERVICE);

    Configuration config = getResources().getConfiguration();

    int rotation = windowManager.getDefaultDisplay().getRotation();

    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)) {
      return Configuration.ORIENTATION_LANDSCAPE;
    } else { 
      return Configuration.ORIENTATION_PORTRAIT;
    }
}

答案 1 :(得分:12)

嗯,你可以找出@Urboss所说的当前方向。你不能得到那种方式的布局(风景/肖像),所以你必须得到屏幕宽度/高度来检查当前是否(无论是否改变,但你已经检查过了;))位置是风景或肖像:

    DisplayMetrics dm = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(dm);
    wPix = dm.widthPixels;
    hPix = dm.heightPixels;

(因此,如果旋转为0并且您获得上面的metrix横向,则您的设备是默认横向。如果旋转是90度并且您是纵向,则默认也是横向,依此类推)

答案 2 :(得分:9)

经过几个小时的努力来解决这个问题。这是不可能的。但是,您可以做的最接近的事情是将方向设置为“NOSENSOR”

 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

这样做会将您的应用程序设置为设备的自然方向。此时,您可以使用DisplayMetrics类获取显示的高度和宽度,并计算您是横向还是纵向。然后你弄清楚它是风景还是肖像,然后你可以这样做

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_XXXXX);

XXXX是LANDSCAPE或PORTRAIT。

如果你有一个滑出式键盘,这样做可能不起作用。

答案 3 :(得分:7)

感谢diyism上面的优秀答案,我还添加了检查实际方向位置的逻辑(横向右侧,纵向,横向左侧,纵向翻转): enter image description here 这是代码:

@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
    //The coordinate-system is defined relative to the screen of the phone in its default orientation
    int orientation = 0;
    float roll=0;
    float pitch=0;
    switch (getWindowManager().getDefaultDisplay().getRotation())  {
        case Surface.ROTATION_0:
                 roll=event.values[2];
                 pitch=event.values[1];
            break;
            case Surface.ROTATION_90:
                 roll=event.values[1];
                 pitch=-event.values[2];
            break;
            case Surface.ROTATION_180:
                 roll=-event.values[2];
                 pitch=-event.values[1];
            break;
            case Surface.ROTATION_270:
                 roll=-event.values[1];
                 pitch=event.values[2];
            break;
           }

    if (pitch >= -45 && pitch < 45 && roll >= 45)
        orientation = 0;
    else if (pitch < -45 && roll >= -45 && roll < 45) 
        orientation = 1; 
    else if (pitch >= -45 && pitch < 45 && roll < -45) 
        orientation = 2;
    else if (pitch >= 45 && roll >= -45 && roll < 45 ) 
        orientation = 3;

    if (m_nOrientation != orientation) { //orientation changed event
        m_Inst.Debug(LOG_TAG,"onSensorChanged: orientation:" + orientation);
        m_nOrientation = orientation;
        // fire event for new notification, or update your interface here
    }
}

此代码也发布在此处:http://www.pocketmagic.net/?p=2847

答案 4 :(得分:6)

这是我的解决方案:

public class ActivityOrientationTest extends Activity {
private static final String TAG = "ActivityOrientationTest";
private int mNaturalOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
private TextView mTextView;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);        
    setContentView(R.layout.main);
    mTextView = (TextView)findViewById(R.id.text);
    setDefaultOrientation();        
}

private void setDefaultOrientation(){
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);

    Display display;         
    display = getWindow().getWindowManager().getDefaultDisplay();
    int rotation = display.getRotation();
    int width = 0;
    int height = 0;
    switch (rotation) {
    case Surface.ROTATION_0:
    case Surface.ROTATION_180:
        Log.i(TAG, "Rotation is: 0 or 180");
        width = display.getWidth();
        height = display.getHeight();
        break;
    case Surface.ROTATION_90:       
    case Surface.ROTATION_270:
        Log.i(TAG, "Rotation is: 90 or 270");
        width = display.getHeight();
        height = display.getWidth();
        break;
    default:
        break;
    }

    if(width > height){
        Log.i(TAG, "Natural Orientation is landscape");
        mTextView.setText("Natural Orientation is landscape");
        mNaturalOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
    } else {
        Log.i(TAG, "Natural Orientation is portrait");
        mNaturalOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
        mTextView.setText("Natural Orientation is portrait");
    } 

    setRequestedOrientation(mNaturalOrientation);
}

Display.getRotation()仅在API级别8或更高级别受支持,因此如果您需要支持旧设备,则需要调用Display.getOrientation()。

答案 5 :(得分:3)

public static boolean isDeviceDefaultOrientationLandscape(Activity a) {

    WindowManager windowManager = (WindowManager) a.getSystemService(Context.WINDOW_SERVICE);

    Configuration config = a.getResources().getConfiguration();

    int rotation = windowManager.getDefaultDisplay().getRotation();

    boolean defaultLandsacpeAndIsInLandscape = (rotation == Surface.ROTATION_0 ||
            rotation == Surface.ROTATION_180) &&
            config.orientation == Configuration.ORIENTATION_LANDSCAPE;

    boolean defaultLandscapeAndIsInPortrait = (rotation == Surface.ROTATION_90 ||
            rotation == Surface.ROTATION_270) &&
            config.orientation == Configuration.ORIENTATION_PORTRAIT;

    return defaultLandsacpeAndIsInLandscape || defaultLandscapeAndIsInPortrait;
}

答案 6 :(得分:2)

@Urboss,它不能。您需要首先知道设备的默认方向,因为两种方法都会根据它返回更改(我的意思是,如果默认为纵向,您要查找的结果将为1或ROTATE_90 - 因此它是横向的 - 但是,如果默认为横向,则结果为0)。

据我所知,找到设备的默认方向并非易事:(

任何人都可以对这个话题有所了解吗?

答案 7 :(得分:2)

答案 8 :(得分:1)

我的解决方案(在HTC欲望测试和SamSung galaxy选项卡10.1测试):

    private class compass_listener implements SensorEventListener
            {public void onAccuracyChanged(Sensor sensor, int accuracy) {}

             public void onSensorChanged(SensorEvent event)
                    {float roll=0;
                     float pitch=0;
                     switch (((Activity)context).getWindowManager().getDefaultDisplay().getRotation())
                            {case Surface.ROTATION_0:
                                  roll=event.values[2];
                                  pitch=event.values[1];
                             break;
                             case Surface.ROTATION_90:
                                  roll=event.values[1];
                                  pitch=-event.values[2];
                             break;
                             case Surface.ROTATION_180:
                                  roll=-event.values[2];
                                  pitch=-event.values[1];
                             break;
                             case Surface.ROTATION_270:
                                  roll=-event.values[1];
                                  pitch=event.values[2];
                             break;
                            }
                     JSONObject json=new JSONObject();
                     try
                         {json.put("roll", roll);
                          json.put("pitch", pitch);
                          json.put("azimuth", event.values[0]);
                         }
                     catch (JSONException e)
                           {throw new RuntimeException(e);
                           }
                     java_2_js(webview, "intent_compass_change", json);
                    }
            }

答案 9 :(得分:0)

您可以使用旋转和方向进行定义。无需使用传感器或任何听众,只需随时调用isDefaultLandscape方法。

private boolean isDefaultLandscape(final Context context)
{
    Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
    int rotation = display.getRotation();
    int orientation = context.getResources().getConfiguration().orientation;

    switch (rotation)
    {
        case Surface.ROTATION_180:
        case Surface.ROTATION_0:
        {
            return orientation == Configuration.ORIENTATION_LANDSCAPE;
        }
        default:
        {
            return orientation == Configuration.ORIENTATION_PORTRAIT;
        }
    }
}

答案 10 :(得分:0)

对于其他Xamarin开发人员,这是C#中此检查的一个版本:

var orientation = ContextHelper.Current.Resources.Configuration.Orientation;
if (orientation == Android.Content.Res.Orientation.Undefined)
{
    //unknown, you can provide special handling for this case
}

var isLandscape = false;
var rotation = windowManager.DefaultDisplay.Rotation;           

switch (rotation)
{
    case SurfaceOrientation.Rotation0:
    case SurfaceOrientation.Rotation180:
        isLandscape = orientation == Android.Content.Res.Orientation.Landscape;
        break;
    default:
        isLandscape = orientation == Android.Content.Res.Orientation.Portrait;
        break;
}

答案 11 :(得分:0)

这就是我一直在使用的:

 /**
     * returns the natural orientation of the device: Configuration.ORIENTATION_LANDSCAPE or Configuration.ORIENTATION_PORTRAIT .<br/>
     * The result should be consistent no matter the orientation of the device
     */
    public static int getScreenNaturalOrientation(@NonNull final Context context) {
        //based on : http://stackoverflow.com/a/9888357/878126
        final WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        final Configuration config = context.getResources().getConfiguration();
        final int rotation = windowManager.getDefaultDisplay().getRotation();
        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))
            return Configuration.ORIENTATION_LANDSCAPE;
        else
            return Configuration.ORIENTATION_PORTRAIT;
    }

您还可以这样获得自然分辨率:

/**
 * returns the natural screen size (in pixels). The result should be consistent no matter the orientation of the device
 */
public static
@NonNull
Point getScreenNaturalSize(@NonNull final Context context) {
    if (sNaturalScreenSize != null)
        return sNaturalScreenSize;
    final int screenNaturalOrientation = getScreenNaturalOrientation(context);
    final DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
    final int currentOrientation = context.getResources().getConfiguration().orientation;
    if (currentOrientation == screenNaturalOrientation)
        return sNaturalScreenSize = new Point(displayMetrics.widthPixels, displayMetrics.heightPixels);
    //noinspection SuspiciousNameCombination
    return sNaturalScreenSize = new Point(displayMetrics.heightPixels, displayMetrics.widthPixels);
}

答案 12 :(得分:0)

google了一番,发现有篇博文提到通过adb shell执行wm size命令时,总是返回未旋转的“自然”屏幕分辨率,于是作者追到了here

        mWm = IWindowManager.Stub.asInterface(ServiceManager.checkService(
                        Context.WINDOW_SERVICE));

here

                mWm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, initialSize);

所以,Android 似乎确实知道初始/未旋转/“自然”屏幕尺寸,但是,它只是不想让应用知道?我很困惑...

答案 13 :(得分:-2)

解决这个问题非常简单

int orient = this.getResources()。getConfiguration()。orientation;

如果它返回1或2

1是肖像 2是景观

答案 14 :(得分:-3)

可以使用Display.getOrientation()Display.getRotation()完成(对于API级别&gt; = 8)。