|
|
|
@ -5,6 +5,8 @@ import android.hardware.SensorManager; |
|
|
|
|
import androidx.annotation.NonNull; |
|
|
|
|
import androidx.annotation.VisibleForTesting; |
|
|
|
|
|
|
|
|
|
import android.hardware.display.DisplayManager; |
|
|
|
|
import android.os.Build; |
|
|
|
|
import android.view.Display; |
|
|
|
|
import android.view.OrientationEventListener; |
|
|
|
|
import android.view.Surface; |
|
|
|
@ -12,21 +14,28 @@ import android.view.WindowManager; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Helps with keeping track of both device orientation (which changes when device is rotated) |
|
|
|
|
* and the display offset (which depends on the activity orientation |
|
|
|
|
* wrt the device default orientation). |
|
|
|
|
* and the display offset (which depends on the activity orientation wrt the device default |
|
|
|
|
* orientation). |
|
|
|
|
*/ |
|
|
|
|
public class OrientationHelper { |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Receives callback about the device orientation changes. |
|
|
|
|
* Receives callback about the orientation changes. |
|
|
|
|
*/ |
|
|
|
|
public interface Callback { |
|
|
|
|
void onDeviceOrientationChanged(int deviceOrientation); |
|
|
|
|
void onDisplayOffsetChanged(int displayOffset, boolean willRecreate); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@VisibleForTesting final OrientationEventListener mListener; |
|
|
|
|
private final Context mContext; |
|
|
|
|
private final Callback mCallback; |
|
|
|
|
|
|
|
|
|
@VisibleForTesting |
|
|
|
|
final OrientationEventListener mDeviceOrientationListener; |
|
|
|
|
private int mDeviceOrientation = -1; |
|
|
|
|
|
|
|
|
|
@VisibleForTesting |
|
|
|
|
final DisplayManager.DisplayListener mDisplayOffsetListener; |
|
|
|
|
private int mDisplayOffset = -1; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -35,57 +44,78 @@ public class OrientationHelper { |
|
|
|
|
* @param callback a {@link Callback} |
|
|
|
|
*/ |
|
|
|
|
public OrientationHelper(@NonNull Context context, @NonNull Callback callback) { |
|
|
|
|
mContext = context; |
|
|
|
|
mCallback = callback; |
|
|
|
|
mListener = new OrientationEventListener(context.getApplicationContext(), |
|
|
|
|
mDeviceOrientationListener = new OrientationEventListener(context.getApplicationContext(), |
|
|
|
|
SensorManager.SENSOR_DELAY_NORMAL) { |
|
|
|
|
|
|
|
|
|
@SuppressWarnings("ConstantConditions") |
|
|
|
|
@Override |
|
|
|
|
public void onOrientationChanged(int orientation) { |
|
|
|
|
int or = 0; |
|
|
|
|
int deviceOrientation = 0; |
|
|
|
|
if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) { |
|
|
|
|
or = mDeviceOrientation != -1 ? mDeviceOrientation : 0; |
|
|
|
|
deviceOrientation = mDeviceOrientation != -1 ? mDeviceOrientation : 0; |
|
|
|
|
} else if (orientation >= 315 || orientation < 45) { |
|
|
|
|
or = 0; |
|
|
|
|
deviceOrientation = 0; |
|
|
|
|
} else if (orientation >= 45 && orientation < 135) { |
|
|
|
|
or = 90; |
|
|
|
|
deviceOrientation = 90; |
|
|
|
|
} else if (orientation >= 135 && orientation < 225) { |
|
|
|
|
or = 180; |
|
|
|
|
deviceOrientation = 180; |
|
|
|
|
} else if (orientation >= 225 && orientation < 315) { |
|
|
|
|
or = 270; |
|
|
|
|
deviceOrientation = 270; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (or != mDeviceOrientation) { |
|
|
|
|
mDeviceOrientation = or; |
|
|
|
|
if (deviceOrientation != mDeviceOrientation) { |
|
|
|
|
mDeviceOrientation = deviceOrientation; |
|
|
|
|
mCallback.onDeviceOrientationChanged(mDeviceOrientation); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
if (Build.VERSION.SDK_INT >= 17) { |
|
|
|
|
mDisplayOffsetListener = new DisplayManager.DisplayListener() { |
|
|
|
|
public void onDisplayAdded(int displayId) { } |
|
|
|
|
public void onDisplayRemoved(int displayId) { } |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void onDisplayChanged(int displayId) { |
|
|
|
|
int oldDisplayOffset = mDisplayOffset; |
|
|
|
|
int newDisplayOffset = findDisplayOffset(); |
|
|
|
|
if (newDisplayOffset != oldDisplayOffset) { |
|
|
|
|
mDisplayOffset = newDisplayOffset; |
|
|
|
|
// With 180 degrees flips, the activity is not recreated.
|
|
|
|
|
boolean willRecreate = Math.abs(newDisplayOffset - oldDisplayOffset) != 180; |
|
|
|
|
mCallback.onDisplayOffsetChanged(newDisplayOffset, willRecreate); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
} else { |
|
|
|
|
mDisplayOffsetListener = null; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Enables this listener. |
|
|
|
|
* @param context a context |
|
|
|
|
*/ |
|
|
|
|
public void enable(@NonNull Context context) { |
|
|
|
|
Display display = ((WindowManager) context |
|
|
|
|
.getSystemService(Context.WINDOW_SERVICE)) |
|
|
|
|
.getDefaultDisplay(); |
|
|
|
|
switch (display.getRotation()) { |
|
|
|
|
case Surface.ROTATION_0: mDisplayOffset = 0; break; |
|
|
|
|
case Surface.ROTATION_90: mDisplayOffset = 90; break; |
|
|
|
|
case Surface.ROTATION_180: mDisplayOffset = 180; break; |
|
|
|
|
case Surface.ROTATION_270: mDisplayOffset = 270; break; |
|
|
|
|
default: mDisplayOffset = 0; break; |
|
|
|
|
public void enable() { |
|
|
|
|
mDisplayOffset = findDisplayOffset(); |
|
|
|
|
if (Build.VERSION.SDK_INT >= 17) { |
|
|
|
|
DisplayManager manager = (DisplayManager) |
|
|
|
|
mContext.getSystemService(Context.DISPLAY_SERVICE); |
|
|
|
|
manager.registerDisplayListener(mDisplayOffsetListener, null); |
|
|
|
|
} |
|
|
|
|
mListener.enable(); |
|
|
|
|
mDeviceOrientationListener.enable(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Disables this listener. |
|
|
|
|
*/ |
|
|
|
|
public void disable() { |
|
|
|
|
mListener.disable(); |
|
|
|
|
mDeviceOrientationListener.disable(); |
|
|
|
|
if (Build.VERSION.SDK_INT >= 17) { |
|
|
|
|
DisplayManager manager = (DisplayManager) |
|
|
|
|
mContext.getSystemService(Context.DISPLAY_SERVICE); |
|
|
|
|
manager.unregisterDisplayListener(mDisplayOffsetListener); |
|
|
|
|
} |
|
|
|
|
mDisplayOffset = -1; |
|
|
|
|
mDeviceOrientation = -1; |
|
|
|
|
} |
|
|
|
@ -94,7 +124,8 @@ public class OrientationHelper { |
|
|
|
|
* Returns the current device orientation. |
|
|
|
|
* @return device orientation |
|
|
|
|
*/ |
|
|
|
|
public int getDeviceOrientation() { |
|
|
|
|
@SuppressWarnings("WeakerAccess") |
|
|
|
|
public int getLastDeviceOrientation() { |
|
|
|
|
return mDeviceOrientation; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -102,7 +133,20 @@ public class OrientationHelper { |
|
|
|
|
* Returns the current display offset. |
|
|
|
|
* @return display offset |
|
|
|
|
*/ |
|
|
|
|
public int getDisplayOffset() { |
|
|
|
|
public int getLastDisplayOffset() { |
|
|
|
|
return mDisplayOffset; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private int findDisplayOffset() { |
|
|
|
|
Display display = ((WindowManager) mContext |
|
|
|
|
.getSystemService(Context.WINDOW_SERVICE)) |
|
|
|
|
.getDefaultDisplay(); |
|
|
|
|
switch (display.getRotation()) { |
|
|
|
|
case Surface.ROTATION_0: return 0; |
|
|
|
|
case Surface.ROTATION_90: return 90; |
|
|
|
|
case Surface.ROTATION_180: return 180; |
|
|
|
|
case Surface.ROTATION_270: return 270; |
|
|
|
|
default: return 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|