功能需求:看視頻時(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è)面我需要的豎屏顯示。
展示完畢,記錄完畢。