Включить изменение ориентации экрана, когда видны определенные фрагменты, и отключить, когда другие

Я использую фрагменты в своем приложении. Большинство фрагментов должны иметь только одну ориентацию - портретную. Поэтому я заставил активность держателя всегда находиться в портретном режиме.

Но один из моих фрагментов должен иметь и портретный, и ландшафтный режимы. Как включить изменение ориентации только для одного фрагмента? Или мне нужно сделать это отдельным действием для обработки ориентации, не зависящим от других фрагментов?


person TpoM6oH    schedule 25.02.2013    source источник


Ответы (5)


Вам придется сделать это вручную.

1) добавьте эту строку в свой тег активности android:configChanges="orientation|screenSize"

2) Переопределить обратный вызов изменения конфигурации в вашем фрагменте или действии.

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

   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();
    }

//Your fragment animation layout changing code

}
person Artem Zelinskiy    schedule 25.02.2013
comment
а как отключить смену ориентации во всех фрагментах кроме одного? - person TpoM6oH; 26.02.2013
comment
после добавления строк в манифест воссоздание фрагмента не будет запущено. В фрагменте, который вы хотите создать новый вид, вы должны вручную удалить текущий вид и создать новый - person Artem Zelinskiy; 26.02.2013

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

Примечание. Этот ответ был отредактирован днем ​​позже, когда я опубликовал его, так как обнаружил проблему с API ниже 26. После тщательного тестирования мой окончательный ответ приведен ниже. Это решение работает (проверено) в API 21 и выше.

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

  1. Одно действие с несколькими фрагментами.
  2. Только один фрагмент должен быть в книжной и альбомной ориентации, так как он имеет соответствующие разные версии макета. Остальные должны оставаться в портретной ориентации, а также экран не должен вращаться, пока приложение находится на переднем плане.
  3. Я использовал Котлин. Для Java должно быть почти то же самое.

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

В моем случае я хотел, чтобы отображался только один фрагмент в книжной и альбомной ориентации, поэтому я установил requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED (это значение по умолчанию, если оно не установлено), но поскольку мы изменим requestedOrientation в остальных фрагментах мы тоже должны установить здесь:

    override fun onResume() {

    super.onResume()

    activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED

    //The rest of your code (if you have something else here).

    }

В остальных фрагментах я хотел принудительно установить книжную ориентацию, поэтому использовал следующее:

    override fun onResume() {

    super.onResume()

    activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT

    //The rest of your code (if you have something else here).

    }

Это все, что вам нужно, чтобы заставить его работать! Следующее является необязательным, но может быть полезным, как это было для меня.

Необязательно 1:

Если у вас много фрагментов и вы не хотите изменять/добавлять onResume() в каждый из них, вы можете создать подкласс (например, PortraitFragment) Fragment(), где вы просто переопределяете onResume(). Затем вы можете получить от него все фрагменты, в которых вы хотите иметь эту функциональность.

open class PortraitFragment : Fragment() {

    override fun onResume() {
        super.onResume()

        activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
    }

}

Вариант 2:

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

В манифесте добавить android:resizeableActivity="false":

    <activity android:name=".MainActivity"
    android:launchMode="singleTask"
    android:windowSoftInputMode="stateHidden|adjustPan"
    android:resizeableActivity="false">
person MatJB    schedule 17.03.2021

Используйте метод активности setRequestedOrientation при выборе фрагмент для показа.

public class MyActivity extends Activity {
  // ...

  public void chooseFragment(int x) {
    Fragment newFragment;
    if (x == 1) {
      // FragmentOne can be any orientation
      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
      newFragment = new FragmentOne();
    }
    else {
      // FragmentTwo can be only portrait orientation
      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
      newFragment = new FragmentTwo();
    }
    getSupportFragmentManager().beginTransaction()
      .replace(R.id.fragment_container, newFragment)
      .commit();
  }

  // ...
}
person William    schedule 05.02.2015

В вашем AndroidManifest.xml добавьте android:screenOrientation="portrait" во фрагмент, который вы хотите исправить как Portrait, и не добавляйте этот оператор во фрагменте вы не хотите исправлять ориентацию. Пример:

<activity
android:name="com.example.myapp.MainActivity"
android:screenOrientation="portrait"/>
person Ankur Sharma    schedule 25.02.2013
comment
Я думаю, вы путаете действия и фрагменты. - person Karl; 06.01.2014

person    schedule
comment
Если это сработало, то больше не работает, более того setUserVisibleHint устарело - person Mathieu de Brito; 11.06.2020