I have to implement "standart" fragments navigation in my app (please see link).
The issue is when device is in portrait mode, there should be shown only 1 fragment, and when it is rotated to landscape mode, 2 fragments should be shown.
I tried to do this 2 different ways:
1) I use only 1 activity with different portrait and landscape layouts.
Portrait layout 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>
And here`s landscape layout:
<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>
Activity`s onCreate method:
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();
}
}
And that`s the way I refresh 2nd fragment:
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();
}
Also I save and restore fragments` states, so my data does not disappear after rotations. Generally, this code works properly in my case.
2) I use 2 activities and the same layout for 1st Activity portrait and landscape modes.
xml layout is the same as in previous one for landscape:
<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 method (note, that fragments entities are not static, as it was in 1st case): private ItemsFragment mItemsFragment; private 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();
}
}
And now if the device is in portrait mode, I start new 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);
}
And, at last, 2nd Activity`s onCreate method:
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();
}
When device is rotated to landscape mode, 2nd activity finishes, and I see my 1st activity with 2 fragments (as expected).
Question:
In 1st case I save fragments as static variables, and because of this I don't care if I change 2nd fragment state in portrait or landscape modes (the same fragment is used). But I don't think it's a good idea to save it as static fields.
In 2nd case I don't know how to sync Activity A Fragment B (landscape) and Activity B Fragment B (portrait). If I change something in fragment (I mean, toggle button etc) and rotate device, changes should be applied in another fragment.
Generally, what case is better, and if 2nd, how can I resolve synchronization issue? Or maybe there is another easier way. Thanks for reading, I hope you can help me :)
Just follow this mate http://developer.android.com/guide/components/fragments.html. Dont make fragments static (thats just wierd)