i'm steve

Orientation Hinting in Android

Sun 06 Sep 2014

Just a quick note on implemeting “orientation hinting” with a default orientation lock at the start. What it actually means:

Say, an activity is defaulted to landscape mode lock, and still allowing the user to change back to portrait only when the user intentionally doing so (rotate the devices to landscape then back to portrait).

This is particularly helpful in a situation where the user would be shown and locked into a preferred mode no matter how he/she holding the device, while still offering a mechanism to change orientation if the user intends to.

How

OrientationEventListener & setRequestedOrientation is the core of this dirty hack.

public class DemoActivity extends Activity {
  OrientationEventListener ol;
  boolean orientationUnlockFlag; // a flag to make sure user intends to change orientation

  public void onCreate(Bundle savedInstanceState) {
    // Say landscape mode is the default orientation to be shown to user
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

    // Listen to sensor event
    ol = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) {

      @Override
      public void onOrientationChanged(int orientation) {
        // check if it's in landscape lock as we landscape was chosen as the default
        if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
          // Make sure the activity shown is in landscape at start
          if (orientationUnlockFlag) {
            // So now device is free to change any orientation in sensor mode
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

            // 260 - 300 indicate anti-clockwise-landscape, while 80-100 clockwise-landscape
          } else if ((orientation >= 260 && orientation <= 300)
                     || (orientation >= 80 && orientation <= 100)) {

            // User turned landscape once,
            // so unlock flag indicating it can be turned into sensor mode -- SCREEN_ORIENTATION_SENSOR,
            // allowing it to switch freely to portrait
            orientationUnlockFlag = true;
          }
        }
      }
    };

    ol.enable();
  }

  public void onDestroy() {
    super.onDestroy();
    ol.disable();
  }
}

This hack here is to first set the default orientation lock, landscape in this example, first thing in the onCreate method. Then prepare the OrientationEventListener to listen on sensor events. When landscape event (clockwise or anti-clockwise) followed by a portrait event is detected, it will then dismiss the orientation lock by setting it to follow the sensor. The “orientationUnlockFlag” here serves two purposes:

  1. to make sure default orientation, landscape in this case, is shown no matter how the device was holded initially
  2. to act as a lock, only when user intended to break the default orientation (landscape-2-portrait event is detected), will it set the orientation to be sensor-based afterwards (hinting part).

Note that, onConfigurationChanged was not used in this case, due to the fact that, it won’t receive any orientation event other than the initial landscape once it’s landscape locked, thus not able to do the hinting part.