拍照功能橫豎屏切換問題
最近專案中要求針對拍照功能新增橫豎屏切換,具體需求如下
1.橫豎屏載入不同的佈局;
2.只處理0度橫屏和90度豎屏,180度橫屏和270度豎屏不做處理;
3.能通過系統的自動旋轉開關控制橫豎屏切換功能的開啟關閉;
起初打算利用的系統的橫豎屏切換功能來實現,具體操作如下
1.清單檔案中配置 android:configChanges
<activity android:name=".xxx" android:configChanges="orientation|screenSize|keyboardHidden" android:theme="@style/FullScreenTheme" />
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;
}
測試發現滿足需求,到此算是告一段落。
程式碼沒什麼難度,記錄下來主要是為了理一下思路,也希望能幫到遇到同樣問題的猿友們。如果大家有什麼更好的解決辦法或思路歡迎留言,不勝感激~