How to handle orientation change using fragment? - android

I now have 2 fragment, one fragment handle portrait mode then another handle landscape mode. But the problem is that when rotate from portrait to landscape then back to portrait. It will not show the same thing that show on the first portrait mode. Is there any code that can solve this problem?
This code is inside the fragment holder:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.frag_holder);
FragmentManager fm = getSupportFragmentManager();
final Fragment fragment = Frag.newInstance(); //Portrait layout
final Fragment fragment2 = Frag2.newInstance(); //Landscape layout
int orientation = getResources().getConfiguration().orientation; //check whether is it portrait or landscape
if(orientation == Configuration.ORIENTATION_PORTRAIT){
Fragment fragTAG = fm.findFragmentByTag(TAG_P);
if(fragTAG == null){
Log.i("test","test");
fm.beginTransaction()
.replace(R.id.fragPlaceHolder, fragment, TAG_P)
.commit(); //Portrait
}
else{
fm.beginTransaction().replace(R.id.fragPlaceHolder,fragTAG).commit();
}
}
if(orientation == Configuration.ORIENTATION_LANDSCAPE){
Fragment fragTAG = fm.findFragmentByTag(TAG_L);
if(fragTAG == null){
fm.beginTransaction()
.replace(R.id.fragPlaceHolder, fragment2, TAG_L)
.commit(); //Landscape
}
else{
fm.beginTransaction().replace(R.id.fragPlaceHolder,fragTAG).commit();
}
}
}
}

Step 1:
Add Config changes in your activity
<activity android:name=".ui.createtasks.CreateTaskActivity"
android:configChanges="orientation|screenSize|keyboardHidden" > </activity>
Step 2:
Add your edit text values to onSaveInstanceState
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putCharSequence(KEY_TITLE, et_text.getText().toString());
}
Step 3:
Get your Saved edit text values through onViewStateRestored
#Override
public void onViewStateRestored(#Nullable Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
String savedTitle = null;
if (savedInstanceState != null) {
savedTitle = savedInstanceState.getString(KEY_TITLE);
et_text.setText(savedTitle);
}
}

You can either call setRetainInstance(True); in the onCreate() methods in both Fragments.
Or
to create a headless-Fragment(a Fragment with no UI) to cache data.
A third option will be to use onSaveInstanceState(Bundle outState) to cache data and re-display the data by using Bundle savedInstanceState in the onCreateView() method.

When there is activity rotation, the activity closed and reopen the onDestroy and onCreate are called.
if you want to save data and reload it in the other rotation you can do it with onSaveInstanceState method:
protected void onSaveInstanceState(Bundle outState)
for example:
#Override
public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putString("name", "David");
outState.putInt("age", 17);
}
and reload the data in the onCreate
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
…
if(savedInstanceState != null)
{
savedInstanceState.getString("name");
savedInstanceState.getInt("age");
}
}

Add code in manifest file
<activity
android:name=".file_name"//add your activity name
android:label="label" //add label
android:configChanges="orientation|screenSize|keyboardHidden"
android:theme="#style/AppTheme.NoActionBar" />

Related

No Activity Error on Fragment after FindFragementByTag

I have a Main Activity with multiple Fragments. And this is how how I switch the fragments
public void openFragment(final Fragment fragment, String title, String tag){
getSupportFragmentManager().popBackStack();
getSupportFragmentManager()
.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.add(R.id.container, fragment, tag)
.addToBackStack(null)
.commit();
getSupportActionBar().setTitle(title);
}
I have an INT variable in the Main Activity that I update from each of the Fragment to determine which Fragment was active before an orientation change
private int ACTIVE_FRAGMENT = 0;
During saved instance on the Activity, I save the INT like so
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(Constants.ACTIVE_EVENT_ID, ACTIVE_FRAGMENT);
super.onSaveInstanceState(outState);
}
And onRestoreInstanceState I go back to the Active Fragment like this
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState != null){
ACTIVE_FRAGMENT = savedInstanceState.getInt(Constants.ACTIVE_EVENT_ID);
if (ACTIVE_FRAGMENT > 0){
FragmentManager fm = getSupportFragmentManager();
switch (ACTIVE_FRAGMENT) {
case 1:
EventSetupFragmentOne fragmentOne = (EventSetupFragmentOne) fm.findFragmentByTag(Constants.SETUP_FRAGMENT_ONE_TAG);
if (fragmentOne != null) {
openFragment(fragmentOne, getString(R.string.event_setup_title_1), Constants.SETUP_FRAGMENT_ONE_TAG);
}
break;
}
}
}
}
This goes back to the Active Fragment but then throws a No Actitiy found exception
Caused by: java.lang.IllegalStateException: No activity
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1125)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1120)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1929)
What can I do differently to go back to an Active Fragment after a configuration change?
You don't have to call openFragment on configuration changes.
Fragments will be recreated by the framework.
That's why in onCreate method you don't (re)initialize your Fragments if savedInstanceState == null.

