【问题标题】:Override onConfigurationChanged while maintaining portrait mode在保持纵向模式的同时覆盖 onConfigurationChanged
【发布时间】:2017-04-08 07:54:10
【问题描述】:

如何在将布局保持在纵向模式的同时检测横向模式?

我有一项活动,无论实际移动方向如何,都可以保持纵向模式。我可以通过将android:screenOrientation="portrait" 添加到清单中的活动配置来做到这一点。

但是,我想在保持纵向活动的同时检测 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 旋转到横向模式。 重复最初的问题,如何在将布局保持在纵向模式的同时检测横向模式?

【问题讨论】:

  • 我尝试了几个 sn-ps 但问题是如果我们使用清单或运行时设置或请求纵向布局,我们无法获得onConfigurationChanged 的回调。我们需要像观察者这样的东西来观察手机配置的变化并在方向改变时触发事件。
  • @BipinVayalu - 是的,你是对的。我正在寻找那个观察者或类似的人。

标签: android android-layout android-configchanges onconfigurationchanged


【解决方案1】:

您可以使用 CustomOrientationEventListener 而不会影响实际的方向更改

在你的活动中

  ...
  private CustomOrientationEventListener customOrientationEventListener;
  ...

 customOrientationEventListener = new CustomOrientationEventListener(mContext) {
        @Override
        public void onSimpleOrientationChanged(int orientation) {
       }
 };

 customOrientationEventListener.enable();

独立类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);

}

【讨论】:

  • 非常有趣。 customOrientationEventListener 是如何绑定到活动或上下文的?我们不需要像this.setOrientationEventListener 这样的事情吗?
  • 您可以扩展类并对其进行覆盖onSimpleOrientationChanged,或者您可以将其用作匿名类,您可以在答案中看到!
  • @KishoreJethava 我按照您的示例尝试了您的代码,但无法获得onSimpleOrientationChanged 回调。你能展示一下我们是如何绑定监听器的吗?
  • 抱歉我忘记添加启用监听器customOrientationEventListener.enable();查看更新答案!
  • 对您的onOrientationChanged 进行细微更改后,您的解决方案完美运行。惊人的答案,谢谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多