Android 手机屏幕旋转的具体使用

功能需求:看视频时,因为视频页面都是自定义的,这里只是用了第三方的播放控件,为啥播放也不自己写音视频(哎,这块不是说你会了就能上手的)。 其余的操作都是需要自己实现,这样才能更好的根据产品的需求来实时改变。

因为觉得网上找到的相关知识和自己所要实现的内容有很大的区别,所以记录了一下,同时也是为了方便一下一同从事andorid开发的小伙伴。
在这里记录的同时,尽量保证内容的可用性,方便日后用到了能快速接入,话不多说,进入今天的主题。

所有的屏幕旋转都离不开SensorManager、SensorEventListener,关于这两个的,网上一搜有很多,所以就简单介绍下吧。

SensorManager 传感器

 SensorManager sensorManager = mContext.getSystemService(Context.SENSOR_SERVICE);
 Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

这样就能获取到传感器的对象。这里默认为方向传感器,因为经过我多次测试,手机屏幕旋转,在视频页面播放,方向传感器比较符合我的需求,网上搜到说中立也可以,这里就不做讨论了,可以自己去试试,毕竟需求不同,要求也不同。

SensorEventListener 加速度传感器

  SensorEventListener sensorEvent = new SensorEventListener() {
        @Override
        public void onSensorChanged(SensorEvent sensorEvent) {
        }

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

这里的主要作用是通过获取x,y,z轴的距离,来判断当前屏幕的旋转方向,通过多次的测试,感觉屏幕旋转用到的技术点不是很多,更多的是对具体现象的理解吧,所以下来就直接代码来标注了。

/**
 * 手机旋转的管理类
 */
public class SensorOrientationManger {
    private Activity mActivity;
    private int sensorTime = 2000;// SensorManager.SENSOR_DELAY_NORMAL or time
    private Sensor sensor;
    private SensorManager sensorManager;
    private SensorEventListener sensorEvent;
    private int mX, mY, mZ;
    private long lastSensorTime = 0;
    private boolean isLock = false;

    public SensorOrientationManger(Activity mActivity) {
        this.mActivity = mActivity;
        sensorManager = (SensorManager)         
        // 获取当前activity 的服务对象
        mActivity.getSystemService(Context.SENSOR_SERVICE);
        // 获取当前activity 的方向传感器
        sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        // 放置获取到空的,不过一般也不会为空
        if (sensor == null) {
            sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        }
   
        if (sensor != null) {
            // 操作加速度传感器
            sensorEvent = new SensorEventListener() {
                @Override
                public void onSensorChanged(SensorEvent event) {
                    if (event == null) return;
                    // 因为视频页面有锁屏功能,所以这块加了判断,不用的可以看着去掉
                    if (!isLock ) {
                        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                            //这块返回的是event的x轴,y轴,z轴的加速度值,所以需要分开来获取
                            int x = (int) event.values[0];
                            int y = (int) event.values[1];
                            int z = (int) event.values[2];
                            //获取开始转动的时间
                            long sensorTime = System.currentTimeMillis();
                            int absX = Math.abs(mX - x);
                            int absY = Math.abs(mY - y);
                            int absZ = Math.abs(mZ - z);
                            
                            int maxvalue = getMaxValue(absX, absY, absZ);
                             //判断下要有最少1秒的时间差,不然就会在短时间内多次旋转屏幕,影响体验
                            if (maxvalue > 1 && (sensorTime - lastSensorTime) > 1000) {
                                lastSensorTime = sensorTime;
                                if (RotationObserver.isAutoRotateOn(mActivity))   {                                   
                                     mActivity.setRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
                                }
                            }
                            mX = x;
                            mY = y;
                            mZ = z;
                        }
                    }else {
                        lockScreenOrientation(mActivity);
                    }
                }
                @Override
                public void onAccuracyChanged(Sensor sensor, int i) {
                }
            };
        }
    }

    /**
     * 绑定传感器
     */
    public void requestSensor() {
        sensorManager.registerListener(sensorEvent, sensor, sensorTime);
    }

    /**
     * 解绑传感器
     */
    public void abandonSensor() {
        sensorManager.unregisterListener(sensorEvent);
    }

    /**
     * 改变锁屏状态
     */
    public void setLock(boolean lock) {
        isLock = lock;
    }
   
    /**
     * 加锁时来根据当前屏幕的方向指定旋转方向
     */
    public void lockScreenOrientation(Activity activity) {
        Display display = activity.getWindowManager().getDefaultDisplay();
        switch (display.getRotation()) {
            // 横屏
            case Surface.ROTATION_90:
            case Surface.ROTATION_270:
                if (isLock) {
                    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
                } else {
                    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
                }
                break;
            case Surface.ROTATION_0:
            case Surface.ROTATION_180:
                if (isLock) {
                    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
                } else {
                    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
                }
                break;
        }
    }
}
    public static int getMaxValue(int x, int y, int z) {
        int max = 0;
        if (x > y && x > z) {
            max = x;
        } else if (y > x && y > z) {
            max = y;
        } else if (z > x && z > y) {
            max = z;
        }
        return max;
    }

