Android游戏开发屏幕旋转问题完美解决

做游戏Android上的游戏开发也有一年多了,虽然没有什么高深的见解,但就遇到的问题及解决方案做下记录

我们的游戏,横屏的棋牌游戏,一直是锁定横屏的一个方向运行,有一天,项目经理找到我,想让游戏像一些IPhone游戏一样,在旋转屏幕的时候按照重力进行旋转,在锁定方向的时候又能固定一个方向,也就是能按照用户选择在横屏方向进行锁定和旋转

当然,我信心满满的答应了,感觉对于一个以Android起家的我来说这并不算什么,五分钟搞定

结果一个小时过去了,并没有找到完美的解决方案,在Android的manifest.xml做配置是不可行的

经过我一番百度和看Android文档,我才发现,Android对旋转屏,特别是只有横屏或者竖屏虽重力旋转的支持是到Android4.3.1才有完美支持的

unspecified - 默认值,由系统选择显示方向
landscape   - 橫向
portrait    - 纵向
reverseLandscape    - 反横向(API >= 9)
reversePortrait     - 反纵向(API >= 9)
user        - 用户当前的首选方向
behind      - 与Activity堆栈下的方向相同
sensor      - 根据物理传感器方向3/4个方向(取决于设备)
fullSensor  - 根据物理传感器方向4个方向
nosensor    - 不按照物理传感器方向,除此之外与"unspecified"无区别
sensorLandscape     - 按照物理传感器,只在横向(2个方向)进行翻转(API >= 9)
sensorPortrait      - 按照物理传感器,只在纵向(2个方向)进行翻转(API >= 9)
userLandscape       - 按照用户选择,锁定一个横向,或者按照物理传感器进行横向的翻转(API >= 18)
userPortrait        - 按照用户选择,锁定一个纵向,或者按照物理传感器进行纵向的翻转(API >= 18)
fullUser    - 如果用户锁定了屏幕,它与"user"作用一致,如果是解锁了旋转,它与"fullSensor"作用一致(API >= 18)
locked      - 锁定了屏幕当前方向(API >= 18)

但由于游戏是要适配各个系统版本的,只在AndroidManifest.xml里配置显然只能满足部分系统需求,于是我写了下面的代码

public class TestOrientationActivity extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        resetScreenOrientation();
        Uri rotationUri = Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION);
        ContentResolver resolver = getApplication().getContentResolver();
        // 此处注册监听旋转设置变化
        resolver.registerContentObserver(rotationUri, true, mContentConfigObserver);
    }

    /**
     * 用于监听旋转变化
     */
    private ContentObserver mContentConfigObserver = new ContentObserver(new Handler()) {
        @Override
        public void onChange(boolean selfChange) {
            resetScreenOrientation();
        }
    };

    @Override
    protected void onRestart() {
        // TODO Auto-generated method stub
        super.onRestart();
        resetScreenOrientation();
    }

    private void resetScreenOrientation() {
        // TODO Auto-generated method stub
        int orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
        int sdkInt = android.os.Build.VERSION.SDK_INT;  
        if (sdkInt >= Build.VERSION_CODES.JELLY_BEAN_MR2 /*18*/) {
            //大于JELLY_BEAN_MR2(4.3.1)版本的直接支持按照用户选择进行屏幕旋转
            //Field requires API level 18 (current min is 8): 
            orientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE;
        } else if (sdkInt >= Build.VERSION_CODES.GINGERBREAD) {
            int flag = Settings.System.getInt(getContentResolver(),Settings.System.ACCELEROMETER_ROTATION, 0);
            if (0 == flag) {
                // 屏幕旋转已经关闭,那么固定屏幕在某一个方向
                orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
            } else {
                // 屏幕旋转打开,屏幕按照sensor的参数进行旋转
                // 此参数只在GINGERBREAD(2.3.3)以上的系统支持
                //Field requires API level 18 (current min is 8): 
                orientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
            }
        } else {
            // 小于GINGERBREAD(2.3.3)版本的系统不支持屏幕旋转
            orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
        }
        int curOrientation = getRequestedOrientation();
        if (orientation != curOrientation) {
            setRequestedOrientation(orientation);
        }
    }
}

除了在2.3.3-4.3.1的部分手机监听设置改变时候会出现延迟以外,别的都是完美解决

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,482评论 25 708
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,251评论 4 61
  • 鹏慧阅读 351评论 0 0
  • 今天我去看了心理老师。其实我最大的收获就是她告诉我。其实每个人的心里暗示很重要的。如果一个人不停地对自己说。我不行...
    橞在祺中阅读 188评论 0 0