功能需求:看视频时,因为视频页面都是自定义的,这里只是用了第三方的播放控件,为啥播放也不自己写音视频(哎,这块不是说你会了就能上手的)。 其余的操作都是需要自己实现,这样才能更好的根据产品的需求来实时改变。
因为觉得网上找到的相关知识和自己所要实现的内容有很大的区别,所以记录了一下,同时也是为了方便一下一同从事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" 因为进入页面我需要的竖屏显示。
展示完毕,记录完毕。