Fool-proof way to handle Fragment on orientation change
You are creating a new fragment every time you turn the screen in your activity onCreate();
But you are also maintaining the old ones with super.onCreate(savedInstanceState);
. So maybe set tag and find the fragment if it exists, or pass null bundle to super.
This took me a while to learn and it can really be a pain when you are working with stuff like viewpager.
I'd recommend you to read about fragments an extra time as this exact topic is covered.
Here is an example of how to handle fragments on a regular orientation change:
Activity:
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
TestFragment test = new TestFragment();
test.setArguments(getIntent().getExtras());
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, test, "your_fragment_tag").commit();
} else {
TestFragment test = (TestFragment) getSupportFragmentManager().findFragmentByTag("your_fragment_tag");
}
}
}
Fragment:
public class TestFragment extends Fragment {
public static final String KEY_ITEM = "unique_key";
public static final String KEY_INDEX = "index_key";
private String mTime;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_layout, container, false);
if (savedInstanceState != null) {
// Restore last state
mTime = savedInstanceState.getString("time_key");
} else {
mTime = "" + Calendar.getInstance().getTimeInMillis();
}
TextView title = (TextView) view.findViewById(R.id.fragment_test);
title.setText(mTime);
return view;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("time_key", mTime);
}
}
How can I handle Orientation change so Fragment doesn't load?
Do you use viewPager or just add fragment into your activity? One way is to save data that you want to maintain on rotation into onSaveInstanceState(Bundle outState)
bundle and then restore that data inside onCreate using
if(savedInstanceState != null) {
//get your data
}
or simply add your fragment only when the activity was loaded (not reloaded after device rotation)
if(savedInstanceState == null)
{
mFragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
YourFragment fragment = new YourFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
}
Anyways you should definitely check this and this questons, they might be helpful.
Put code in Activity or Fragment to handle orientation change?
You put the code where the views are... It's really that simple.
res/layout-land
should keep the exact same view IDs.
For example, MainActivity
would load both res/layout/activity_main.xml
and res/layout-land/activity_main.xml
automatically for you depending on orientation.
findViewById
will work appropriately if you don't change any ID values
There is a whole documentation page on this. Notice they use retained Fragments, but that is not necessary.
Also Android Studio: Creating landscape layouts
Android Fragment lifecycle over orientation changes
You're layering your Fragments one on top of the other.
When a config change occurs the old Fragment adds itself to the new Activity when it's recreated. This is a massive pain in the rear most of the time.
You can stop errors occurring by using the same Fragment rather than recreating a new one. Simply add this code:
if (savedInstanceState == null) {
// only create fragment if activity is started for the first time
mFragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
FragmentOne fragment = new FragmentOne();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
} else {
// do nothing - fragment is recreated automatically
}
Be warned though: problems will occur if you try and access Activity Views from inside the Fragment as the lifecycles will subtly change. (Getting Views from a parent Activity from a Fragment isn't easy).
How to handle orientation change in fragment in viewpager programmatically?
As always in such situations, it seems that the decision should be difficult to implement. In fact, it was three lines:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
ViewGroup viewGroup = (ViewGroup) getView();
viewGroup.removeAllViewsInLayout();
View view = onCreateView(getActivity().getLayoutInflater(), viewGroup, null); viewGroup.addView(view);
}
Here where I found it
Redrawing the fragment is not the best idea if it keeps some data (plays video, map, etc.) because I have no dynamically changing data there, and I had to show the same thing, only in a different orientation, I used this approach if you need to change the orientation and did not lose the data you must read this.
Related Topics
Call Method When Home Button Pressed
Android Parcelable -- Retailerorderactivity.Java Return Null
Difference Between Activity and Fragmentactivity
Change Toolbar Color in Appcompat 21
How to Enable Disable Gps Programmatically in Android
Animating Markers on Google Maps V2
Failed to Resolve: Com.Android.Support:Appcompat-V7:27.+ (Dependency Error)
Java.Util.Zip.Zipexception: Duplicate Entry
How to Scale a Website for Mobile Devices
Android Automatic Horizontally Scrolling Textview
Programmatically Change the Value of a Color Resource Obtained from API Response
How Do Android Screen Coordinates Work
Firebase (Fcm) How to Get Token
Emulator Error: This Avd's Configuration Is Missing a Kernel File
How to Get Recent Tasks on Android "L"