Как определить изменение ориентации в макете в Android?

Я только что реализовал функцию изменения ориентации - например, когда макет меняется с книжного на альбомный (или наоборот). Как я могу определить, когда событие изменения ориентации закончено.

OrientationEventListener не работает. Как я могу получать уведомления о событиях изменения ориентации макета?

Ответ 1

Используйте метод Activity onConfigurationChanged. См. Следующий код:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}

Вам также нужно отредактировать соответствующий элемент в файле манифеста, чтобы включить android: configChanges Посмотрите код ниже:

<activity android:name=".MyActivity"
          android:configChanges="orientation|keyboardHidden"
          android:label="@string/app_name">

ПРИМЕЧАНИЕ: с Android 3.2 (уровень API 13) или выше, "размер экрана" также изменяется, когда устройство переключается между портретной и альбомной ориентацией. Таким образом, если вы хотите предотвратить перезапуск во время изменения ориентации при разработке для уровня API 13 или выше, вы должны объявить android: configChanges = "orientation | screenSize" для уровня API 13 или выше.

Надеюсь, это поможет вам...:)

Ответ 2

Для загрузки макета в папке layout-land у вас есть два отдельных макета, тогда вы должны сделать setContentView в onConfigurationChanged.

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        setContentView(R.layout.yourxmlinlayout-land);
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        setContentView(R.layout.yourxmlinlayoutfolder);
    }
}

Если у вас есть только один макет, то нет необходимости делать setContentView в этом методе. просто

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}

Ответ 3

Просто хотел показать вам способ сохранить весь свой пакет после onConfigurationChanged:

Создайте новый пакет сразу после вашего класса:

public class MainActivity extends Activity {
    Bundle newBundy = new Bundle();

Далее, после того, как "protected void onCreate" добавьте это:

@Override
public void onConfigurationChanged(Configuration newConfig) {
     super.onConfigurationChanged(newConfig);
     if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            onSaveInstanceState(newBundy);
        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            onSaveInstanceState(newBundy);
        }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBundle("newBundy", newBundy);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    savedInstanceState.getBundle("newBundy");
}

Если вы добавите это, все ваши разбитые классы в MainActivity будут сохранены.

Но лучше всего добавить это в свой AndroidManifest:

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>

Ответ 4

используйте этот метод

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
    {
        Toast.makeText(getActivity(),"PORTRAIT",Toast.LENGTH_LONG).show();
       //add your code what you want to do when screen on PORTRAIT MODE
    }
    else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
    {
        Toast.makeText(getActivity(),"LANDSCAPE",Toast.LENGTH_LONG).show();
        //add your code what you want to do when screen on LANDSCAPE MODE
   }
}

И не забудьте добавить это в свой Androidmainfest.xml

android:configChanges="orientation|screenSize"

как это

<activity android:name=".MainActivity"
          android:theme="@style/Theme.AppCompat.NoActionBar"
          android:configChanges="orientation|screenSize">

    </activity>

Ответ 6

Создайте экземпляр класса OrientationEventListener и включите его.

OrientationEventListener mOrientationEventListener = new OrientationEventListener(YourActivity.this) {
    @Override
    public void onOrientationChanged(int orientation) {
        Log.d(TAG,"orientation = " + orientation);
    }
};

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

Ответ 7

Я просто хочу предложить другую альтернативу, которая действительно затронет некоторых из вас, как описано выше:

android:configChanges="orientation|keyboardHidden" 

подразумевает, что мы явно объявляем макет для внедрения.

В случае, если мы хотим сохранить автоматический впрыск благодаря папкам layout-land и layout. Все, что вам нужно сделать, это добавить его в onCreate:

    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
        getSupportActionBar().hide();

    } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        getSupportActionBar().show();
    }

Здесь мы показываем или нет панель действий в зависимости от ориентации телефона

Ответ 8

Если принятый ответ не работает, убедитесь, что вы не определили в файле манифеста:

android:screenOrientation="portrait"

Это мой случай.

Ответ 9

В случае, если это полезно для некоторых новых разработчиков, потому что это не указано выше. Просто чтобы быть очень явным:

Если вы используете onConfigurationChanged, вам нужно две вещи:

  1. Метод onConfigurationChanged в вашем классе деятельности

  2. Укажите в своем манифесте, какие изменения конфигурации будут обрабатываться вашим методом onConfigurationChanged

Фрагмент манифеста в приведенных выше ответах, хотя он, без сомнения, корректен для конкретного приложения, к которому принадлежит манифест, является НЕ именно тем, что нужно добавить в манифест, чтобы вызвать метод onConfigurationChanged в ваш класс деятельности. то есть приведенная ниже запись манифеста может быть неправильной для вашего приложения.

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>

В приведенной выше записи манифеста есть различные действия Android для android:configChanges="", которые могут вызвать onCreate в вашем жизненном цикле Activity.

Это очень важно - НЕ указываются в манифесте те, которые запускают ваши onCreate и . Те, которые указаны в манифесте, запускают ваш метод onConfigurationChanged в вашем Класс деятельности.

Таким образом, вам нужно определить, какие изменения конфигурации вам нужно обрабатывать самостоятельно. Для Android Encyclopedically Challenge, как я, я использовал всплывающие подсказки в Android Studio и добавил почти все возможные варианты конфигурации. Перечисление всего этого в основном говорит, что я обработаю все, и onCreate никогда не будет вызываться из-за конфигураций.

<activity name= ".MainActivity" android:configChanges="screenLayout|touchscreen|mnc|mcc|density|uiMode|fontScale|orientation|keyboard|layoutDirection|locale|navigation|smallestScreenSize|keyboardHidden|colorMode|screenSize"/>

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

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

В итоге у меня было 3, которые первоначально запускали onCreate, затем я тестировал на S10+, и я все еще получал onCreate, поэтому мне пришлось снова выполнить упражнение на устранение, и мне также был нужен |screenSize. Так что тестируйте на выбор платформ.

<activity name= ".MainActivity" android:configChanges="screenLayout|uiMode|orientation|screenSize"/>

Так что мое предложение, хотя я уверен, что кто-то может пробить дыры в этом:

  1. Добавьте свой метод onConfigurationChanged в свой класс активности с помощью TOAST или LOG, чтобы вы могли видеть, когда он работает.

  2. Добавьте все возможные параметры конфигурации в манифест.

  3. Убедитесь, что ваш метод onConfigurationChanged работает, протестировав ваше приложение.

  4. Удалите каждый параметр конфигурации из файла манифеста по одному, тестируя приложение после каждого.

  5. Протестируйте как можно большее количество устройств.

  6. Не копируйте/вставляйте мой фрагмент выше в ваш файл манифеста. Обновления Android меняют список, поэтому используйте всплывающие подсказки Android Studio, чтобы убедиться, что вы их все получили.

Надеюсь, это сэкономит кому-то время.

Мой метод onConfigurationChanged только для информации ниже. onConfigurationChanged вызывается в жизненном цикле после того, как доступна новая ориентация, но до пользовательского интерфейса был воссоздан. Следовательно, мой первый if для проверки правильности ориентации работает, а затем второй вложенный if для проверки видимости моего пользовательского интерфейса ImageView также работает правильно.

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        // Checks the orientation of the screen
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        }
    }