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 :)
If you want the activity to not restart during screen orientation change, you can use the below AndroidManifest. xml. Please note the activity android:configChanges=”orientation|screenSize” attribute. This attribute makes the activity not restart when change screen orientation.
When you rotate your device and the screen changes orientation, Android usually destroys your application's existing Activities and Fragments and recreates them. Android does this so that your application can reload resources based on the new configuration.
The first key is that we can save our Fragments' state ourselves using FragmentManager. saveInstanceState(Fragment) . Before removing the Fragment, call this method to get a Bundle containing your Fragment's saved state! The second key is restoring state.
Just follow this mate http://developer.android.com/guide/components/fragments.html. Dont make fragments static (thats just wierd)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With