Fragments keep duplicating - android

Hee Guys,
I'm currently working with fragments and I'm trying to manage it so that when you click twice on the same menu item it won't put 2 of the same fragments on top of eachother. However it still does. Could anyone tell me what I'm doing wrong?
/*
* Method to check which action is behind the selected Menu item. Then call ShowFragment()
* With the correct fragment parameter used with this Menu action value.
*/
public void getAction(int position, Cursor cursor) {
// TODO Auto-generated method stub
mCursor = cursor;
cursor.moveToPosition(position);
String action = cursor.getString(cursor.getColumnIndex(AppMenu.ACTION));
if (action != null) {
if (action.equalsIgnoreCase("home")) {
trans = manager.beginTransaction();
BaseFragment newFragment = new HomeFragment();
if (manager.findFragmentByTag(newFragment.getTag()) != null) {
mCursor.moveToPosition(position);
// Set the current fragment
mCurrentFragment = newFragment;
Bundle bundle = new Bundle();
int fragId = mCursor.getInt(mCursor.getColumnIndex(AppMenu._ID));
Log.i(TAG, fragId + " ");
bundle.putInt("fragmentID", fragId);
newFragment.setArguments(bundle);
trans.replace(R.id.fragmentContainer, newFragment).addToBackStack(
newFragment.tag());
trans.commit();
} else {
trans.show(newFragment);
}
} else if (action.equalsIgnoreCase("event")) {
showFragment(new EventsFragment(), position);
} else if (action.equalsIgnoreCase("location")) {
showFragment(new LocationsFragment(), position);
} else if (action.equalsIgnoreCase("news")) {
showFragment(new NewsFragment(), position);
} else if (action.equalsIgnoreCase("bars")) {
showFragment(new BarsFragment(), position);
} else if (action.equalsIgnoreCase("currency")) {
showFragment(new CurrencyFragment(), position);
} else if (action.equalsIgnoreCase("map")) {
showFragment(new MapFragment(), position);
}
} else {
Log.i(TAG, "You've got a nullpointerexception on getAction().");
}
}
/*
* Method that's called when changing from fragment through Menu or HomeMenu.
*/
public void showFragment(BaseFragment newFragment, int position) {
trans = manager.beginTransaction();
if (manager.findFragmentByTag(newFragment.tag()) == null) {
mCursor.moveToPosition(position);
// Set the current fragment
mCurrentFragment = newFragment;
// Go on and set the bundle values and pass it on the fragment.
Bundle bundle = new Bundle();
int fragId = mCursor.getInt(mCursor.getColumnIndex(AppMenu._ID));
Log.i(TAG, fragId + " ");
bundle.putInt("fragmentID", fragId);
newFragment.setArguments(bundle);
trans.replace(R.id.fragmentContainer, newFragment).addToBackStack(
newFragment.tag());
trans.commit();
} else {
trans.show(newFragment);
}
}
And here are 2 callbacks for when something changes or when back pressed.
/*
* Interface method called whenever a new fragment is created.
*/
#Override
public void onNewFragment(BaseFragment newFragment) {
// TODO Auto-generated method stub
FragmentManager fm = getSupportFragmentManager();
Class<? extends Fragment> newFragmentClass = newFragment.getClass();
if (newFragmentClass == EventsFragment.class
|| newFragmentClass == LocationsFragment.class
|| newFragmentClass == MapFragment.class
|| newFragmentClass == NewsFragment.class
|| newFragmentClass == CurrencyFragment.class
|| newFragmentClass == BarsFragment.class) {
for (Fragment fragment : fm.getFragments()) {
if (fragment != null && ((Object) fragment).getClass() == newFragmentClass) {
while (((Object) mCurrentFragment).getClass() != newFragmentClass) {
popFragment();
}
popFragment();
break;
}
}
}
}
/*
* Interface method called when you navigate back from a fragment.
* Checks which fragment is active, calls upon this fragments back function to clear any data,
* then pops the first fragment on the backstack.
*/
#Override
public void onBackNavigated() {
// TODO Auto-generated method stub
if ((mCurrentFragment instanceof HomeFragment)
&& !((HomeFragment) mCurrentFragment)
.isStackEmpty()) {
System.exit(0);
// break;
}
if ((mCurrentFragment instanceof LocationsFragment)
&& !((LocationsFragment) mCurrentFragment)
.isStackEmpty()) {
((LocationsFragment) mCurrentFragment).goBack();
// return;
}
if ((mCurrentFragment instanceof EventsFragment)
&& !((EventsFragment) mCurrentFragment)
.isStackEmpty()) {
((EventsFragment) mCurrentFragment).goBack();
// return;
}
if ((mCurrentFragment instanceof MapFragment)
&& !((MapFragment) mCurrentFragment).isStackEmpty()) {
((MapFragment) mCurrentFragment).goBack();
// break;
}
if ((mCurrentFragment instanceof BarsFragment)
&& !((BarsFragment) mCurrentFragment).isStackEmpty()) {
((BarsFragment) mCurrentFragment).goBack();
// break;
}
if ((mCurrentFragment instanceof CurrencyFragment)
&& !((CurrencyFragment) mCurrentFragment).isStackEmpty()) {
((CurrencyFragment) mCurrentFragment).goBack();
// break;
}
popFragment();
}
/*
* Pops the first fragment in the backstack. Then sets this as the new current fragment.
* If no fragment is in the backstack then finish() is called. Which will destroy the only fragment.
* Which in this case exits the application.
*/
public void popFragment() {
if (manager.getBackStackEntryCount() > 1) {
manager.popBackStack();
manager.executePendingTransactions();
ArrayList<Fragment> reversedFragments = new ArrayList<Fragment>(
manager.getFragments());
Collections.reverse(reversedFragments);
for (Fragment fragment : reversedFragments)
if (fragment != null) {
mCurrentFragment = (BaseFragment) fragment;
break;
}
} else {
finish();
}
}
**NOTE : ** The tag() functions calls a final String from the fragment itself with the same hardcoded tag everytime. So every fragment of the same class has the same tag. (Which should prevent double fragments, but it still doesn't)
Solution:
The tag() was returning null al the time. (Don't know why) So I changed the showFragment(fragment, tag, position) and hardcoded the tag in the mainactivity. Then used :
trans.replace(R.id.fragmentContainer, newFragment, tag);
//instead of
trans.replace(R.id.fragmentContainer, newFragment).addToStackBack(tag);
Don't forget to still add it to the backstack! Or else your back navigation won't work.
Just add an extra line: trans.addToBackStack(tag);

You can set the tag while adding/replacing the Fragment,
So you need to mention it as :
trans.replace(R.id.fragmentContainer, newFragment,tag);
Pass the tag value to the method according to the Fragment
showFragment(new EventsFragment(),tag, position);
Hope it will help you ツ

Related

How to detect what Fragment is currently in use

I have an app project where there is 10 Fragments. When user open a Fragment I want to in code know this and save the Fragment as the last Fragment user has visited.
If user close app and open it again this last visited Fragment will be showed to user.
I read many answers about this and there does not seam to be a consensus on a solution to know what Fragment is currently visible for User.
I was thinking to subclass FragmentManager maybe to detect popping and monitor queue state.
Or maybe put some GestureDetector.OnGestureListener in the Fragment and when that fires I can save the last Fragment user has visited.
Any help on this would be grate
This is what happen when user in the Fragment press back press button
/**
* user press back button
*/
#Override
public void onBackPressed() {
//Fragment fragment = getVisibleFragment();
//get the name from the topmost BackStackEntry which is also the fragment tag.
String fragmentTag = mFragManager.getBackStackEntryAt(mFragManager.getBackStackEntryCount()-1).getName();
Fragment currentFrag = mFragManager.findFragmentByTag(fragmentTag);
if (currentFrag == null ) {
super.onBackPressed();
}
if (currentFrag != null) {
if (currentFrag.getTag().equals(SettingsManager.FragmentsModel.CHAT_FRAGMENT.toString())) {
if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
openDrawer(false);
} else
requestBeginTransaction(SettingsManager.FragmentsModel.LAUNCHER_FRAGMENT.toString(), true, false);
} else if (currentFrag.getTag().equals(SettingsManager.FragmentsModel.BILLBOARD_FRAGMENT.toString())) {
} else if (currentFrag.getTag().equals(SettingsManager.FragmentsModel.NEWS_FRAGMENT.toString())) {
} else if (currentFrag.getTag().equals(SettingsManager.FragmentsModel.INFO_FRAGMENT.toString())) {
super.onBackPressed();
} else if (currentFrag.getTag().equals(SettingsManager.FragmentsModel.SEARCH_FRAGMENT.toString())) {
// exit app if the search address view is visible
if (currentFrag.getView().findViewById(R.id.search_address_layout).getVisibility() == View.VISIBLE) {
exitApp();
} else if (currentFrag.getView().findViewById(R.id.show_search_result_layout).getVisibility() == View.VISIBLE) {
// show search address view if Address already exist view is visible
currentFrag.getView().findViewById(R.id.search_address_layout).setVisibility(View.VISIBLE);
currentFrag.getView().findViewById(R.id.history).setVisibility(View.VISIBLE);
currentFrag.getView().findViewById(R.id.show_search_result_layout).setVisibility(View.INVISIBLE);
((SearchFragment)currentFrag).onSearchLayoutVisible();
}
} else if (currentFrag.getTag().equals(SettingsManager.FragmentsModel.PREFERENCE_FRAGMENT.toString())) {
super.onBackPressed();
//requestBeginTransaction(SettingsManager.FragmentsModel.LAUNCHER_FRAGMENT.toString(), true, false);
} else if (currentFrag.getTag().equals(SettingsManager.FragmentsModel.PREFERENCE_FRAGMENT_CHAT_SETTINGS.toString())) {
super.onBackPressed();
//requestBeginTransaction(SettingsManager.FragmentsModel.LAUNCHER_FRAGMENT.toString(), true, false);
} else if (currentFrag.getTag().equals(SettingsManager.FragmentsModel.PREFERENCE_FRAGMENT_THEME_SETTINGS.toString())) {
super.onBackPressed();
//requestBeginTransaction(SettingsManager.FragmentsModel.LAUNCHER_FRAGMENT.toString(), true, false);
} else if (currentFrag.getTag().equals(SettingsManager.FragmentsModel.LAUNCHER_FRAGMENT.toString())) {
super.onBackPressed();
//requestBeginTransaction(SettingsManager.FragmentsModel.LAUNCHER_FRAGMENT.toString(), true, false);
}
} else
exitApp();
}
In the code above i pop Fragment and dont know what Fragment is under the popt Fragment.
Here is when I add or show Fragment
/**
* Change the current displayed fragment by a new one.
* - if the fragment is in backstack, it will pop it
* - if the fragment is already displayed (trying to change the fragment with the same), it will not do anything
*
* #param backStateName the new fragment to display
* #param saveInBackstack if we want the fragment to be in backstack
* #param animate if we want a nice animation or not
*/
public void requestBeginTransaction(String backStateName, boolean saveInBackstack, boolean animate) {
Fragment frag = null;
if (mFragManager.findFragmentByTag(backStateName) != null) {
frag = mFragManager.findFragmentByTag(backStateName);
} else
try {
frag = (Fragment) Class.forName(backStateName).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate(backStateName, 0);
if (!fragmentPopped && manager.findFragmentByTag(backStateName) == null) {
//fragment not in back stack, create it.
FragmentTransaction transaction = manager.beginTransaction();
if (animate) {
LogManager.d(this, "Change Fragment: animate");
// transaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right);
}
transaction.add(R.id.frame, frag, backStateName);
if (saveInBackstack) {
LogManager.d(this, "Change Fragment: addToBackTack " + backStateName);
transaction.addToBackStack(backStateName);
LogManager.d(this, "Change Fragment: NO addToBackTack");
}
transaction.commit();
} else {
mFragManager.beginTransaction().show(mFragManager.findFragmentByTag(backStateName)).commit();
// custom effect if fragment is already instanciated
}
} catch (IllegalStateException exception) {
LogManager.w(this, "Unable to commit fragment, could be activity as been killed in background. " + exception.toString());
}
}
You can test it by looking at its instance.
Fragment fragment = getFragmentManager().findFragmentById(R.id.fragment_container);
if (fragment instanceOf Fragment1) {
// It is fragment of class Fragment1
} else if (fragment instanceOf Fragment2) {
// It is fragment of class Fragment2
}
When the user presses back button, have this in your activity (not fragment):
#Override
public void onBackPressed() {
super.onBackPressed();
Fragment fragment = getFragmentManager().findFragmentById(R.id.fragment_container);
if (fragment instanceOf Fragment1) {
// It is fragment of class Fragment1
} else if (fragment instanceOf Fragment2) {
// It is fragment of class Fragment2
}
// Save to prefs which fragment tag it is
}
If you only need to know the last visible fragment to restore it if the user closes the app, I would suggest to simply store the fragment's tag (or some identifier) in the SharedPreferences when it's started. Then, you can use that preference value later to set the correct fragment when the application starts.
You can do that by overriding the onStart() fragment method.

How to go to an activity's fragment from an another activity?

I have a DrawerMenuActivity suppose "AA" and it has 3 fragments "A", "B" and "C" as it's menu. Fragment "A" is my default screen. Now i have navigated to the fragment "B" which has listview items and each item click will open another new activity "AB". In AB there will be a button and that button click will open another activity "AC". so Basically the flow is as follows,
From AA(DrawerMenuActivity) -> "A" fragemnt -> "B" or "C" fragments -> AB(Activity) -> AC(Activity)
Now what i want to do is to return to fragment "B" from the Activity "AC".
I have replaced the fragments of Activity "AA" like this,
in OnCreate(),
if (savedInstanceState == null) {
A fragment = new A();
replaceFragment(fragment, false, Constants.HOME_FRG_TAG);
Handler handler = new Handler(Looper.getMainLooper());
Runnable runnable = new Runnable() {
#Override
public void run() {
if (getIntent().getStringExtra("FROM AC") != null) {
updateDisplay(1);
}
}
};
handler.postDelayed(runnable, 10);
}
and for replacing fragments,
public void updateDisplay(int position) {
Fragment fragment = null;
String tag = null;
switch (position) {
case 0:
clearStack();
mDrawerLayout.closeDrawer(mDrawerList);
break;
case 1:
fragment = new B();
tag = "B";
break;
case 2:
fragment = new C();
tag = "C";
break;
default:
break;
}
if (fragment != null) {
replaceFragment(fragment, true, tag);
setTitle(navMenuTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
} else {
Log.e("Activity", "Error in creating fragment");
}
}
replaceFragment() function,
public void replaceFragment(Fragment newFragment, boolean backStackTag, String fragmentTag) {
try {
Fragment selectedFrag = getSupportFragmentManager().findFragmentByTag(fragmentTag);
if (selectedFrag != null && selectedFrag.isVisible()) {
return;
}
FragmentManager fm = AA.this.getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
if (backStackTag) transaction.addToBackStack(null);
transaction.commit();
} catch (Exception e) {
Log.e("exception ", " on adding fragment");
// TODO: handle exception
}
}
and clearStack(),
public void clearStack() {
FragmentManager fm = AA.this.getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
in AC Activity i have tried to come back to fragment "B" like this,
Intent in = new Intent(AC.this, AA.class);
in.putExtra("FROM AC", "from ac");
startActivity(in);
now this does what i intend to do but the problem is when it is loading fragment "A" opens for a brief time and then it comes back to the fragment "B".
How Do i navigate to fragment "B" from Activity "AC" properly?? please any help would be appreciated...!!
First when you go from AB to AC start it as with startActvityForResult, and make sure you don't pass the clear backstack flags. Do it just like this:
public static final int REQ_CODE = 1;
Intent in = new Intent(this, AB.class);
startActivityForResult(in, REQ_CODE);
So the backstack is not cleared. When replacing the fragments in AA do it like this:
public void replaceFragment(Fragment newFragment, boolean backStackTag, String fragmentTag) {
try {
Fragment selectedFrag = getSupportFragmentManager().findFragmentByTag(fragmentTag);
if (selectedFrag != null && selectedFrag.isVisible()) {
return;
}
FragmentManager fm = AA.this.getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.container, fragmentB).commit();
} catch (Exception e) {
Log.e("exception ", " on adding fragment");
// TODO: handle exception
}
}
And when you want to get back from activity AC, set the result to RESULT_OK if you want to navigate back to AA or RESULT_CANCELED if not.
setResult(Activity.RESULT_OK);
finish();
In AB, override the onActivityResult method so it sends you back to AA:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQ_CODE) {
if (resultCode == RESULT_OK) {
finish();
}
}
}
so if RESULT_OK is passed, it will go back to AA where the activity was still in onStop() and the state was saved. Also make sure to init your views in onCreate and not in onStart.
Use startActivityForResult to pass params from AC to AA.It's a little complicated.EventBus may be helpful to you.