下面是监听手机是否打开了自动旋转功能的类了,这个必须要用到,不然的话,手机屏幕旋转会和系统设置是否允许旋转冲突,会直接写成bug,哈哈

/**
 * 监听手机设置-自动旋转
 */
public class RotationObserver extends ContentObserver {
    ContentResolver mResolver;
    Activity mContext;
    SensorOrientationManger mOrientationManger;

    public RotationObserver(Handler handler, Context context, SensorOrientationManger orientationManger) {
        super(handler);
        this.mContext = (Activity) context;
        mResolver = context.getContentResolver();
        this.mOrientationManger = orientationManger;
        // TODO Auto-generated constructor stub
    }

    //手机设置是否允许自动旋转的时候会调用
    @Override
    public void onChange(boolean selfChange) {
        // TODO Auto-generated method stub
        super.onChange(selfChange);
        //更新按钮状态
        setScreenOrientation();
    }

    public void startObserver() {
        mResolver.registerContentObserver(Settings.System
                    .getUriFor(Settings.System.ACCELEROMETER_ROTATION), false,
            this);
    }

    public void stopObserver() {
        mResolver.unregisterContentObserver(this);
    }

    private void setScreenOrientation() {
        //是否开启自动旋转设置 
        mOrientationManger.lockScreenOrientation(mContext);
    }

    /**
     * 系统是否允许自动旋转屏幕
     *
     * @return
     */
    public static boolean isAutoRotateOn(Activity activity) {
        //获取系统是否允许自动旋转屏幕
        return (android.provider.Settings.System.getInt(activity.getContentResolver(),     Settings.System.ACCELEROMETER_ROTATION, 0) == 1);
    }
}

下面就是使用了,伪代码走起来。

    private SensorOrientationManger orientationManger;
    private RotationObserver mRotationObserver;
    private Handler mHandler;
    private void initData(){
        //因为ContentObserver 中需要,所以就直接获取下
        mHandler = new Handler(Looper.myLooper());
        orientationManger = new SensorOrientationManger(this);
        mRotationObserver = new RotationObserver(mHandler, SpeedPlayNewActivity2.this, orientationManger);
    }
     @Override
        public void onResume() {
            orientationManger.requestSensor();
            mRotationObserver.startObserver();
        }

       @Override
        protected void onPause() {
           super.onPause();
           mRotationObserver.stopObserver();
           orientationManger.abandonSensor();
    }
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        int orientation = newConfig.orientation;
        if (orientation == ORIENTATION_LANDSCAPE) {
            // 横屏的操作
        } else {
            // 竖屏的操作
        }
    }
都很好理解,只是整理逻辑的时候比较麻烦,很费时间,所以写出来为大家提供个方便吧。或许写的不是很好,但是也是一次不小的收货。网上好多说配置Activity 的screenOrientation属性的,但是我并没有发现有啥实际作用,所以我这里只是设置了 android:screenOrientation="portrait" 因为进入页面我需要的竖屏显示。

展示完毕,记录完毕。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,492评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,048评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,927评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,293评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,309评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,024评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,638评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,546评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,073评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,188评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,321评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,998评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,678评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,186评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,303评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,663评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,330评论 2 358

推荐阅读更多精彩内容