i'm using a navigation drawer to switch between fragments , each time i move to a new one ,it's completely recreated and the previous one is completely destroyed, so i want to conserve the state of fragments while swapping and back again
Runnable mPendingRunnable = new Runnable() {
#Override
public void run() {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);
Fragment fragment=getHomeFragment();
fragmentTransaction.replace(R.id.frame,fragment,CURRENT_TAG);
fragmentTransaction.commitAllowingStateLoss();
}
};
if (mPendingRunnable != null) {
mHandler.post(mPendingRunnable);
}
and the getHomeFragment() :
public Fragment getHomeFragment() {
switch (navItemIndex) {
case 0:
HomeFragment homeFragment = new HomeFragment();
return homeFragment;
case 1:
BoiteRFragment boiteRFragment = new BoiteRFragment();
return boiteRFragment;
case 2:
InfoPersFragment infoPersFragment = new InfoPersFragment();
return infoPersFragment;
case 3:
NotificationsFragment notificationsFragment = new NotificationsFragment();
return notificationsFragment;
case 4:
PrametresFragment prametresFragment = new PrametresFragment();
return prametresFragment;
default:
return new HomeFragment();
}
}
Related
I have problem with implement fragment and bottom bar on my apps..
I wan to switch fragment according initialize bottom bar..
this my code
private Fragment frag_summary = new SummaryFragment();
private Fragment frag_my_proposal = new MyProposalFragment();
private Fragment frag_proposal = new ProposalFragment();
private Fragment frag_friends = new FriendsFragment();
bottomNavigation.setOnTabSelectListener(new OnTabSelectListener() {
#Override
public void onTabSelected(#IdRes int tabId) {
setSelectedFragment(tabId);
}
});
public void setSelectedFragment(int id) {
switch (id) {
case R.id.menu_home:
setFragment(id, frag_summary);
break;
case R.id.menu_my_proposals:
setFragment(id, new MyProposalFragment());
break;
case R.id.menu_proposal:
setFragment(id, new ProposalFragment());
break;
case R.id.menu_friends:
setFragment(id, new FriendsFragment());
break;
case R.id.menu_more:
/* drawer.openDrawer(GravityCompat.START);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
drawer.openDrawer(GravityCompat.START);
}*/
break;
default:
setFragment(id, frag_summary);
break;
}
}
private void setFragment(int id, Fragment fragments) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
String fragmentTag = String.valueOf(id);
if (frag_summary.isAdded()) {
fragmentTransaction.hide(frag_summary);
}
if (frag_my_proposal.isAdded()) {
fragmentTransaction.hide(frag_my_proposal);
}
if (frag_proposal.isAdded()) {
fragmentTransaction.hide(frag_proposal);
}
if (frag_friends.isAdded()) {
fragmentTransaction.hide(frag_friends);
}
if (fragments.isAdded()) {
fragmentTransaction.show(fragments);
} else {
fragmentTransaction.add(R.id.content_frame, fragments, fragmentTag);
}
fragmentTransaction.commitAllowingStateLoss();
}
The Issue is : When I selected from Fragment frag_summary to Fragment frag_friends, Fragment frag_summary and other fragment sometimes still showed.. like other activity ex: from Fragment frag_friends to Fragment frag_proposal .
sho how to fix it ?
sorry for my english
Repalce the code in setFragment with -
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragments, fragmentTag);
fragmentTransaction.commitAllowingStateLoss();
Basically you are replacing the current visivble fragment.
Edit : Change the code as below -
public void setSelectedFragment(int id) {
switch (id) {
case R.id.menu_home:
setFragment(id, frag_summary);
break;
case R.id.menu_my_proposals:
setFragment(id, /*send the class instance you created for this fragment */);
break;
case R.id.menu_proposal:
setFragment(id, /*send the class instance you created for this fragment */);
break;
case R.id.menu_friends:
setFragment(id, /*send the class instance you created for this fragment */);
break;
case R.id.menu_more:
/* drawer.openDrawer(GravityCompat.START);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
drawer.openDrawer(GravityCompat.START);
}*/
break;
default:
setFragment(id, frag_summary);
break;
}
}
I have this problem with overlapping fragments. I read other resolutions, but they seem to be over complicated as for problem like this. It happens when app is not used for sometime and then it's resumed or recreated and it seems that it remembers last fragment and creates the new one as if app have been destroyed last time.
Is that something related to savedInstanceState?
Code:
// used in onCreate()
private void setUpFragments(){
Fragment fragment;
switch (fragmentName){
case CALLS:
fragment = new CallLogsFragment();
break;
case CONTACTS:
fragment = new ContactListFragment();
break;
case SETUP:
fragment = new SetupFragment();
break;
case REGISTER:
fragment = new RegisterFragment();
break;
default:
fragment = new SetupFragment();
}
getFragmentManager().beginTransaction()
.add(R.id.fragment_container, fragment)
.commit();
}
#Override
public boolean onNavigationItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.nav_calls:
setFragment(new CallLogsFragment());
break;
case R.id.nav_contacts:
setFragment(new ContactListFragment());
break;
case R.id.nav_add_contacts:
setFragment(new AddContactsFragment());
break;
case R.id.nav_setup:
setFragment(new SetupFragment());
break;
default:
setFragment(new ContactListFragment());
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
public void setFragment(Fragment fragment){
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
After default you do not have
break;
default:
fragment = new SetupFragment();
than it should be in both cases
default:
fragment = new SetupFragment();
break;
You can check my code:
in the begging of the program (in onCreate)
getSupportFragmentManager()
.beginTransaction()
.addToBackStack(null)
.add(FRAME_LAYOUT,
createFragment(defaultCurrentItem),
createItemDescription(defaultCurrentItem))
.commit();
The function to begin transaction
private Fragment createFragment(int position){
switch (position) {
case BOT_NAV_POSITION_SETTINGS:
return new SettingsFragment_();
case BOT_NAV_POSITION_STATISTICS:
return new StatisticsFragment_();
case BOT_NAV_POSITION_MAIN:
return new MainFragment_();
case BOT_NAV_POSITION_FORTH:
return new ForthFragment_();
case BOT_NAV_POSITION_REMINDERS:
return new ReminderFragment_();
}
throw new IllegalArgumentException();
}
And later when you need to change fragment
getSupportFragmentManager()
.beginTransaction()
.replace(FRAME_LAYOUT,
createFragment(position),
createItemDescription(position))
.addToBackStack(null)
.commit();
You are right, setup the fragments(i.e call setupFragments) only if activity is newly created(i.e savedInstanceState == null).
On activity recreation, activity's fragment manager will restore its old state. If you didn't check for savedInstanceState, yours newly committed fragment and fragment manager's restored fragment will be overlapped.
I have a navigation drawer in my activity and add the fragments on drawer item clicked
For adding the fragment
Fragment fragment = null;
switch (position) {
case 0:
fragment = new Fragment()1;
break;
case 1:
fragment = new Fragment()2;
break;
case 2:
fragment = new Fragment()3;
break;
case 3:
fragment = new Fragment()4;
break;
case 4:
fragment = new Fragment()5;
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.frame_container, fragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
closeDrawer();
} else {
Logger.e("MainActivity", "Error in creating fragment");
}
Whenever I switch back from one fragment to another fragment the view is inflated again as in previous fragment was destroyed and it is being created again.
How can I stop it from being recreated?
Fragment fragment1 = null;
Fragment fragment2 = null;
Fragment fragment3 = null;
Fragment fragment4 = null;
Fragment fragment5 = null;
switch (position) {
case 0:
if (fragment1 == null) {
fragment1 = new Fragment()1;
}
break;
case 1:
if (fragment2 == null) {
fragment2 = new Fragment()2;
}
break;
case 2:
if (fragment3 == null) {
fragment3 = new Fragment()3;
}
break;
case 3:
if (fragment4 == null) {
fragment4 = new Fragment()4;
}
break;
case 4:
if (fragment5 == null) {
fragment5 = new Fragment()5;
}
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.frame_container, fragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
closeDrawer();
} else {
Logger.e("MainActivity", "Error in creating fragment");
}
There is problem with my fragment, they are showed together, one on the second fragment. How to disapear, and only show one of them?
Definiton:
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
fr = new avc);
FragmentTransaction ft = ((TestingActivity)context).getFragmentManager().beginTransaction();
ft.replace(R.id.test, fr);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
});
And definiton of container below:
<FrameLayout
android:id="#+id/test"
android:layout_width="match_parent"
android:layout_height="match_parent" />
You can use some thing like this. Make a function for showing a fragment and call each time this function with different parameter.
eg. If You want to show "HomeFragment" then call displayView(0) and if you want to show "FindPeopleFragment" then call displayView(1)
private void displayView(int position) {
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 0:
fragment = new HomeFragment();
break;
case 1:
fragment = new FindPeopleFragment();
break;
case 2:
fragment = new PhotosFragment();
break;
case 3:
fragment = new CommunityFragment();
break;
case 4:
fragment = new PagesFragment();
break;
case 5:
fragment = new WhatsHotFragment();
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment).commit();
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
setTitle(navMenuTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
} else {
// error in creating fragment
Log.e("MainActivity", "Error in creating fragment");
}
}
So I have my navigation drawer with 5 different options. They all open a new fragment that I have created. The first one is Home, and I am trying to find a way to bring it back to the first screen that shows up under the navigation drawer. It has the id of "container", in the main_activity.xml. I do not want to use and intent to call the entire class again to load up. Also I do not want to be able to use the back button from another intent. I am confused on how to make this happen.
#Override
public void onNavigationDrawerItemSelected(int position) {
FragmentHowItWorks fragmentHow;
FragmentSettings fragmentSettings;
FragmentTransaction transaction = getFragmentManager().beginTransaction();
switch(position){
case 0:
// should I call the layout?
// this is the "Home" option
break;
case 1:
fragmentHow = new FragmentHowItWorks();
transaction.replace(R.id.container, fragmentHow);
transaction.addToBackStack(null);
transaction.commit();
break;
case 2:
fragmentSettings = new FragmentSettings();
transaction.replace(R.id.container, fragmentSettings);
transaction.addToBackStack(null);
transaction.commit();
break
case 3:
fragment = new FragmentHowItWorks();
transaction.replace(R.id.container, fragment);
transaction.addToBackStack(null);
transaction.commit();
break;
case 4:
fragment = new FragmentHowItWorks();
transaction.replace(R.id.container, fragment);
transaction.addToBackStack(null);
transaction.commit();
break;
}
}
Use methods add,hide and show,
Step1 Prepare all your fragments
Fragment fragment1 = new FragmentOne();
Fragment fragment2 = new FragmentTwo();
Fragment fragment3 = new FragmentThree();
Fragment mCurrentFragment = null;
Step2 Show/hide your fragments
#Override
public void onNavigationDrawerItemSelected(int position) {
Fragment fragment;
switch (position) {
case 1:
fragment = fragment1;
break;
case 2:
fragment = fragment2;
break;
case 3:
fragment = fragment3;
break;
}
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if(mCurrentFragment == null) {
ft.add(R.id.container, fragment).commit();
mCurrentFragment = fragment;
} else if(fragment.isAdded()) {
ft.hide(mCurrentFragment).show(fragment).commit();
} else {
ft.hide(mCurrentFragment).add(R.id.container, fragment).commit();
}
mCurrentFragment = fragment;
}
You can do this ,
You can get the name of current fragment which is in the container . This will return name including the package + fragment name
String name = getFragmentManager().findFragmentById(container id ).getClass().getName();
When you click on the home index of drawer, check weather the current name id equal to the home.
If it is home, you don't need to perform any action.
I know that this was asked and answered long time ago but, I would like to show my approach on this problem, maybe it will help anyone else:
I added a Fragment Name over each Fragment that I use like:
public class MainFragment extends BaseFragment {
public static final String FRAGMENT_TAG = "main";
// ... all your fragment
}
And on the Drawer Layout:
public void methodThatSetsTheUi() {
mDrawerView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
getFragmentManager().findFragmentByTag("main");
String tag = getFragmentTag(position);
replaceFragment(getOrCreateFragment(tag), tag);
mDrawerLayout.closeDrawer(mDrawerView);
}
});
}
#NonNull
private String getFragmentTag(int position) {
String tag;
switch (position) {
case MAIN_FRAGMENT_DRAWER_POSITION:
tag = MainFragment.FRAGMENT_TAG;
break;
case FAVORITE_FRAGMENT_DRAWER_POSITION:
tag = FavoriteFragment.FRAGMENT_TAG;
break;
default:
throw new AssertionError("That selection is wrong");
}
return tag;
}
private BaseFragment getOrCreateFragment(String fragmentName) {
BaseFragment fragment = (BaseFragment) getFragmentManager().findFragmentByTag(fragmentName);
if(fragment == null) {
fragment = FragmentFactory.createFragment(fragmentName);
}
return fragment;
}
and well, the FragmentFactory is just a simple Factory:
public final class FragmentFactory {
public static BaseFragment createFragment(String fragmentName) {
switch(fragmentName) {
case MainFragment.FRAGMENT_TAG:
return MainFragment.newInstance();
case FavoriteFragment.FRAGMENT_TAG:
return FavoriteFragment.newInstance();
// ... all fragments here.
default:
return null;
}
}
Hope to help someone.