findFragmentByTag returns null in Activity at some places

I know this question has been asked so many times but I have tried every thing which was answered
like
getSupportFragmentManager().executePendingTransactions();
used fragmentTransaction.replace
my problem is when I use findFragmentByTag, it works at one place and does not work at other place.
I am not getting where I am doing wrong because findFragmentByTag return fragment in R.id.action_clean case but does not work in R.id.action_cart case.
my code is
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id){
case R.id.action_cart: // don't work in this case
if (Cart.getProductCount(this) > 0) {
if (getSupportFragmentManager().findFragmentByTag(CartFragment.class.getName()) != null) {
if (getSupportFragmentManager().findFragmentByTag(CartFragment.class.getName()).isVisible()) {
Log.v("visible","visible");
}
Log.v("visible2","not null");
Toast.makeText(this, "Cart is not empty", Toast.LENGTH_SHORT).show();
}
else{
changeFragment(new CartFragment());
}
}else{
Toast.makeText(this,"Cart is empty",Toast.LENGTH_SHORT).show();
}
break;
case R.id.action_login:
changeFragment(new LoginFragment());
// Toast.makeText(this,"login",Toast.LENGTH_SHORT).show();
break;
case R.id.action_signup:
changeFragment(new UserDetailFragment());
//Toast.makeText(this,"sign up",Toast.LENGTH_SHORT).show();
break;
case R.id.action_clean: // work here
if(Cart.clearCart(this)){
Toast.makeText(this,"All items has been removed from Cart",Toast.LENGTH_SHORT).show();
updateCartCount();
if (getSupportFragmentManager().findFragmentByTag(CartFragment.class.getName()) != null
&& getSupportFragmentManager().findFragmentByTag(CartFragment.class.getName()).isVisible()) {
removeFragment(getSupportFragmentManager().findFragmentByTag(CartFragment.class.getName()));
}
}else Toast.makeText(this,"Cart can not be cleaned",Toast.LENGTH_SHORT).show();
break;
}
return super.onOptionsItemSelected(item);
}
and here is the changeFragment
#Override
public void changeFragment(Fragment fragment, CustomDictionary... dictionary) {
FragmentTransaction ft= getSupportFragmentManager().beginTransaction();
Bundle bundle = new Bundle();
if (dictionary != null && dictionary.length > 0) {
for (CustomDictionary dic : dictionary) {
bundle.putString(dic.getKey(),dic.getValue());
}
}
fragment.setArguments(bundle);
ft.setCustomAnimations(R.anim.enter, R.anim.exit);
ft.replace(R.id.fragmentContainer, fragment,fragment.getClass().getName()) // tag
.addToBackStack(fragment.getClass().getName())
.commit();
getSupportFragmentManager().executePendingTransactions();
}
removeFragment()
#Override
public void removeFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().remove(fragment)
.commit();
fragmentManager.popBackStack();
}
You used different name for tags...
you assigned tag by
fragment.getClass().getSimpleName()
And call it by
CartFragment.class.getName()
So just use one of them for both process setting and getting by tag.
P.S. You set tag when you call addToBackStack !
----- Update:
I would suggest to iterate all fragments you have in backstack by:
for (Fragment fragment : getFragmentManager().getFragments()) {
try {
Log.v(TAG,"fragment:"+fragment.getTag()+", isVisible:"+fragment.isVisible());
} catch (NullPointerException e) {
}
}
Then it will be clear what is the tag of fragment to call if exists :-)
use getSupportFragmentManager instead of getFragmentManager when call from activity.

