【问题标题】:Get phone orientation but fix screen orientation to portrait获取手机方向,但将屏幕方向固定为纵向
【发布时间】:2012-01-26 16:50:38
【问题描述】:

我想获取手机方向,但将屏幕方向保持为纵向。 因此,无论用户将手机切换为横向还是纵向,视图都保持不变,但我可以得到它是横向还是纵向。

将活动设置为 android:screenOrientation="portrait" 将解决这两个问题,但我无法通过

检测手机方向
public void onConfigurationChanged(Configuration newConfig) {
    switch (newConfig.orientation) {
    case Configuration.ORIENTATION_PORTRAIT:
        Toast.makeText(this, "Portrait", Toast.LENGTH_SHORT).show();
        break;
    case Configuration.ORIENTATION_LANDSCAPE:
        Toast.makeText(this, "Landscape", Toast.LENGTH_SHORT).show();
        break;
    default:
        break;
    }
}

有人知道如何解决这个问题吗?

【问题讨论】:

标签: android screen-orientation orientation-changes


【解决方案1】:

这是一个用于轻松管理屏幕方向更改的多功能类:

public class OrientationManager extends OrientationEventListener {

    public enum ScreenOrientation {
        REVERSED_LANDSCAPE, LANDSCAPE, PORTRAIT, REVERSED_PORTRAIT
    }

    public ScreenOrientation screenOrientation; 
    private OrientationListener listener;

    public OrientationManager(Context context, int rate, OrientationListener listener) {
        super(context, rate);
        setListener(listener);
    }

    public OrientationManager(Context context, int rate) {
        super(context, rate);
    }

    public OrientationManager(Context context) {
        super(context);
    }

    @Override
    public void onOrientationChanged(int orientation) {
        if (orientation == -1){
            return;
        }
        ScreenOrientation newOrientation;
        if (orientation >= 60 && orientation <= 140){
            newOrientation = ScreenOrientation.REVERSED_LANDSCAPE;
        } else if (orientation >= 140 && orientation <= 220) {
            newOrientation = ScreenOrientation.REVERSED_PORTRAIT;
        } else if (orientation >= 220 && orientation <= 300) {
            newOrientation = ScreenOrientation.LANDSCAPE;
        } else {
            newOrientation = ScreenOrientation.PORTRAIT;                    
        }
        if(newOrientation != screenOrientation){
            screenOrientation = newOrientation;
            if(listener != null){
                listener.onOrientationChange(screenOrientation);
            }           
        }
    }

    public void setListener(OrientationListener listener){
        this.listener = listener;
    }

    public ScreenOrientation getScreenOrientation(){
        return screenOrientation;
    }

    public interface OrientationListener {

        public void onOrientationChange(ScreenOrientation screenOrientation);
    }
}

这样更简单、可重复使用,您还可以获得 REVERSE_LANDSCAPE 和 REVERSE_PORTRAIT 方向。

您必须实现 OrientationListener 才能仅在发生方向更改时收到通知。

不要忘记调用orientationManager.enable()开始方向跟踪,然后调用orientationManager.disable()(这两个方法继承自OrientationEventListener类)

更新:用例示例

MyFragment extends Fragment implements OrientationListener {

    ...

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        orientationManager = new OrientationManager(getActivity(), SensorManager.SENSOR_DELAY_NORMAL, this);
        orientationManager.enable();        
    }

    @Override
    public void onOrientationChange(ScreenOrientation screenOrientation) {
        switch(screenOrientation){
            case PORTRAIT:
            case REVERSED_PORTRAIT:
                MainActivityBase.getInstance().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            break;
            case REVERSED_LANDSCAPE:
                MainActivityBase.getInstance().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
            break;
            case LANDSCAPE:
                MainActivityBase.getInstance().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            break;
        }
    }
}

【讨论】:

  • 太好了,非常感谢。不敢相信这个答案只有一个赞成票。
  • 很好的解决方案,但请注意,这只会在将纵向模式作为默认模式的智能手机上给出正确的结果。在平板电脑上(默认为横向),在横向的情况下,方向的值为 0,也就是说,在应用逻辑之前,您必须将 270 添加到方向值。有关默认设备方向,请参阅stackoverflow.com/questions/4553650/…
  • 3 年后我找到了这个,这是一个如此优雅的解决方案......如果我能给你超过 1 个赞,哈哈。
【解决方案2】:

您能否使用加速度计满足您的要求?如果是这样,也许像这个(未经测试的)片段这样的东西会适合你的目的。

SensorManager sensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);
        sensorManager.registerListener(new SensorEventListener() {
            int orientation=-1;;

            @Override
            public void onSensorChanged(SensorEvent event) {
                if (event.values[1]<6.5 && event.values[1]>-6.5) {
                    if (orientation!=1) {
                        Log.d("Sensor", "Landscape");
                    }
                    orientation=1;
                } else {
                    if (orientation!=0) {
                        Log.d("Sensor", "Portrait");
                    }
                    orientation=0;
                }
            }

            @Override
            public void onAccuracyChanged(Sensor sensor, int accuracy) {
                // TODO Auto-generated method stub

            }
        }, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_GAME);

【讨论】:

  • 嗨菲利普。这与我自己实施的解决方案相同。在这种情况下,似乎没有其他选择可以访问传感器以获取设备的方向。
  • 如果设备平放在桌子上,价值不大。
  • 有谁知道如何检测reverse_landscape?
  • 这会吃太多电池吗?
【解决方案3】:

我需要一个仅按需提供方向的解决方案。这个对我有用:

