Мне нужно реализовать в своем приложении "стандартную" навигацию по фрагментам (см. ссылку ).
Проблема в том, что когда устройство находится в портретном режиме, должен отображаться только 1 фрагмент, а при повороте в альбомный режим должны отображаться 2 фрагмента.
Я пытался сделать это двумя разными способами:
1) Я использую только одно занятие с разным макетом книжной и альбомной ориентации.
Вертикальный макет xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="@+id/main_frame_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
А вот ландшафтный макет:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="horizontal" >
<FrameLayout
android:id="@+id/main_frame_fragment_container_left"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<FrameLayout
android:id="@+id/main_frame_fragment_container_right"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
Метод действия onCreate:
private static ItemsFragment mItemsFragment;
private static ItemDetailsFragment mItemDetailsFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (mItemsFragment == null) {
mItemsFragment = ItemsFragment.newInstance();
}
if (mItemDetailsFragment == null) {
mItemDetailsFragment = ItemDetailsFragment.newInstance();
}
if (isLandscape()) {
getSupportFragmentManager().beginTransaction().replace(R.id.main_frame_fragment_container_left, mItemsFragment)
.commit();
getSupportFragmentManager().beginTransaction()
.replace(R.id.main_frame_fragment_container_right, mItemDetailsFragment).commit();
} else {
getSupportFragmentManager().beginTransaction().replace(R.id.main_frame_fragment_container, mItemsFragment)
.commit();
}
}
И вот так я обновляю 2-й фрагмент:
Bundle bundle = new Bundle();
bundle.putSerializable(BaseFragment.KEY_BUNDLE_ITEM, response.getItem());
mItemDetailsFragment = ItemDetailsFragment.newInstance(bundle);
if (isLandscape()) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.main_frame_fragment_container_right, mItemDetailsFragment).commit();
} else {
getSupportFragmentManager().beginTransaction()
.replace(R.id.main_frame_fragment_container, mItemDetailsFragment).addToBackStack(null).commit();
}
Также я сохраняю и восстанавливаю состояния фрагментов, поэтому мои данные не пропадают после поворотов. В общем, в моем случае этот код работает правильно.
2) Я использую два занятия и один и тот же макет для первого занятия в портретном и ландшафтном режимах.
xml макет такой же, как и в предыдущем для альбомной ориентации:
<FrameLayout
android:id="@+id/main_frame_fragment_container_left"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<FrameLayout
android:id="@+id/main_frame_fragment_container_right"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
onCreate (обратите внимание, что сущности фрагментов не статичны, как в первом случае): private ItemsFragment mItemsFragment; частный ItemDetailsFragment mItemDetailsFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
mItemsFragment = ItemsFragment.newInstance();
mItemDetailsFragment = ItemDetailsFragment.newInstance();
getSupportFragmentManager().beginTransaction().replace(R.id.main_frame_fragment_container_left, mItemsFragment)
.commit();
getSupportFragmentManager().beginTransaction()
.replace(R.id.main_frame_fragment_container_right, mItemDetailsFragment).commit();
}
}
И теперь, если устройство находится в портретном режиме, я запускаю новое Activity:
if (isLandscape()) {
Bundle bundle = new Bundle();
bundle.putSerializable(BaseFragment.KEY_BUNDLE_ITEM, response.getItem());
mItemDetailsFragment = ItemDetailsFragment.newInstance(bundle);
getSupportFragmentManager().beginTransaction()
.replace(R.id.main_frame_fragment_container_right, mItemDetailsFragment).commit();
} else {
Intent intent = new Intent(getApplicationContext(), DetailsActivity.class);
intent.putExtra(KEY_ITEM, response.getItem());
startActivity(intent);
}
И, наконец, метод onCreate 2-го Activity:
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
setContentView(R.layout.activity_details);
if (isLandscape()) {
finish();
}
Item item = (Item) getIntent().getExtras().getSerializable(KEY_ITEM);
Bundle bundle = new Bundle();
bundle.putSerializable(BaseFragment.KEY_BUNDLE_ITEM, item);
ItemDetailsFragment mItemDetailsFragment = ItemDetailsFragment.newInstance(bundle);
getSupportFragmentManager().beginTransaction()
.replace(R.id.main_frame_fragment_container, mItemDetailsFragment).commit();
}
Когда устройство переведено в альбомный режим, второе действие завершается, и я вижу свое первое действие с двумя фрагментами (как и ожидалось).
Вопрос:
В 1-м случае я сохраняю фрагменты как статические переменные, и из-за этого меня не волнует, изменю ли я состояние 2-го фрагмента в портретном или ландшафтном режимах (используется тот же фрагмент). Но я не думаю, что стоит сохранять его как статические поля.
Во втором случае я не знаю, как синхронизировать Activity A Fragment B (пейзаж) и Activity B Fragment B (портрет). Если я что-то изменил во фрагменте (я имею в виду кнопку переключения и т. Д.) И повернул устройство, изменения должны быть применены в другом фрагменте.
Как правило, какой вариант лучше, а второй - как решить проблему с синхронизацией? Или, может быть, есть другой способ попроще. Спасибо за чтение, надеюсь, вы мне поможете :)