最近项目中要求针对拍照功能添加横竖屏切换,具体需求如下
1.横竖屏加载不同的布局;
2.只处理0度横屏和90度竖屏,180度横屏和270度竖屏不做处理;
3.能通过系统的自动旋转开关控制横竖屏切换功能的开启关闭;
起初打算利用的系统的横竖屏切换功能来实现,具体操作如下
1.清单文件中配置 android:configChanges
2.重写 onConfigurationChanged() 方法
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
}
}
但是发现这样做存在一些问题,比如说
1.每次只能旋转90度,才能触发 onConfigurationChanged() 方法的回调,如果突然翻转180度,或者快速从0度到90度再到180度都是无法触发 onConfigurationChanged() 方法回调的;
2.无法满足只处理0度和90度的情况;
所以改用通过 OrientationEventListener 自己控制横竖屏的切换,核心代码如下
private class IOrientationEventListener extends OrientationEventListener {
public IOrientationEventListener(Context context) {
super(context);
}
@Override
public void onOrientationChanged(int orientation) {
if (ORIENTATION_UNKNOWN == orientation) {
return;
}
//关联系统自动旋转开关
if (!PhoneUtils.getRotateSwitchState(mContext)) return;
if (orientation > 350 || orientation < 10) {
//90度竖屏
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else if (orientation > 260 && orientation < 280) {
//0度横屏
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
}
public static boolean getRotateSwitchState(Context context) {
try {
//1 开启 0 关闭
return Settings.System.getInt(context.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 1;
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
return false;
}
}
然后在合适的位置通过 enable() 和 disable() 控制 OrientationEventListener 的开启和关闭就可以了。
本以为到此完事大吉,但是测试同事反馈横竖屏切换的时候太灵敏了,快速晃动手机的时候就可能触发横竖屏的切换,要求能否控制一下灵敏度。
既然提出了问题,身为猿的我们总要尝试寻求解决优化的办法不是,于是查找API,发现 OrientationEventListener 有一个构造方法
public OrientationEventListener(Context context, int rate)
其中第二个参数就可以控制获取传感器数据的速度,不幸的是实际测试好像并不能解决我的问题~,于是转变思路能否自己计算角度变化的速度呢?改进代码如下
private class IOrientationEventListener extends OrientationEventListener {
long time1, time2;
public IOrientationEventListener(Context context) {
super(context);
time1 = System.currentTimeMillis();
time2 = System.currentTimeMillis();
}
@Override
public void onOrientationChanged(int orientation) {
if (ORIENTATION_UNKNOWN == orientation) {
return;
}
if (!PhoneUtils.getRotateSwitchState(mContext)) return;
if (orientation > 350 || orientation < 10) {
time1 = System.currentTimeMillis();
if (getOrienSpeed(time1, time2) > 0) return;
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else if (orientation > 260 && orientation < 280) {
time2 = System.currentTimeMillis();
if (getOrienSpeed(time1, time2) > 0) return;
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
}
private long getOrienSpeed(long time1, long time2) {
long time = Math.abs(time1 - time2);
return 270 / time;
}
测试发现满足需求,到此算是告一段落。
代码没什么难度,记录下来主要是为了理一下思路,也希望能帮到遇到同样问题的猿友们。如果大家有什么更好的解决办法或思路欢迎留言,不胜感激~