亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android實(shí)現(xiàn)屏幕旋轉(zhuǎn)四個(gè)方向準(zhǔn)確監(jiān)聽

 更新時(shí)間:2022年07月20日 12:24:47   作者:小風(fēng)666  
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)屏幕旋轉(zhuǎn)四個(gè)方向準(zhǔn)確監(jiān)聽,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

在做相機(jī)開發(fā)時(shí),遇到一個(gè)問題,就是需要監(jiān)聽屏幕旋轉(zhuǎn)。最簡單的就是使用onConfigurationChanged()和OrientationEventListener這兩種方法來實(shí)現(xiàn),但是最后都遇到了問題。

#1 一開始是使用onConfigurationChanged()這個(gè)回調(diào),重新Activity里面的這個(gè)方法就可以了,簡單又方便。用了之后發(fā)現(xiàn),它只能監(jiān)聽,橫屏切豎屏的情況。左橫屏切右橫屏是監(jiān)聽不到的,而且切完之后你也不知道是左橫屏還是右橫屏。下面是使用onConfigurationChanged()進(jìn)行監(jiān)聽的簡單使用。

@Override
? ? public void onConfigurationChanged(Configuration newConfig) {
? ? ? ? super.onConfigurationChanged(newConfig);
? ? ? ? if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
? ? ? ? ? ? // 橫屏
? ? ? ? }else if(newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
? ? ? ? ? ? // 豎屏
? ? ? ? }
? ? }

#2 之后又想到了OrientationEventListener來監(jiān)聽屏幕旋轉(zhuǎn)的實(shí)時(shí)角度,這個(gè)非常靈活,手機(jī)轉(zhuǎn)動(dòng)實(shí)時(shí)角度都會(huì)回調(diào)出來。下面是使用OrientationEventListener的簡單實(shí)現(xiàn)。在適當(dāng)?shù)奈恢谜{(diào)用enable()和disable()來開啟和關(guān)閉監(jiān)聽。

class MyOrientationEventListener extends OrientationEventListener {
?
? ? ? ? private static final int SENSOR_ANGLE = 10;
?
? ? ? ? public MyOrientationEventListener(Context context) {
? ? ? ? ? ? super(context);
? ? ? ? }
?
? ? ? ? @Override
? ? ? ? public void onOrientationChanged(int orientation) {
? ? ? ? ? ? Log.d(TAG, "onOrientationChanged orientation=" + orientation);
? ? ? ? ? ? if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
? ? ? ? ? ? ? ? return; ?//手機(jī)平放時(shí),檢測不到有效的角度
? ? ? ? ? ? }
?
? ? ? ? ? ? //下面是手機(jī)旋轉(zhuǎn)準(zhǔn)確角度與四個(gè)方向角度(0 90 180 270)的轉(zhuǎn)換
? ? ? ? ? ? if (orientation > 360 - SENSOR_ANGLE || orientation < SENSOR_ANGLE) {
? ? ? ? ? ? ? ? orientation = 0;
? ? ? ? ? ? } else if (orientation > 90 - SENSOR_ANGLE && orientation < 90 + SENSOR_ANGLE) {
? ? ? ? ? ? ? ? orientation = 90;
? ? ? ? ? ? } else if (orientation > 180 - SENSOR_ANGLE && orientation < 180 + SENSOR_ANGLE) {
? ? ? ? ? ? ? ? orientation = 180;
? ? ? ? ? ? } else if (orientation > 270 - SENSOR_ANGLE && orientation < 270 + SENSOR_ANGLE) {
? ? ? ? ? ? ? ? orientation = 270;
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? return;
? ? ? ? ? ? }
? ? ? ? }
? ? }
MyOrientationEventListener listener = new MyOrientationEventListener(this);
? ? ? ? listener.enable();
? ? ? ? listener.disable();

