2

There is CheckBox with following code:

    CheckBox cb = (CheckBox)findViewById(R.id.freezer);
    cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if (isChecked) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
            }
        }
    });

So, when i check it, screen is rotated to default system orientation (landscape for my tablet).

I need to freeze CURRENT orientation. If you turned device to portrait and toggled CheckBox, device rotation must be ingored until CheckBox is unchecked.

Display.getRotation() is not a solution, because each device has it's own Surface.ROTATION

styanton
  • 676
  • 1
  • 9
  • 19

3 Answers3

6

So, here is my solution.

private int getCurentOrientation() {
    Display d = ((WindowManager) getSystemService(WINDOW_SERVICE))
            .getDefaultDisplay();
    boolean isWide = d.getWidth() >= d.getHeight();
    switch (d.getRotation()) {
    case Surface.ROTATION_0:
        return isWide ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
                : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
    case Surface.ROTATION_90:
        return isWide ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
                : ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
    case Surface.ROTATION_180:
        return isWide ? ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
                : ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
    case Surface.ROTATION_270:
        return isWide ? ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
                : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
    }
    return -1;
}

private void lockOrientation(boolean lock) {
    if (lock) {
        setRequestedOrientation(getCurentOrientation());
    } else {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
    }
}

On 4 devices (2 smartphones and 2 tablets) it works as nedded.

styanton
  • 676
  • 1
  • 9
  • 19
1

Since you know how to get the current orientation, just write

if(isChecked){
      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
PrincessLeiha
  • 3,144
  • 4
  • 32
  • 53
  • `Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay(); int orientation = display.getOrientation();` //portrait=1; landscape=2; – PrincessLeiha Apr 25 '12 at 06:29
  • @styanton accept the answers which are correct/ which work for you. – PrincessLeiha Apr 25 '12 at 06:48
  • `Display.getRotation()` returns "the rotation of the screen from its "natural" orientation", so on different devices Surface.ROTATION_0 can be both SCREEN_ORIENTATION_PORTRAIT (for tall screens, like smartphone) and SCREEN_ORIENTATION_LANDSCAPE (for tablets). Thats why this answer os not correct. – styanton Apr 25 '12 at 10:24
  • well @styanton i had adviced `display.getOrientation();` and not `Display.getRotation()` this is some thing you are doing which i did not recommend!!! – PrincessLeiha Apr 25 '12 at 10:42
  • Google documentations says, than `display.getOrientation()` if deprecated, so it should be used just for backward compatibility. I think that `display.getOrientation()` returns the same values. – styanton Apr 25 '12 at 11:22
  • @styanton in your problem you don't need to `getOrienation` you just have to `set` it!!! **i changed the answer** now check if it works – PrincessLeiha Apr 25 '12 at 11:41
  • I need not simply `set` orientation, i need to `freeze` in in some case. Your answer just switches between landscape and portrait. So, your answer **is not correct**. For example device is rotated to REVERSE_PORTRAIT. If CheckBox checked it must stay in this state on **any** device orientation changes, and change to appropriate when checkbox unchecked. – styanton Apr 25 '12 at 12:21
  • Try this: `setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); //Do your operation setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);` – PrincessLeiha Apr 25 '12 at 12:42
1

Create a memeber variable and save current set state. short is_landscape = -1;

oncheckedchange listener you can set your state permanently and save it.

if (is_landscape == -1) {
    Configuration config_screen = getResources().getConfiguration();
    int orientation = config_screen.orientation;
    if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
       setRequestedOrientation(Configuration.ORIENTATION_LANDSCAPE);
       is_landscape = 0;
    } else {
       setRequestedOrientation(Configuration.ORIENTATION_PORTRAIT);
       is_landscape = 1;
   }
}

Problem is that whenever you rotate your device then it recreates your activity so you loose your state. so just save your is_landscape variable on

@Override
protected void onSaveInstanceState(Bundle outState) {
    oustate.putExtra("last_state", is_landscape);
    super.onSaveInstanceState(outState);
}

you can restore your position on on restore instance

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    is_landscape = savedInstanceState.getShort("last_state");
    if (is_landscape == 0) {
        setRequestedOrientation(Configuration.ORIENTATION_LANDSCAPE);
    } else if (is_landscape == 1) {
        setRequestedOrientation(Configuration.ORIENTATION_PORTRAIT);
    }
    super.onRestoreInstanceState(savedInstanceState);
}

If you dont want to save and restore instance then you can use.

android:configChanges="orientation"

in your menifest file it will not allow to recreate activity on changing orientation of your device.

Hope it will work for you.

If you want to detect reverse state also the you can use

int state = (WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay().getRotation();

if state is Surface.ROTATION_0 then it will be portrait if state is Surface.ROTATION_90 then it will be landscape if state is Surface.ROTATION_180 then it will be reverse portrait if state is Surface.ROTATION_270 then it will be reverse landscape

set portrait in case of Surface.ROTATION_0 and Surface.ROTATION_180. set landscape in case of Surface.ROTATION_90 and Surface.ROTATION_270.

you can also set rotation instead of orientation so that your device will be in rotated state instead of oriented state.

Bharat Sharma
  • 3,926
  • 2
  • 17
  • 29
  • Your code will fail on REVERSE_LANDSCAPE and REVERSE_PORTRAIT orientations – styanton Apr 25 '12 at 06:01
  • If it is working for landscape and portrait then you can make it work i have given you idea you only need to detect reverse_landscape and reverse_portrai mode and save its state and restore it – Bharat Sharma Apr 25 '12 at 06:38
  • I have given you idea you can now save your reverse state and restore it onrestoreinstance remaining thing is you only need to detect reverse_landscape and reverse_portrait and save it. – Bharat Sharma Apr 25 '12 at 06:44
  • As i've said lower, `Display.getRotation()` returns "the rotation of the screen from its "natural" orientation", so on different devices Surface.ROTATION_0 can be both SCREEN_ORIENTATION_PORTRAIT (for tall screens, like smartphone) and SCREEN_ORIENTATION_LANDSCAPE (for tablets). – styanton Apr 25 '12 at 10:25
  • ok use two different variable one to save orientation and another to save rotation if orientation is landscape and rotation is less then 180 then it is not reverse else reverse set according to that like that you can try. I am also trying to find some other way. – Bharat Sharma Apr 25 '12 at 10:31