在保持纵向模式的同时覆盖 onConfigurationChanged
Override onConfigurationChanged while maintaining portrait mode
如何在保持纵向模式布局的同时检测横向模式?
我有一个 activity 可以保持纵向模式,而不管实际的移动方向如何。我可以通过将 android:screenOrientation="portrait"
添加到我的清单中的 activity 配置来做到这一点。
但是,我想在保持纵向 activity 的同时检测 screenOrientation。
我试过以下代码:
@Override
public void onConfigurationChanged(Configuration newConfig) {
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
recordConfigChanges(newConfig); // Performs some variable changes or similar
}
// Maintain activity in portrait mode itself
Configuration customConfig = newConfig;
customConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
super.onConfigurationChanged(customConfig);
}
上面的代码没有保持纵向,而是将 UI 旋转为横向模式。
重申最初的问题,如何在保持纵向模式布局的同时检测横向模式?
您可以使用 CustomOrientationEventListener 而不会影响实际的方向变化
在你的 activity
...
private CustomOrientationEventListener customOrientationEventListener;
...
customOrientationEventListener = new CustomOrientationEventListener(mContext) {
@Override
public void onSimpleOrientationChanged(int orientation) {
}
};
customOrientationEventListener.enable();
独立 class CustomOrientationEventListener
public abstract class CustomOrientationEventListener extends OrientationEventListener {
private String TAG="CustomOrientation";
private static final int CONFIGURATION_ORIENTATION_UNDEFINED = Configuration.ORIENTATION_UNDEFINED;
private volatile int defaultScreenOrientation = CONFIGURATION_ORIENTATION_UNDEFINED;
private int prevOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
private Context ctx;
private final int ROTATION_O = 1;
private final int ROTATION_90 = 2;
private final int ROTATION_180 = 3;
private final int ROTATION_270 = 4;
private int rotation = 0;
private ReentrantLock lock = new ReentrantLock(true);
public CustomOrientationEventListener(Context context) {
super(context);
ctx = context;
}
public CustomOrientationEventListener(Context context, int rate) {
super(context, rate);
ctx = context;
}
@Override
public void onOrientationChanged(final int orientation) {
//return if auto rotate disabled. should rotate if auto rotate enabled only
if (android.provider.Settings.System.getInt(ctx.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0) == 0) // 0 = Auto Rotate Disabled
return;
int currentOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
if (orientation >= 340 || orientation < 20 && rotation != ROTATION_O) {
currentOrientation = Surface.ROTATION_0;
rotation = ROTATION_O;
} else if (orientation >= 70 && orientation < 110 && rotation != ROTATION_90) {
currentOrientation = Surface.ROTATION_90;
rotation = ROTATION_90;
} else if (orientation >= 160 && orientation < 200 && rotation != ROTATION_180) {
currentOrientation = Surface.ROTATION_180;
rotation = ROTATION_180;
} else if (orientation >= 250 && orientation < 290 && rotation != ROTATION_270) {
currentOrientation = Surface.ROTATION_270;
rotation = ROTATION_270;
}
if (prevOrientation != currentOrientation
&& orientation != OrientationEventListener.ORIENTATION_UNKNOWN) {
prevOrientation = currentOrientation;
if (currentOrientation != OrientationEventListener.ORIENTATION_UNKNOWN)
reportOrientationChanged(currentOrientation);
}
}
private void reportOrientationChanged(final int currentOrientation) {
int defaultOrientation = getDeviceDefaultOrientation();
int orthogonalOrientation = defaultOrientation == Configuration.ORIENTATION_LANDSCAPE ? Configuration.ORIENTATION_PORTRAIT
: Configuration.ORIENTATION_LANDSCAPE;
int toReportOrientation;
if (currentOrientation == Surface.ROTATION_0
|| currentOrientation == Surface.ROTATION_180)
toReportOrientation = defaultOrientation;
else
toReportOrientation = orthogonalOrientation;
onSimpleOrientationChanged(toReportOrientation);
}
/**
* Must determine what is default device orientation (some tablets can have
* default landscape). Must be initialized when device orientation is
* defined.
*
* @return value of {@link Configuration#ORIENTATION_LANDSCAPE} or
* {@link Configuration#ORIENTATION_PORTRAIT}
*/
private int getDeviceDefaultOrientation() {
if (defaultScreenOrientation == CONFIGURATION_ORIENTATION_UNDEFINED) {
lock.lock();
defaultScreenOrientation = initDeviceDefaultOrientation(ctx);
lock.unlock();
}
return defaultScreenOrientation;
}
/**
* Provides device default orientation
*
* @return value of {@link Configuration#ORIENTATION_LANDSCAPE} or
* {@link Configuration#ORIENTATION_PORTRAIT}
*/
private int initDeviceDefaultOrientation(Context context) {
WindowManager windowManager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
Configuration config = context.getResources().getConfiguration();
int rotation = windowManager.getDefaultDisplay().getRotation();
boolean isLand = config.orientation == Configuration.ORIENTATION_LANDSCAPE;
boolean isDefaultAxis = rotation == Surface.ROTATION_0
|| rotation == Surface.ROTATION_180;
int result = CONFIGURATION_ORIENTATION_UNDEFINED;
if ((isDefaultAxis && isLand) || (!isDefaultAxis && !isLand)) {
result = Configuration.ORIENTATION_LANDSCAPE;
} else {
result = Configuration.ORIENTATION_PORTRAIT;
}
return result;
}
/**
* Fires when orientation changes from landscape to portrait and vice versa.
*
* @param orientation
* value of {@link Configuration#ORIENTATION_LANDSCAPE} or
* {@link Configuration#ORIENTATION_PORTRAIT}
*/
public abstract void onSimpleOrientationChanged(int orientation);
}
如何在保持纵向模式布局的同时检测横向模式?
我有一个 activity 可以保持纵向模式,而不管实际的移动方向如何。我可以通过将 android:screenOrientation="portrait"
添加到我的清单中的 activity 配置来做到这一点。
但是,我想在保持纵向 activity 的同时检测 screenOrientation。
我试过以下代码:
@Override
public void onConfigurationChanged(Configuration newConfig) {
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
recordConfigChanges(newConfig); // Performs some variable changes or similar
}
// Maintain activity in portrait mode itself
Configuration customConfig = newConfig;
customConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
super.onConfigurationChanged(customConfig);
}
上面的代码没有保持纵向,而是将 UI 旋转为横向模式。 重申最初的问题,如何在保持纵向模式布局的同时检测横向模式?
您可以使用 CustomOrientationEventListener 而不会影响实际的方向变化
在你的 activity
...
private CustomOrientationEventListener customOrientationEventListener;
...
customOrientationEventListener = new CustomOrientationEventListener(mContext) {
@Override
public void onSimpleOrientationChanged(int orientation) {
}
};
customOrientationEventListener.enable();
独立 class CustomOrientationEventListener
public abstract class CustomOrientationEventListener extends OrientationEventListener {
private String TAG="CustomOrientation";
private static final int CONFIGURATION_ORIENTATION_UNDEFINED = Configuration.ORIENTATION_UNDEFINED;
private volatile int defaultScreenOrientation = CONFIGURATION_ORIENTATION_UNDEFINED;
private int prevOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
private Context ctx;
private final int ROTATION_O = 1;
private final int ROTATION_90 = 2;
private final int ROTATION_180 = 3;
private final int ROTATION_270 = 4;
private int rotation = 0;
private ReentrantLock lock = new ReentrantLock(true);
public CustomOrientationEventListener(Context context) {
super(context);
ctx = context;
}
public CustomOrientationEventListener(Context context, int rate) {
super(context, rate);
ctx = context;
}
@Override
public void onOrientationChanged(final int orientation) {
//return if auto rotate disabled. should rotate if auto rotate enabled only
if (android.provider.Settings.System.getInt(ctx.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0) == 0) // 0 = Auto Rotate Disabled
return;
int currentOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
if (orientation >= 340 || orientation < 20 && rotation != ROTATION_O) {
currentOrientation = Surface.ROTATION_0;
rotation = ROTATION_O;
} else if (orientation >= 70 && orientation < 110 && rotation != ROTATION_90) {
currentOrientation = Surface.ROTATION_90;
rotation = ROTATION_90;
} else if (orientation >= 160 && orientation < 200 && rotation != ROTATION_180) {
currentOrientation = Surface.ROTATION_180;
rotation = ROTATION_180;
} else if (orientation >= 250 && orientation < 290 && rotation != ROTATION_270) {
currentOrientation = Surface.ROTATION_270;
rotation = ROTATION_270;
}
if (prevOrientation != currentOrientation
&& orientation != OrientationEventListener.ORIENTATION_UNKNOWN) {
prevOrientation = currentOrientation;
if (currentOrientation != OrientationEventListener.ORIENTATION_UNKNOWN)
reportOrientationChanged(currentOrientation);
}
}
private void reportOrientationChanged(final int currentOrientation) {
int defaultOrientation = getDeviceDefaultOrientation();
int orthogonalOrientation = defaultOrientation == Configuration.ORIENTATION_LANDSCAPE ? Configuration.ORIENTATION_PORTRAIT
: Configuration.ORIENTATION_LANDSCAPE;
int toReportOrientation;
if (currentOrientation == Surface.ROTATION_0
|| currentOrientation == Surface.ROTATION_180)
toReportOrientation = defaultOrientation;
else
toReportOrientation = orthogonalOrientation;
onSimpleOrientationChanged(toReportOrientation);
}
/**
* Must determine what is default device orientation (some tablets can have
* default landscape). Must be initialized when device orientation is
* defined.
*
* @return value of {@link Configuration#ORIENTATION_LANDSCAPE} or
* {@link Configuration#ORIENTATION_PORTRAIT}
*/
private int getDeviceDefaultOrientation() {
if (defaultScreenOrientation == CONFIGURATION_ORIENTATION_UNDEFINED) {
lock.lock();
defaultScreenOrientation = initDeviceDefaultOrientation(ctx);
lock.unlock();
}
return defaultScreenOrientation;
}
/**
* Provides device default orientation
*
* @return value of {@link Configuration#ORIENTATION_LANDSCAPE} or
* {@link Configuration#ORIENTATION_PORTRAIT}
*/
private int initDeviceDefaultOrientation(Context context) {
WindowManager windowManager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
Configuration config = context.getResources().getConfiguration();
int rotation = windowManager.getDefaultDisplay().getRotation();
boolean isLand = config.orientation == Configuration.ORIENTATION_LANDSCAPE;
boolean isDefaultAxis = rotation == Surface.ROTATION_0
|| rotation == Surface.ROTATION_180;
int result = CONFIGURATION_ORIENTATION_UNDEFINED;
if ((isDefaultAxis && isLand) || (!isDefaultAxis && !isLand)) {
result = Configuration.ORIENTATION_LANDSCAPE;
} else {
result = Configuration.ORIENTATION_PORTRAIT;
}
return result;
}
/**
* Fires when orientation changes from landscape to portrait and vice versa.
*
* @param orientation
* value of {@link Configuration#ORIENTATION_LANDSCAPE} or
* {@link Configuration#ORIENTATION_PORTRAIT}
*/
public abstract void onSimpleOrientationChanged(int orientation);
}