EDIT:
From the discussion in the comments, I see that your major problem seems to be the handling of the orientation change.
As Emmanuel said, when a configuration change occurred (and you're
basically back to onCreate()
, you need to check for
getResources().getConfiguration().orientation
. According to that,
you have to check if you need to remove or add fragment/s. So e.g.
you have a smartphone in portrait, only one Fragment is present.
Then you change to landscape, you have to either
- add a Fragment into old layout or
- remove whole fragment stack and add new layout
There's no way out of dealing with layout param changes (like setting visibility from GONE to VISIBLE, etc.), if you want to use an old layout for your Fragment container. If you don't use your old layout and create a new one, you have to save the UI state, so that the user gets his selections, etc. back (you know this stuff probably - use Intents, etc.).
I prefer to create a new layout for a new configuration and recreate the state, so I do something like this in onCreate()
:
if (CheckApp.isScreenBig()) {
setContentView(R.layout.frag_multi);
} else {
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
// search and remove former fragments, if there were any
setContentView(R.layout.frag_multi);
} else {
if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) {
getSupportFragmentManager().beginTransaction().add(android.R.id.content, new FragSingle()).commit(); // single Fragment
}
}
}
Detect Multi-configuration for example like this Determine if the device is a smartphone or tablet?
In your Activity, start your configurations in onCreate
if (App.isScreenBig()) {
setContentView(R.layout.frag_multi);
} else {
if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) {
getSupportFragmentManager().beginTransaction().add(android.R.id.content, new FragMainPaging()).commit(); // single Fragment
}
}
Depending on your overall design, you don't need to do anything more. If you need to interact between your Fragments, you can propagate changes through your Parent Fragment's/Activity's ViewPager or a Controller or whatever you have in place.
I usually go with nested fragments, and use something like that to communicate changes
((FragManagedPaging) getParentFragment()).forwardChanges(NotifyState.NOTIFY_ALL, result);
NotifyState
is an enum indicating if the change is relevant for all Fragments or certain ones (I pass in the Class names if I want certain ones) or if I want to create a new Fragment for a certain event (NotifyState.ADD
), etc. The parent fragment hosts the other Fragments (also a ViewPager, if needed) and forwards changes, if there are other Fragments present. The other Fragments have a notify method, that indicates to do work.
void onChangeOccurred(Object... args) {
// look what changed, what work to do in args, etc.
But overall it's up to you to decide.
Example of multi pane 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" >
<fragment
android:id="@id/frag_travel_list"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="2"
class="de.einschnaehkeee.travel.check.frag.FragTravelBags" />
<fragment
android:id="@id/frag_travel_items"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="3"
class="de.einschnaehkeee.travel.check.frag.FragBag" />
<fragment
android:id="@id/frag_choose_items"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="3"
class="de.einschnaehkeee.travel.check.frag.ChooseItemsFragment" />
</LinearLayout>
For configurations with multi pane layouts, use appropriate layout directories, like layout-land/frag_multi.xml
, etc.