Multi Fragment Save/Restore fail after Rotate device

I have a problem, in my Activity I have a NavigationDrawer, I use to call 3 fragment.
I have implemented the onSaveInstanceState/onRestoreInstanceState for the Fragment active, all the data are saved correctly, but when I rotate the device, the savedInstanceState (inside onCreate) is not null and the NavigationDrawer not call the Fragment.
now I have broken my head to think a solution....
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dualpane);
if(savedInstanceState == null)
instantiateFragments(null);//init
// Handle Toolbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
if (null != toolbar) {
setSupportActionBar(toolbar);
//set the back arrow in the toolbar
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
//Create the AccountHeader
headerResult = new AccountHeaderBuilder()
.withActivity(this)
.withTranslucentStatusBar(false)
.withSavedInstance(savedInstanceState)
.build();
Fragment_1 = new PrimaryDrawerItem()
.withName("Fragment 1")
.withIdentifier(1);
Fragment_2 = new PrimaryDrawerItem()
.withName("Fragment 2")
.withIdentifier(2);
Fragment_3 = new PrimaryDrawerItem()
.withName("Fragment 3")
.withIdentifier(3);
builder = new DrawerBuilder()
.withActivity(this)
.withToolbar(toolbar)
.withTranslucentStatusBar(false)
.withAccountHeader(headerResult) //set the AccountHeader we created earlier for the header
.addDrawerItems(
Fragment_1,
Fragment_2,
Fragment_3
) // add the items we want to use with our Drawer
// .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
// #Override
// public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
// // do something with the clicked item :D
// if (drawerItem != null && drawerItem instanceof Nameable) {
// String name = ((Nameable) drawerItem).getName().getText(CustomListActivity.this);
// getSupportActionBar().setTitle(name);
// FragmentManager mFragmentManager = getSupportFragmentManager();
// FragmentTransaction transaction = mFragmentManager.beginTransaction();
// Log.d(TAG, "onCreate: savedInstanceState = " + (savedInstanceState == null ? "NULL" : "Not NULL"));
// if (savedInstanceState == null) {
// switch (position) {
// case 1:
// transaction.replace(R.id.fragment_container, Fragment1.newInstance(), FRAGMENT_TAG1).commit();
// break;
// case 2:
// transaction.replace(R.id.fragment_container, Fragment2.newInstance(), FRAGMENT_TAG2).commit();
// break;
// case 3:
// transaction.replace(R.id.fragment_container, Fragment3.newInstance("Terzo"), FRAGMENT_TAG3).commit();
// break;
// }
// }else{
// instantiateFragments(savedInstanceState);
// }
// /* FragmentManager mFragmentManager = getSupportFragmentManager();
// Fragment fragment = mFragmentManager.findFragmentById(R.id.fragment_container);
// fragment1 = (Fragment1) mFragmentManager.findFragmentByTag(FRAGMENT_TAG1);
// fragment2 = (Fragment2) mFragmentManager.findFragmentByTag(FRAGMENT_TAG2);
// fragment3 = (Fragment3) mFragmentManager.findFragmentByTag(FRAGMENT_TAG3);
// if (savedInstanceState == null) {
//
// // List<Fragment> lista = mFragmentManager.getFragments();
// if (fragment == null) {
// mFragmentManager.beginTransaction().add(R.id.fragment_container, Fragment3.newInstance("Terzo"), FRAGMENT_TAG3).commit();
// mFragmentManager.beginTransaction().add(R.id.fragment_container, Fragment2.newInstance(), FRAGMENT_TAG2).commit();
// mFragmentManager.beginTransaction().add(R.id.fragment_container, Fragment1.newInstance(), FRAGMENT_TAG1).commit();
//
// } else {
// //mFragmentManager.beginTransaction().remove(fragment).commit();
// mFragmentManager.beginTransaction().detach(fragment).commit();
//
// switch (position) {
// case 1:
// mFragmentManager.beginTransaction().attach(fragment1).commit();
// break;
// case 2:
// mFragmentManager.beginTransaction().attach(fragment2).commit();
// break;
// case 3:
// //bSavePage = new Bundle();
// //bSavePage.putString("section_name", "Quarto");
// //fragment3.setArguments(bSavePage);
// Bundle args = new Bundle();
// args.putString("someString", "Quarto");
// // Put any other arguments
// fragment3.setArguments(args);
// Fragment.instantiate(getApplicationContext(), Fragment3.class.getName(), args);
// mFragmentManager.beginTransaction().attach(fragment3).commit();
// break;
// }
// }
// } else {
// // probabilmente e' accaduta una rotazione
// mFragmentManager.beginTransaction().detach(fragment).commit();
// switch (position) {
// case 1:
// mFragmentManager.beginTransaction().attach(fragment1).commit();
// break;
// case 2:
// mFragmentManager.beginTransaction().attach(fragment2).commit();
// break;
// case 3:
// Bundle args = new Bundle();
// args.putString("someString", "Quarto");
// // Put any other arguments
// fragment3.setArguments(args);
// Fragment.instantiate(getApplicationContext(), Fragment3.class.getName(), args);
// mFragmentManager.beginTransaction().attach(fragment3).commit();
// break;
// }
// }*/
// getSupportActionBar().setTitle(name);
// }
// return false;
// }
// }
//
// )
.withOnDrawerListener(new Drawer.OnDrawerListener() {
#Override
public void onDrawerOpened(View drawerView) {
KeyboardUtil.hideKeyboard(CustomListActivity.this);
}
#Override
public void onDrawerClosed(View drawerView) {
}
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
}
}
)
.withFireOnInitialOnClick(true)
.withSavedInstance(savedInstanceState);
result = builder.build();
#Override
protected void onSaveInstanceState(Bundle outState) {
//add the values which need to be saved from the drawer to the bundle
outState = result.saveInstanceState(outState);
//add the values which need to be saved from the accountHeader to the bundle
outState = headerResult.saveInstanceState(outState);
super.onSaveInstanceState(outState);
Log.d(TAG, "onSaveInstanceState");
FragmentManager mFragmentManager = getSupportFragmentManager();
mMyFragment = mFragmentManager.findFragmentById(R.id.fragment_container);
mFragmentManager.putFragment(outState, "SaveFrag", mMyFragment);
outState.putString("TAG", mMyFragment.getTag());
}
#Override
protected void onRestoreInstanceState(Bundle inState) {
super.onRestoreInstanceState(inState);
Log.d(TAG, "onRestoreInstanceState");
instantiateFragments(inState);
}
private void instantiateFragments(Bundle inState) {
FragmentManager mFragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = mFragmentManager.beginTransaction();
if (inState != null) {
mMyFragment = (Fragment) mFragmentManager.getFragment(inState, "SaveFrag");
transaction.replace(R.id.fragment_container, mMyFragment, inState.getString("TAG"));
} /*else {
// inizializzazione
transaction.add(R.id.fragment_container, Fragment1.newInstance(), FRAGMENT_TAG1);
transaction.commit();
}*/
}
EDIT**
I have implemented onPostCreate in my Activity and moved the code withOnDrawerItemClickListener inside and now works!
#Override
protected void onPostCreate( final Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
Log.d(TAG, "onPostCreate");
builder.withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
#Override
public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
if (drawerItem != null && drawerItem instanceof Nameable) {
String name = ((Nameable) drawerItem).getName().getText(CustomListActivity.this);
getSupportActionBar().setTitle(name);
FragmentManager mFragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = mFragmentManager.beginTransaction();
Log.d(TAG, "onCreate: savedInstanceState = " + (savedInstanceState == null ? "NULL" : "Not NULL"));
//if (savedInstanceState == null) {
switch (position) {
case 1:
transaction.replace(R.id.fragment_container, Fragment1.newInstance(), FRAGMENT_TAG1).commit();
break;
case 2:
transaction.replace(R.id.fragment_container, Fragment2.newInstance(), FRAGMENT_TAG2).commit();
break;
case 3:
transaction.replace(R.id.fragment_container, Fragment3.newInstance("Terzo"), FRAGMENT_TAG3).commit();
break;
}
//}else{
//instantiateFragments(savedInstanceState);
//}
getSupportActionBar().setTitle(name);
}
return false;
}
});
}