但是,它只有當(dāng)手機(jī)豎直握持,然后左右轉(zhuǎn)動(dòng)時(shí)是有效的,手機(jī)平放,左右轉(zhuǎn)動(dòng),是感應(yīng)不到角度變化的。原因是OrientationEventListener原理是只采集了Sensor X和Y方向上的加速度進(jìn)行計(jì)算的??梢詮南旅嬖创a中看到orientation的值只跟X和Y有關(guān)。(下面的源碼取自android.view.OrientationEventListener)而且使用這個(gè)判斷還有一個(gè)弊端,就是當(dāng)屏幕實(shí)際已經(jīng)進(jìn)行旋轉(zhuǎn)切換,但是OrientationEventListener回調(diào)的值還沒到達(dá)旋轉(zhuǎn)后的值。這就導(dǎo)致了系統(tǒng)屏幕旋轉(zhuǎn)了,但是我們app的UI因?yàn)闆]有收到callback而沒有改變的問題。

class SensorEventListenerImpl implements SensorEventListener {
? ? ? ? private static final int _DATA_X = 0;
? ? ? ? private static final int _DATA_Y = 1;
? ? ? ? private static final int _DATA_Z = 2;
? ? ? ??
? ? ? ? public void onSensorChanged(SensorEvent event) {
? ? ? ? ? ? float[] values = event.values;
? ? ? ? ? ? int orientation = ORIENTATION_UNKNOWN;
? ? ? ? ? ? float X = -values[_DATA_X];
? ? ? ? ? ? float Y = -values[_DATA_Y];
? ? ? ? ? ? float Z = -values[_DATA_Z]; ? ? ? ?
? ? ? ? ? ? float magnitude = X*X + Y*Y;
? ? ? ? ? ? // Don't trust the angle if the magnitude is small compared to the y value
? ? ? ? ? ? if (magnitude * 4 >= Z*Z) {
? ? ? ? ? ? ? ? float OneEightyOverPi = 57.29577957855f;
? ? ? ? ? ? ? ? float angle = (float)Math.atan2(-Y, X) * OneEightyOverPi;
? ? ? ? ? ? ? ? orientation = 90 - (int)Math.round(angle);
? ? ? ? ? ? ? ? // normalize to 0 - 359 range
? ? ? ? ? ? ? ? while (orientation >= 360) {
? ? ? ? ? ? ? ? ? ? orientation -= 360;
? ? ? ? ? ? ? ? }?
? ? ? ? ? ? ? ? while (orientation < 0) {
? ? ? ? ? ? ? ? ? ? orientation += 360;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? if (mOldListener != null) {
? ? ? ? ? ? ? ? mOldListener.onSensorChanged(Sensor.TYPE_ACCELEROMETER, event.values);
? ? ? ? ? ? }
? ? ? ? ? ? if (orientation != mOrientation) {
? ? ? ? ? ? ? ? mOrientation = orientation;
? ? ? ? ? ? ? ? onOrientationChanged(orientation);
? ? ? ? ? ? }
? ? ? ? }

#3 為了解決上述問題,其實(shí)最好的就是在系統(tǒng)屏幕旋轉(zhuǎn)的時(shí)候,能有個(gè)回調(diào),告訴我當(dāng)前是哪個(gè)角度,這樣就是最準(zhǔn)確的了。但是onConfigurationChanged只能告訴你是橫的還是豎的,雖然它做不了,但是給了一個(gè)方向。就是屏幕旋轉(zhuǎn)系統(tǒng)調(diào)用onConfigurationChanged的時(shí)候,肯定是知道旋轉(zhuǎn)后的角度的。根據(jù)閱讀源碼可知,當(dāng)屏幕旋轉(zhuǎn)時(shí),會(huì)調(diào)用IRotationWatcher#onRotationChanged(),但是對(duì)app來說是Hide的api,無法對(duì)他進(jìn)行監(jiān)聽。然后又發(fā)現(xiàn)android.hardware.LegacySensorManager類它在構(gòu)造函數(shù)里面,對(duì)IRotationWatcher進(jìn)行了注冊,onRotationChanged()返回的值,也會(huì)保存在sRotation,所以可以在這里做文章了。

public class ScreenOrientationListener extends OrientationEventListener {
?
? ? private static final String TAG = ScreenOrientationListener.class.getSimpleName();
? ? private int mOrientation;
? ? private OnOrientationChangedListener mOnOrientationChangedListener;
? ? private Context mContext;
? ? private Field mFieldRotation;
? ? private Object mOLegacy;
?
? ? public ScreenOrientationListener(Context context) {
? ? ? ? super(context);
? ? ? ? mContext = context;
? ? }
?
? ? public void setOnOrientationChangedListener(OnOrientationChangedListener listener) {
? ? ? ? this.mOnOrientationChangedListener = listener;
? ? }
?
? ? public int getOrientation() {
? ? ? ? int rotation = -1;
? ? ? ? try {
? ? ? ? ? ? if (null == mFieldRotation) {
? ? ? ? ? ? ? ? SensorManager sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
? ? ? ? ? ? ? ? Class clazzLegacy = Class.forName("android.hardware.LegacySensorManager");
? ? ? ? ? ? ? ? Constructor constructor = clazzLegacy.getConstructor(SensorManager.class);
? ? ? ? ? ? ? ? constructor.setAccessible(true);
? ? ? ? ? ? ? ? mOLegacy = constructor.newInstance(sensorManager);
? ? ? ? ? ? ? ? mFieldRotation = clazzLegacy.getDeclaredField("sRotation");
? ? ? ? ? ? ? ? mFieldRotation.setAccessible(true);
? ? ? ? ? ? }
? ? ? ? ? ? rotation = mFieldRotation.getInt(mOLegacy);
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? Log.e(TAG, "getRotation e=" + e.getMessage());
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
// ? ? ? ?Log.d(TAG, "getRotation rotation=" + rotation);
?
? ? ? ? int orientation = -1;
? ? ? ? switch (rotation) {
? ? ? ? ? ? case Surface.ROTATION_0:
? ? ? ? ? ? ? ? orientation = 0;
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case Surface.ROTATION_90:
? ? ? ? ? ? ? ? orientation = 90;
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case Surface.ROTATION_180:
? ? ? ? ? ? ? ? orientation = 180;
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case Surface.ROTATION_270:
? ? ? ? ? ? ? ? orientation = 270;
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? default:
? ? ? ? ? ? ? ? break;
? ? ? ? }
// ? ? ? ?Log.d(TAG, "getRotation orientation=" + orientation);
? ? ? ? return orientation;
? ? }
?
? ? @Override
? ? public void onOrientationChanged(int orientation) {
? ? ? ? if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
? ? ? ? ? ? return; // 手機(jī)平放時(shí),檢測不到有效的角度
? ? ? ? }
? ? ? ? orientation = getOrientation();
? ? ? ? if (mOrientation != orientation) {
? ? ? ? ? ? mOrientation = orientation;
? ? ? ? ? ? if (null != mOnOrientationChangedListener) {
? ? ? ? ? ? ? ? mOnOrientationChangedListener.onOrientationChanged(mOrientation);
? ? ? ? ? ? ? ? Log.d(TAG, "ScreenOrientationListener onOrientationChanged orientation=" + mOrientation);
? ? ? ? ? ? }
? ? ? ? }
? ? }
?
? ? public interface OnOrientationChangedListener {
? ? ? ? void onOrientationChanged(int orientation);
? ? }
}

上面的代碼,就是通過監(jiān)聽OrientationEventListener實(shí)時(shí)角度變化,然后使用反射的方法去獲取LegacySensorManager里面的rotation,這樣拿到的角度就是準(zhǔn)確的,在配合角度變化時(shí)才回調(diào)callback,就完美實(shí)現(xiàn)了4個(gè)方向角度旋轉(zhuǎn)時(shí)的監(jiān)聽。

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論