Android 手機(jī)屏幕旋轉(zhuǎn)的具體使用

功能需求:看視頻時(shí),因?yàn)橐曨l頁(yè)面都是自定義的,這里只是用了第三方的播放控件,為啥播放也不自己寫(xiě)音視頻(哎,這塊不是說(shuō)你會(huì)了就能上手的)。 其余的操作都是需要自己實(shí)現(xiàn),這樣才能更好的根據(jù)產(chǎn)品的需求來(lái)實(shí)時(shí)改變。

因?yàn)橛X(jué)得網(wǎng)上找到的相關(guān)知識(shí)和自己所要實(shí)現(xiàn)的內(nèi)容有很大的區(qū)別,所以記錄了一下,同時(shí)也是為了方便一下一同從事andorid開(kāi)發(fā)的小伙伴。
在這里記錄的同時(shí),盡量保證內(nèi)容的可用性,方便日后用到了能快速接入,話不多說(shuō),進(jìn)入今天的主題。

所有的屏幕旋轉(zhuǎn)都離不開(kāi)SensorManager、SensorEventListener,關(guān)于這兩個(gè)的,網(wǎng)上一搜有很多,所以就簡(jiǎn)單介紹下吧。

SensorManager 傳感器

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

這樣就能獲取到傳感器的對(duì)象。這里默認(rèn)為方向傳感器,因?yàn)榻?jīng)過(guò)我多次測(cè)試,手機(jī)屏幕旋轉(zhuǎn),在視頻頁(yè)面播放,方向傳感器比較符合我的需求,網(wǎng)上搜到說(shuō)中立也可以,這里就不做討論了,可以自己去試試,畢竟需求不同,要求也不同。

SensorEventListener 加速度傳感器

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

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

這里的主要作用是通過(guò)獲取x,y,z軸的距離,來(lái)判斷當(dāng)前屏幕的旋轉(zhuǎn)方向,通過(guò)多次的測(cè)試,感覺(jué)屏幕旋轉(zhuǎn)用到的技術(shù)點(diǎn)不是很多,更多的是對(duì)具體現(xiàn)象的理解吧,所以下來(lái)就直接代碼來(lái)標(biāo)注了。

/**
 * 手機(jī)旋轉(zhuǎn)的管理類
 */
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)         
        // 獲取當(dāng)前activity 的服務(wù)對(duì)象
        mActivity.getSystemService(Context.SENSOR_SERVICE);
        // 獲取當(dāng)前activity 的方向傳感器
        sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        // 放置獲取到空的,不過(guò)一般也不會(huì)為空
        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;
                    // 因?yàn)橐曨l頁(yè)面有鎖屏功能,所以這塊加了判斷,不用的可以看著去掉
                    if (!isLock ) {
                        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                            //這塊返回的是event的x軸,y軸,z軸的加速度值,所以需要分開(kāi)來(lái)獲取
                            int x = (int) event.values[0];
                            int y = (int) event.values[1];
                            int z = (int) event.values[2];
                            //獲取開(kāi)始轉(zhuǎn)動(dòng)的時(shí)間
                            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秒的時(shí)間差,不然就會(huì)在短時(shí)間內(nèi)多次旋轉(zhuǎn)屏幕,影響體驗(yàn)
                            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);
    }

    /**
     * 改變鎖屏狀態(tài)
     */
    public void setLock(boolean lock) {
        isLock = lock;
    }
   
    /**
     * 加鎖時(shí)來(lái)根據(jù)當(dāng)前屏幕的方向指定旋轉(zhuǎn)方向
     */
    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;
    }

下面是監(jiān)聽(tīng)手機(jī)是否打開(kāi)了自動(dòng)旋轉(zhuǎn)功能的類了,這個(gè)必須要用到,不然的話,手機(jī)屏幕旋轉(zhuǎn)會(huì)和系統(tǒng)設(shè)置是否允許旋轉(zhuǎn)沖突,會(huì)直接寫(xiě)成bug,哈哈

/**
 * 監(jiān)聽(tīng)手機(jī)設(shè)置-自動(dòng)旋轉(zhuǎn)
 */
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
    }

    //手機(jī)設(shè)置是否允許自動(dòng)旋轉(zhuǎn)的時(shí)候會(huì)調(diào)用
    @Override
    public void onChange(boolean selfChange) {
        // TODO Auto-generated method stub
        super.onChange(selfChange);
        //更新按鈕狀態(tài)
        setScreenOrientation();
    }

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

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

    private void setScreenOrientation() {
        //是否開(kāi)啟自動(dòng)旋轉(zhuǎn)設(shè)置 
        mOrientationManger.lockScreenOrientation(mContext);
    }

    /**
     * 系統(tǒng)是否允許自動(dòng)旋轉(zhuǎn)屏幕
     *
     * @return
     */
    public static boolean isAutoRotateOn(Activity activity) {
        //獲取系統(tǒng)是否允許自動(dòng)旋轉(zhuǎn)屏幕
        return (android.provider.Settings.System.getInt(activity.getContentResolver(),     Settings.System.ACCELEROMETER_ROTATION, 0) == 1);
    }
}

下面就是使用了,偽代碼走起來(lái)。

    private SensorOrientationManger orientationManger;
    private RotationObserver mRotationObserver;
    private Handler mHandler;
    private void initData(){
        //因?yàn)镃ontentObserver 中需要,所以就直接獲取下
        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 {
            // 豎屏的操作
        }
    }
都很好理解,只是整理邏輯的時(shí)候比較麻煩,很費(fèi)時(shí)間,所以寫(xiě)出來(lái)為大家提供個(gè)方便吧?;蛟S寫(xiě)的不是很好,但是也是一次不小的收貨。網(wǎng)上好多說(shuō)配置Activity 的screenOrientation屬性的,但是我并沒(méi)有發(fā)現(xiàn)有啥實(shí)際作用,所以我這里只是設(shè)置了 android:screenOrientation="portrait" 因?yàn)檫M(jìn)入頁(yè)面我需要的豎屏顯示。

展示完畢,記錄完畢。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容