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 ツ