Android: программная настройка «разрешить переориентацию» работает только один раз - PullRequest
3 голосов
/ 07 апреля 2011

У меня есть CheckBoxPreference с ключом "allow_reorientation".Если включено, то моя основная деятельность должна переориентироваться на поворот устройства, а если отключено, оно должно оставаться в своей текущей ориентации.Я установил 'android: configChanges = "direction"' в моем manifest.xml, чтобы разрешить настраиваемую обработку изменений ориентации.

Из моего основного класса активности:

@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        if (preferences.getBoolean("allow_reorientation", true)) {
            switch(newConfig.orientation) {
                case Configuration.ORIENTATION_PORTRAIT:
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    break;
                case Configuration.ORIENTATION_LANDSCAPE:
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    break;
                default:
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
                    break;
            }
        }
    }

Если я начну свойприложение в портретной ориентации, затем поверните устройство в альбомную ориентацию, приведенный выше код вызывается и ведет себя как нужно.Однако этот метод вообще не вызывается при повороте назад в портретный режим, и, конечно, вид остается в альбомной ориентации.

Мое первое предположение состояло в том, что, поскольку я нигде не храню 'newConfig.orientation',вторая переориентация обратно в портрет сравнивала последнее значение ориентации с ранее существовавшим значением, которое все еще указывало портретную ориентацию, и, таким образом, не было обнаружено никакого изменения конфигурации.Однако, если бы это было так, то точка останова, которую я установил в вышеупомянутом методе, будет активирована, когда я попытаюсь сориентироваться в ландшафте во второй раз, но метод никогда не вызывается в этом случае.

Может кто-то пожалуйстаобъяснить, что происходит, и предложить лекарство?

Огромное спасибо.

РЕШЕНИЕ - Благодарю Мэтью Уиллиса ниже

В YourApp, который расширяет приложение:

public void updateOrientationConfiguration(Activity activity) {
    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
    if (preferences.getBoolean("allow_reorientation", true)) {
        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
    } else {
        if (activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }
        if (activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
    }
}

В YourActivity, который расширяет активность:

    public void onResume() {
        super.onResume();
        YourApp app = (YourApp)this.getApplication();
        app.updateOrientationConfiguration(this);
    }

Ответы [ 2 ]

7 голосов
/ 07 апреля 2011

Альтернативным методом является использование ActivityInfo.SCREEN_ORIENTATION_SENSOR и ActivityInfo.SCREEN_ORIENTATION_NOSENSOR .

В основном вы устанавливаете одно или другое на основе ваших предпочтений, и тогда вам не нужно вводить onConfigurationChanged (или указывать configChanges в манифесте).

Пример деятельности:

public class Main extends Activity {
    private static boolean locked = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        doLock();
    }

    public void doLock() {
        if (locked) {
            if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }
            if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            }
        } else {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
        }
    }

    public void toggle(View v) {
        locked = !locked;
        doLock();
    }
}

При тестировании я заметил, что SCREEN_ORIENTATION_NOSENSOR также вызывает поворот в ориентацию по умолчанию, поэтому необходимо явно использовать _LANDSCAPE и _PORTRAIT.

0 голосов
/ 07 апреля 2011

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

Проводите ли вы функциональное тестирование после изменения ориентации или просто смотрите на экран? Может случиться так, что super. onConfigurationChanged () - это место, где изменяется макет, и код застревает в цикле при вызове setRequestedOrientation

Надеюсь, это поможет,

Фил Лелло

...