Saving and Restoring Fragment state in Android

how to Saving and Restoring Fragment state in Android ?
my code for save and restore state :
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("CurrentState",CurrentState);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
if (savedInstanceState != null) {
// Restore last state for checked position.
CurrentState = savedInstanceState.getInt("CurrentState", 0);
}
.
.
.
switch (CurrentState){
case 1 :button_DisplayMemoris.performClick();break;
case 2 :
linearLayout_AddMemoris.setVisibility(View.VISIBLE);
linearLayout_Memoris.setVisibility(View.GONE);
linearLayout_DisplayMemoris.setVisibility(View.GONE);
break;
default:break;
}
return inflate;
}
when CurrentState=2 , linearLayout_AddMemoris Not displayed
How do I fix it?
update :
this is my activity :
public class ToolsActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tools);
displayView();
}
public void displayView() {
// update the main content by replacing fragments
Fragment fragment = = new MemoirsFragment();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.frame_container, fragment);
ft.commit();
}
}
Is there a way to solve the problem?
I have no idea
Add in onCreate method null checking, now you are replace restored fragment by new fragment
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tools);
if (savedInstanceState == null)
displayView();
}

Android rotation: Why fragment not restored by TAG?

I have an activity called MainActivity with a fragment inside called 'HomeFragment'. I want to restore fragment after screen rotation, however something seems missing.
I followed below process:
save fragment by using getSupportFragmentManager().putFragment(...) during onSaveInstanceState
try to restore fragment by fragmentManager.findFragmentByTag during onCreate (after checking that bundle is not null)
However findFragmentByTag returns null.
Here is code snippets inside MainActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set up the action bar to show a dropdown list.
final ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
setupNavigationSpinner(actionBar);
FragmentManager fragmentManager = getSupportFragmentManager();
if (savedInstanceState != null) {
if (fragmentManager.findFragmentByTag("frag") != null) {
// findFragmentByTag always return null
homeFragment = (HomeFragment) fragmentManager
.findFragmentByTag(HomeFragment.ARG_ITEM_ID);
contentFragment = homeFragment;
}else{
homeFragment = new HomeFragment();
switchContent(homeFragment, HomeFragment.ARG_ITEM_ID);
}
} else {
homeFragment = new HomeFragment();
switchContent(homeFragment, HomeFragment.ARG_ITEM_ID);
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
getSupportFragmentManager().putFragment(outState, "frag",homeFragment );
}
public void switchContent(Fragment fragment, String tag) {
FragmentManager fragmentManager = getSupportFragmentManager();
while (fragmentManager.popBackStackImmediate())
;
if (fragment != null) {
FragmentTransaction transaction = fragmentManager
.beginTransaction();
transaction.replace(R.id.content_frame, fragment, tag);
// Only ArticlDetailFragment is added to the back stack.
if (!(fragment instanceof Fragment)) {
transaction.addToBackStack(tag);
}
transaction.commit();
contentFragment = fragment;
}
}
There is no reason to call
getSupportFragmentManager().putFragment(outState, "frag",homeFragment );
A Fragment state will automatically be restored. The problem is that you're not calling the super of your onSaveInstanceState. It should simply look like this:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
Also, you're setting the tag as HomeFragment.ARG_ITEM_ID then looking for "frag". Does HomeFragment.ARG_ITEM_ID == "frag"?

Can't keep fragments live through changing orientation or Saving fragment UI

