Как определить поворот экрана на 180 градусов от альбомной до альбомной ориентации?

Я видел несколько других вопросов, похожих на это, но ответов нет.

Вращаясь от портрета к ландшафту (в любом направлении) и обратно, мы получаем полезный вызов onConfigurationChanged().

Однако при повороте из пейзажа в ландшафт (на 180 градусов) onConfigurationChanged() не вызывается.

Я видел упоминание об использовании OrientationEventListener, но мне это кажется странным, потому что вы можете быстро вращаться, не вызывая изменения ориентации дисплея.

Я попытался добавить слушателя изменения макета, но безуспешно.

Таким образом, вопрос заключается в том, как надежно обнаружить такое изменение в альбомной ориентации?

4 ответа

Решение

OrientationEventlistener не будет работать, когда устройство не вращается / движется.

Я считаю, что прослушивание экрана - лучший способ обнаружить изменения.

     DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() {
        @Override
        public void onDisplayAdded(int displayId) {
           android.util.Log.i(TAG, "Display #" + displayId + " added.");
        }

        @Override
        public void onDisplayChanged(int displayId) {
           android.util.Log.i(TAG, "Display #" + displayId + " changed.");
        }

        @Override
        public void onDisplayRemoved(int displayId) {
           android.util.Log.i(TAG, "Display #" + displayId + " removed.");
        }
     };
     DisplayManager displayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
     displayManager.registerDisplayListener(mDisplayListener, UIThreadHandler);

Может быть, вы должны добавить некоторый логический код в свой OrientationEventListener, например так:

mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);

OrientationEventListener orientationEventListener = new OrientationEventListener(this,
        SensorManager.SENSOR_DELAY_NORMAL) {
    @Override
    public void onOrientationChanged(int orientation) {

        Display display = mWindowManager.getDefaultDisplay();
        int rotation = display.getRotation();
        if ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) && rotation != mLastRotation) {
            Log.i(TAG, "changed >>> " + rotation);

            // do something

            mLastRotation = rotation;
        }
    }
};

if (orientationEventListener.canDetectOrientation()) {
    orientationEventListener.enable();
}

Я использую этот код, чтобы он работал для моего случая.

  OrientationEventListener mOrientationEventListener = new OrientationEventListener(mActivity)
  {
     @Override
     public void onOrientationChanged(int orientation)
     {
        if (orientation == ORIENTATION_UNKNOWN) return;

        int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
        switch (rotation) {
          case Surface.ROTATION_0:
             android.util.Log.i(TAG, "changed ROTATION_0 - " + orientation);
             break;
          case Surface.ROTATION_90:
             android.util.Log.i(TAG, "changed ROTATION_90 - " + orientation);
             break;
          case Surface.ROTATION_180:
             android.util.Log.i(TAG, "changed ROTATION_180 - " + orientation);
             break;
          case Surface.ROTATION_270:
             android.util.Log.i(TAG, "changed ROTATION_270 - " + orientation);
             break;
        }
        if ((rotation != mLastRotation) && (rotation & 0x1) == (mLastRotation & 0x1))
        {
           android.util.Log.i(TAG, "unhandled orientation changed >>> " + rotation);
        }
        mLastRotation = rotation;
     }
  };

  if (mOrientationEventListener.canDetectOrientation()){
     mOrientationEventListener.enable();
  }

Вы все равно захотите использовать класс прослушивателя дисплея: Google рекомендует его для обработки поворотов устройства на 180 градусов из разблокированной ориентации. Вы не можете просто обрабатывать все обратные вызовы onDisplayChanged как повороты на 180 градусов. Более полная реализация от Google показывает, как получить вращение дисплея из диспетчера дисплея во время обратного вызова onDisplayChanged, упомянутого user2870070 .

      /** DisplayManager to listen to display changes */
private val displayManager: DisplayManager by lazy {
    applicationContext.getSystemService(DISPLAY_SERVICE) as DisplayManager
}

/** Keeps track of display rotations */
private var displayRotation = 0

...

override fun onAttachedToWindow() {
    super.onAttachedToWindow()
    displayManager.registerDisplayListener(displayListener, mainLooperHandler)
}

override fun onDetachedFromWindow() {
    super.onDetachedFromWindow()
    displayManager.unregisterDisplayListener(displayListener)
}

private val displayListener = object : DisplayManager.DisplayListener {
    override fun onDisplayAdded(displayId: Int) {}
    override fun onDisplayRemoved(displayId: Int) {}
    override fun onDisplayChanged(displayId: Int) {
        val difference = displayManager.getDisplay(displayId).rotation - displayRotation
        displayRotation = displayManager.getDisplay(displayId).rotation

        if (difference == 2 || difference == -2) {
            createCaptureSession()
        }
    }
}
Другие вопросы по тегам