public class SensorOrientationChecker {

public final String TAG = getClass().getSimpleName();

int mOrientation = 0;
private SensorEventListener mSensorEventListener;
private SensorManager mSensorManager;

private static SensorOrientationChecker mInstance;

public static SensorOrientationChecker getInstance() {
    if (mInstance == null)
        mInstance = new SensorOrientationChecker();

    return mInstance;
}

private SensorOrientationChecker() {
    mSensorEventListener = new Listener();
    Context applicationContext = GlobalData.getInstance().getContext();
    mSensorManager = (SensorManager) applicationContext.getSystemService(Context.SENSOR_SERVICE);

}

/**
 * Call on activity onResume()
 */
public void onResume() {
    mSensorManager.registerListener(mSensorEventListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
}

/**
 * Call on activity onPause()
 */
public void onPause() {
    mSensorManager.unregisterListener(mSensorEventListener);
}

private class Listener implements SensorEventListener {

    @Override
    public void onSensorChanged(SensorEvent event) {
        float x = event.values[0];
        float y = event.values[1];

        if (x<5 && x>-5 && y > 5)
            mOrientation = 0;
        else if (x<-5 && y<5 && y>-5)
            mOrientation = 90;
        else if (x<5 && x>-5 && y<-5)
            mOrientation = 180;
        else if (x>5 && y<5 && y>-5)
            mOrientation = 270;

        //Log.e(TAG,"mOrientation="+mOrientation+"   ["+event.values[0]+","+event.values[1]+","+event.values[2]+"]");
                                                                       }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

}

public int getOrientation(){
    return mOrientation;
    }
}

【讨论】:

    【解决方案4】:

    如果您禁用屏幕方向更改,那么显然永远不会调用 onConfigurationChanged...

    我认为唯一的方法是使用加速度传感器,检查this link

    【讨论】:

      【解决方案5】:

      要进入你想在该活动的清单文件中设置的内容

      android:configChanges="orientation|keyboardHidden"
      

      然后当用户旋转手机时,它会进入 public void onConfigurationChanged() 方法。 同时删除

      android:screenOrientation="portrait" 
      

      来自同一活动。

      【讨论】:

      • 但是如果 onConfigurationChanged() 被调用,方向改变已经被执行了......我需要之前的信息。
      【解决方案6】:

      这比编写一个全新的类要简单得多:

       final OrientationEventListener orientationEventListener = new OrientationEventListener( getApplicationContext() ) {
      
        @Override
        public void onOrientationChanged( final int orientation ) {
          Log.i("", "orientation = " + orientation );
        }
      };
      
      orientationEventListener.enable();
      

      【讨论】:

        【解决方案7】:

        如果有人正在寻找该问题的 Webview/javascript 解决方案,下面可以做到这一点。

        这将触发窗口上的自定义“翻转”事件,并带有 jquery 的“额外参数”。它还设置了window.flip,类似于window.orientation:

        $(window).on('flip',function(ev,angle,orientation) {
            console.log(angle,orientation);
            alert(window.flip);
        });
        

        if (window.DeviceOrientationEvent) {
            jQuery.flip = {
                debug       : false,
                interval    : 1000,
                checked     : false,
                betaflat    : 25,
                gammaflat   : 45,
                orientation : 'portrait-primary',
                angles      : {
                    'portrait-primary'      : 0,
                    'portrait-secondary'    : 0,
                    'landscape-primary'     : 90,
                    'landscape-secondary'   : -90       
                },
                timer       : null,
                check       : function(ev) {
                    if (!this.checked) {
                        var trigger=false;
                        if (this.debug) console.log([ev.alpha,ev.beta,ev.gamma]);
                        if (ev.beta>this.betaflat) {
                            // if beta is big its portrait
                            if (this.debug) console.log('beta portrait pri');
                            if (this.orientation!='portrait-primary') {
                                this.orientation='portrait-primary';
                                trigger=true;
                            }
                        } else if (ev.beta<-this.betaflat) {
                            // if beta is big its portrait
                            if (this.debug) console.log('beta portrait sec');
                            if (this.orientation!='portrait-secondary') {
                                this.orientation='portrait-secondary';
                                trigger=true;
                            }
                        } else if (ev.gamma>this.gammaflat) {
        
                            // else if gamma is big its landscape
                            if (this.debug) console.log('gamma landscape pri');
                            if (this.orientation!='landscape-primary') {
                                this.orientation='landscape-primary';
                                trigger=true;
                            }
        
                        } else if (ev.gamma<-this.gammaflat) {
        
                            // else if gamma is big its landscape
                            if (this.debug) console.log('gamma landscape sec');
                            if (this.orientation!='landscape-secondary') {
                                this.orientation='landscape-secondary';
                                trigger=true;
                            }
        
                        }
                        if (trigger) {
                            if (this.debug) console.log('trigger flip');
                            window.flip = this.angles[this.orientation];
                            $(window).trigger('flip',[window.flip,this.orientation]);
                            this.checked=true;
                        }
                    }
                }
            }
            $(document).ready(function() {
                setInterval(function() {jQuery.flip.checked=false},jQuery.flip.interval);
                $(window).on('deviceorientation',function(ev) { jQuery.flip.check(ev.originalEvent) });
            });
        } else {
            if (this.debug) console.log('DeviceOrientationEvent not supported');
        }
        

        jquery 并不是真正需要的。无论如何我都需要它。

        【讨论】:

        • 用 Javascript 解决 Android 问题并没有真正的帮助。它需要有一个 WebView 或类似的东西来运行可能不是这种情况的脚本。
        • 哦-好点。生活在我自己的泡泡里。更新答案。
        • 那么为什么现在投反对票?我提到这是 webview/javascript,OP 没有提到他/她生活在什么世界。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多