获取手机方向时锁定到一个方向方向、手机

2023-09-05 10:53:48 作者:待绝笔墨痕干

这可以很容易地的另外一个问题重复,我只是在努力搞清楚该怎么寻找。

This could easily be a duplicate of another question, Im just struggling to figure out what to search for.

我的相机应用锁定在横向模式(在清单)是这样的:

My camera app is locked in landscape mode (in the manifest) like this:

android:screenOrientation="landscape"

不过,我想还是旋转一些UI元素时,该设备被旋转到纵向(尽管Android将仍然认为它的景观,但是那故意的)。

However, I want to still rotate some UI elements when the device is rotated into portrait (although android will still think its in landscape, but thats on purpose).

所以我尝试这样做,检查方向

So I've tried this to check the orientation

int rotation = this.getWindowManager().getDefaultDisplay()
            .getRotation();
    int degrees = 0;
    switch (rotation) {
        case Surface.ROTATION_0:
            Log.d("Rotation", "0");
            break;
        case Surface.ROTATION_90:
            Log.d("Rotation", "90");
            break;
        case Surface.ROTATION_180:
            Log.d("Rotation", "180");
            break;
        case Surface.ROTATION_270:
            Log.d("Rotation", "270");
            break;
    }

不幸的是,它总是返回90,不管我怎么打开手机。是否有一个更强大的方式来获得方向,不管是什么安卓认为的方向是?

And unfortunately it always returns 90, regardless of how I turn the phone. Is there a more robust way to get orientation, regardless of what Android "thinks" the orientation is?

推荐答案

所以以后我想过这个问题,我意识到我可以实现类似的算法是什么安卓本身使用找出方向。我用onSenseorChanged回调它

So after I thought about it, I realized I could just implement a similar algorithm as what Android itself uses to figure out the orientation. I do it using the onSenseorChanged callback

public static final int UPSIDE_DOWN = 3;
public static final int LANDSCAPE_RIGHT = 4;
public static final int PORTRAIT = 1;
public static final int LANDSCAPE_LEFT = 2;
public int mOrientationDeg; //last rotation in degrees
public int mOrientationRounded; //last orientation int from above 
private static final int _DATA_X = 0;
private static final int _DATA_Y = 1;
private static final int _DATA_Z = 2;
private int ORIENTATION_UNKNOWN = -1;
@Override
public void onSensorChanged(SensorEvent event) 
{
    Log.d(TAG, "Sensor Changed");
    float[] values = event.values;
    int orientation = ORIENTATION_UNKNOWN;
    float X = -values[_DATA_X];
    float Y = -values[_DATA_Y];
    float Z = -values[_DATA_Z];        
    float magnitude = X*X + Y*Y;
    // Don't trust the angle if the magnitude is small compared to the y value
    if (magnitude * 4 >= Z*Z) {
        float OneEightyOverPi = 57.29577957855f;
        float angle = (float)Math.atan2(-Y, X) * OneEightyOverPi;
        orientation = 90 - (int)Math.round(angle);
        // normalize to 0 - 359 range
        while (orientation >= 360) {
            orientation -= 360;
        } 
        while (orientation < 0) {
            orientation += 360;
        }
    }
    //^^ thanks to google for that code
    //now we must figure out which orientation based on the degrees
    Log.d("Oreination", ""+orientation);
    if (orientation != mOrientationDeg) 
    {
        mOrientationDeg = orientation;
        //figure out actual orientation
        if(orientation == -1){//basically flat

        }
        else if(orientation <= 45 || orientation > 315){//round to 0
            tempOrientRounded = 1;//portrait
        }
        else if(orientation > 45 && orientation <= 135){//round to 90
            tempOrientRounded = 2; //lsleft
        }
        else if(orientation > 135 && orientation <= 225){//round to 180
            tempOrientRounded = 3; //upside down
        }
        else if(orientation > 225 && orientation <= 315){//round to 270
            tempOrientRounded = 4;//lsright
        }

    }

    if(mOrientationRounded != tempOrientRounded){
            //Orientation changed, handle the change here
        mOrientationRounded = tempOrientRounded;

    }
}

它看起来更complecated比它,但只知道它的工作原理(我会说同样的一部作品系统)。不要忘记注册您的传感器变化事件监听器在onResume和的onPause加速度计

It looks more complecated than it is, but just know that it works(I'd say equally well as the system one works). Dont forget to register your sensor change event listener in onResume and onPause for accelerometer