1. 程式人生 > >拍照功能橫豎屏切換問題

拍照功能橫豎屏切換問題

最近專案中要求針對拍照功能新增橫豎屏切換,具體需求如下

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;
}

測試發現滿足需求,到此算是告一段落。

程式碼沒什麼難度,記錄下來主要是為了理一下思路,也希望能幫到遇到同樣問題的猿友們。如果大家有什麼更好的解決辦法或思路歡迎留言,不勝感激~