I have an app that uses SherlockActionBar and switches between dynamic fragments through ActionItems in the Action Bar.
The problem is that i can't save the fragment states and their UI data.
This is the FragmentActivity:
public class MainActivity extends SherlockFragmentActivity {
private LocationFragment locationFragement;
private HomeFragment homeFragment;
private SettingsFragment settingsFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayShowTitleEnabled(false);
locationFragement = new LocationFragment();
homeFragment = new HomeFragment();
settingsFragment = new SettingsFragment();
}
#Override
public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
getSupportMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
FragmentManager fragManager = getSupportFragmentManager();
FragmentTransaction fragTransaction = fragManager.beginTransaction();
switch (item.getItemId()){
case R.id.home:
fragTransaction.replace(android.R.id.content, homeFragment);
break;
case R.id.location:
fragTransaction.replace(android.R.id.content, locationFragement);
break;
case R.id.settings:
fragTransaction.replace(android.R.id.content, settingsFragment);
break;
}
fragTransaction.commit();
return true;
}
Firstly, I tried to call to a single instance of the fragments, only to encounter NullPointerExceptions every time i did in the onOptionsItemSelected switch block
fragTransaction.replace(android.R.id.content, myFragmentClassName);
while the fragment instantiation was under
if(savedInstanceState == null){
locationFragement = new LocationFragment();
homeFragment = new HomeFragment();
settingsFragment = new SettingsFragment();
}
The fragments would not have created under orientation change obviously, and i couldn't figure anyway i could keep them instantiated. So i decided to create them anew every onCreate (which is bad but i wanted something to work) and save the UI data just to pass it back to the fragment.
This is one of the fragments, the other 2 are the same:
public class LocationFragment extends SherlockFragment {
private View myView;
private CheckBox myCheckBok;
#Override
public void onCreate(Bundle savedInstanceState) {
setRetainInstance(true);
Log.d("LocationFragment", "onCreate running");
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("LocationFragment", "onCreateView running");
myView = inflater.inflate(R.layout.map_fragment, container, false);
myCheckBok = (CheckBox) myView.findViewById(R.id.mapFragmentCheckBox);
if(savedInstanceState != null){
myCheckBok.setChecked(savedInstanceState.getBoolean("isChecked"));
}
return myView;
}
#Override
public void onResume()
{
Log.d("LocationFragment", "onResume running");
super.onResume();
}
#Override
public void onPause() {
Log.d("LocationFragment", "onPause running");
super.onPause();
}
#Override
public void onSaveInstanceState(Bundle outState) {
boolean isChecked = myCheckBok.isChecked();
outState.putBoolean("isChecked", isChecked);
Log.d("LocationFragment", "onSaved Instant running");
super.onSaveInstanceState(outState);
}
I'm saving the checkbox's state, when i pass through the icons the checkbox state is saved and also through orientation change. BUT, when i change orientation, press another icon (or press the same one) and return to my fragment, the state isn't saved. I realized this is caused due to onSavedInstanceState not running when i change to another fragment (thus not saving or passing the checkBox data).
I haven't found answers anywhere on how to save correctly UI data from fragments (just through savedInstanceState doesn't cut it for my purposes) or how to manage several fragment instantiations while changing them. I know that each time i change a fragment, all it's data
is saved automatically by the system, but can't seem to get it to work.
Please help.
It's not part of the problem but you should be aware that the use of onSaveInstanceState is not needed for saving a View state. Android does that for you already as long as there's an ID to the View.
Seems like the problem you are facing is that you are not restoring the fragments from their FragmentManager. The fragments are there, but you simply didn't go to the FragmentManager and brought them once the onCreate has happened again.
This code should go in the onCreate:
// Try and fetch the fragments from the manager
locationFragement = fragmentManager.findFragmentByTag(LOCATION_FRAGMENT_TAG);
homeFragment = fragmentManager.findFragmentByTag(HOME_FRAGMENT_TAG);
settingsFragment = fragmentManager.findFragmentByTag(SETTINGS_FRAGMENT_TAG);
// If the fragment weren't found - meaning it's the first time the activity was
// started, create them
if (locationFragement == null) locationFragement = new LocationFragment();
if (homeFragment == null) homeFragment = new HomeFragment();
if (settingsFragment == null) settingsFragment = new SettingsFragment();
And, whenever you are adding/removing/replacing a fragment, make sure to add him with the TAG, i.e.
// EXAMPLE HOW TO USE A REPLACE WITH A TAG
getSupportFragmentManager().beginTransaction().replace(android.R.id.content,
locationFragement, LOCATION_FRAGMENT_TAG);
Does that work?

android : save fields value of tab while changing tabs

I have an Activity A with 2 tabs and each tab have its own Activity (B and C) . Activity B and Activity C each have 2 text fields . I want to save value of these text field in SharedPreferences when user changes tabs.
How can I do this?
What you probably want is save your activity state in onSaveInstanceState instead, like this:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(MY_KEY, myStringValue);
// ...
}
And then in onCreate:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// other stuff...
if(savedInstanceState != null) {
myStringValue = savedInstanceState.getString(MY_KEY);
}
}

Categories

Resources