I know this question has been asked before but none of the answers given so far is of any help to me.
I have a viewpager which is populated with fragments (android.support.v4.app.Fragment) from a FragmentStatePagerAdapter . Some of these fragments contain logic that needs to be retained when the orientation changes, such as keeping track of which view is currently selected.
However, although I save the data in question in onSaveInstanceState the savedInstanceState is always null. I can solve this by storing the data in a static variable (which since I only have one instance of each fragment would work for me) but i found this to be a quite ugly solution and there has to be a proper way of doing this.
This is one of the fragments that doesn't retain it's state on rotation:
public class PriceSelectFragment extends Fragment {
private TableRow mSelected;
private int mSelectedPos = 0;
// newInstance constructor for creating fragment with arguments
public static PriceSelectFragment newInstance() {
PriceSelectFragment fragmentFirst = new PriceSelectFragment();
return fragmentFirst;
}
public PriceSelectFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_price_select, container, false);
TableLayout mTable = (TableLayout)view.findViewById(R.id.price_table);
List<PriceGroup> mPriceGroups = ((MainActivity) getActivity()).getPriceGroups();
int i = 0;
for (final PriceGroup group : mPriceGroups) {
//Create row from layout and access child TextViews
TableRow r = (TableRow)inflater.inflate( R.layout.price_group, mTable, false);
TextView size = (TextView)r.getChildAt(0);
TextView dimension = (TextView)r.getChildAt(1);
TextView weight = (TextView)r.getChildAt(2);
TextView price = (TextView)r.getChildAt(3);
//Populate row with PriceGroup Data
size.setText(group.sizeIndicator);
dimension.setText(String.format("%2.0fx%2.0fx%2.0f", group.length, group.width, group.height));
weight.setText(Float.toString(group.weight));
price.setText(Integer.toString(group.price));
//Alternate background color every other row
if (i % 2 == 0) {
r.setBackgroundDrawable(getResources().getDrawable(R.drawable.price_selector_1));
}
else {
r.setBackgroundDrawable(getResources().getDrawable(R.drawable.price_selector_2));
}
mTable.addView(r); // Add to table
r.setTag(i);
r.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
selectRow((TableRow) v);
}
});
i++;
}
mSelected = (TableRow)view.findViewWithTag(mSelectedPos);
selectRow(mSelected);
return view;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("selected", mSelectedPos);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
mSelectedPos = savedInstanceState.getInt("selected");
}
}
private void selectRow(TableRow row) {
if ((int) mSelected.getTag() % 2 == 0) {
mSelected.setBackgroundDrawable(getResources().getDrawable(R.drawable.price_selector_1));
}
else {
mSelected.setBackgroundDrawable(getResources().getDrawable(R.drawable.price_selector_2));
}
mSelected = row;
mSelectedPos = (int) mSelected.getTag();
mSelected.setBackgroundColor(getResources().getColor(R.color.light_blue));
}
}
How do I solve this without having to save my states in static variables?
I should point out that all of the fragments are programatically created and as such they do not have an id and I read that that might be the problem but I don't know how to solve that either.
Also my application is structured like this:
The fragments whose states I'm having trouble with are the subfragments.
If there is no available instance data, the savedInstanceState will be null.
This method may be called by the ViewPager to obtain a title string to describe the specified page. This method is deprecated. This method should be called by the application if the data backing this adapter has changed and associated views should update.
ViewPager in Android allows the user to flip left and right through pages of data. In our android ViewPager application we'll implement a ViewPager that swipes through three views with different images and texts.
You can't use ViewPager to swipe between Activities . You need to convert each of you five Activities into Fragments , then combine everything in one FragmentActivity with the Adapter you use with ViewPager .
In your Activity
which is hosting your Fragment
you need to store a refernce to the fragment in the Bundle
.
Something like this should work for you
public void onCreate(Bundle savedInstanceState) {
if (savedInstanceState != null) {
//Restore your fragment instance
fragment1 = getSupportFragmentManager().getFragment(
savedInstanceState, "fragment");
}
}
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getSupportFragmentManager().putFragment(outState, "fragment", fragment1);
}
fragment1
is the instance of the Fragment1 that you mentioned in your question that needs to get recreated.
I haven't done this with a structure like yours before but this is how I would start:
In the onSaveInstanceState
in your Fragment1
I believe you would need to do the same with each of the fragments in your ViewPager
. Then in the onCreateView
on your Fragment1
get the fragments from the fragment manager and recreate your ViewPager
.
I have found this answer here which is pretty much the same but has a little more detail: https://stackoverflow.com/a/17135346/1417483
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