Fragment replacing problems

I'm having issues with fragment replacing implementing a navigation drawer.
The problem is layout overlapping, but it happens only if I let the application on the background for a long time (I asume after the activity goes to Stop).
This is the code I'm using for changing fragments. I'm not doing anything in onStop method
(Should I be doing something?)
#Override
public void onNavigationDrawerItemSelected(int position) {
if(lastPosition == position){
return;
}
FragmentTransaction transaction = fragmentManager.beginTransaction();
Fragment lastFragment = fragmentManager.findFragmentByTag( lastTag );
Fragment fragment;
if ( lastFragment != null ) {
transaction.hide( lastFragment );
}
switch (position) {
case 0:
lastTag = "miPerfil";
lastPosition = 0;
fragment = fragmentManager.findFragmentByTag("miPerfil");
if(fragment != null) {
transaction.remove(fragment);
}
transaction.add(R.id.container, MiPerfilFragment.newInstance(position + 1),"miPerfil");
break;
case 1:
lastTag = "misReportes";
lastPosition = 1;
fragment = fragmentManager.findFragmentByTag("misReportes");
if(fragment != null) {
transaction.remove(fragment);
}
transaction.add(R.id.container, MisReportesFragment.newInstance(position + 1),"misReportes");
break;
case 2:
lastTag = "mapFragment";
lastPosition = 2;
fragment = fragmentManager.findFragmentByTag("mapFragment");
if(fragment != null) {
transaction.show(fragment);
}else{
transaction.add(R.id.container, MapFragment.newInstance(position + 1),"mapFragment");
}
break;
case 3:
moveTaskToBack(true);
return;
}
transaction.addToBackStack( lastTag ).commit();
}
Thanks.
there is two solution that you can try to overcome from your problem of overlapping fragment.
try (1) set a background color to your fragment in xml file.
if it does not work,
try (2) fixing this by writing your own code to remove any existing fragments before committing a new one.
for example:
fragmentManager = getFragmentManager();
ft = fragmentManager.beginTransaction();
mbFragment = new SettingsManageBooksFragment();
ft.replace(R.id.setting_detail_container2, mbFragment).commit();
mImgFragmentTitle.setImageResource(R.drawable.manage_my_books);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.imageButtonSettingsManageBooks:
if (mPurchaseHistory == true) {
ft.remove(phFragment);
Log.d(TAG, "REMOVING PURCHASE HISTORY FRAG");
} else if (mAudio == true) {
ft.remove(aFragment);
Log.d(TAG, "REMOVING AUDIO FRAG");
} else if (mRestore == true) {
ft.remove(rFragment);
Log.d(TAG, "REMOVING RESTORE FRAG");
} else if (mCopyright == true) {
ft.remove(cFragment);
Log.d(TAG, "REMOVING COPYRIGHT FRAG");
} else if (mAbout == true) {
ft.remove(abFragment);
Log.d(TAG, "REMOVING ABOUT FRAG");
}
ft = fragmentManager.beginTransaction();
mbFragment = new SettingsManageBooksFragment();
ft.replace(R.id.setting_detail_container2, mbFragment).commit();
mImgFragmentTitle.setImageResource(R.drawable.manage_my_books);
mManageBooks = true;
mPurchaseHistory = false;
mAudio = false;
mRestore = false;
mCopyright = false;
mAbout = false;
break;
hope it will helps....
if you use first solution You may also come up with problems where the fragment behind your new fragment is still clickable. If this happens then just make the parent view of the new fragment clickable..

Categories

Resources