i have implemented Drawer menu in my application. i have 7 different fragments in my app. the MainActivity which holds all the fragments is drawer activity. i have overriden the onBackPressed() method in this activity. i have a fragment where i would like user to save the data he has changed. that is if user have changed something in one fragment and without saving it if user leaves fragment (By selecting another fragment from drawer menu or by pressing a back button) then i want to show the confirmation dialog to user on same fragment where the changes were made. as an example.. if user have made some change in sixth fragment and he leaves the fragment (by selecting any other fragment or back button) i want to show user a confirmation dialog on sixth fragment itself. from where according to his input he can move the selected fragment or stay in the fragment where he made some changes.
Here is the snap of a code of my DrawerActivity.
#Override
public void onBackPressed() {
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
{
super.onBackPressed();
AppConstants.SELECTED_NAVIGATION_TAB=0;
return;
}
else { Toast.makeText(getBaseContext(), "Tap back button in order to exit", Toast.LENGTH_SHORT).show(); }
mBackPressed = System.currentTimeMillis();
}
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
Fragment fragment = null;
switch (id) {
case R.id.nav_home:
AppConstants.SELECTED_NAVIGATION_TAB = 0;
fragment = new HomeFragment();
title = getResources().getString(R.string.home);
break;
case R.id.nav_progress:
AppConstants.SELECTED_NAVIGATION_TAB = 1;
fragment = new ProgressFragment();
title = getResources().getString(R.string.progress);
break;
case R.id.nav_workouts:
AppConstants.SELECTED_NAVIGATION_TAB = 2;
/* if (Utilities.getInstance().getPreferences(DrawerActivity.this, AppConstants.PREF_KEY_USER_INFO,
AppConstants.PREF_KEY_SUBSCRIPTION_STATUS, "").equals("1")){
fragment = new FragmentPremiumClasses();
title = getResources().getString(R.string.premium);
}else {*/
fragment = new WorkoutsFragment();
title = getResources().getString(R.string.workouts);
// }
break;
case R.id.nav_subscription:
AppConstants.SELECTED_NAVIGATION_TAB = 3;
if (!Utilities.getInstance().getPreferences(DrawerActivity.this, AppConstants.PREF_KEY_USER_INFO,
AppConstants.PREF_KEY_SUBSCRIPTION_STATUS, "").equals("1")){
fragment = new SubscriptionFragment();
title = getResources().getString(R.string.subscription);
} else {
fragment = new SelectSocietyFragment();
title = getResources().getString(R.string.newsubscription);
}
break;
case R.id.nav_aboutUs:
AppConstants.SELECTED_NAVIGATION_TAB = 4;
fragment = new AboutUsFragment();
title = getResources().getString(R.string.aboutus);
break;
case R.id.nav_settings:
AppConstants.SELECTED_NAVIGATION_TAB = 5;
fragment = new SettingsFragment();
title = getResources().getString(R.string.settings);
break;
case R.id.nav_logout:
drawer.closeDrawer(GravityCompat.START);
isLogoutClicked = true;
SharedPreferences.Editor editor = getSharedPreferences(AppConstants.PREF_KEY_USER_INFO,
Context.MODE_PRIVATE).edit();
editor.clear();
editor.commit();
AppConstants.SELECTED_NAVIGATION_TAB = 0;
Utilities.getInstance().finishAndStartIntent(DrawerActivity.this, MainActivity.class, 0, 0);
break;
}
if (!isLogoutClicked) {
getSupportActionBar().setTitle(title);
android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame, fragment);
fragmentTransaction.commit();
drawer.closeDrawer(GravityCompat.START);
}
return true;
}
Hope i have made the question clear, how to achieve this functionality? any help would be much appreciated :)
thanks :)
Save data in onPause() of fragment.
Related
I know there are similar questions to the one I'm asking but none of them was able to solve the issue I'm having.
I Have a bottom navigation view with five fragments that use viewpager, one of these fragments opens an activity.
Problem
When I open the activity from the fragment it works fine but the issue is the when I press back it goes back to the same fragment that opens the activity.
Solution
I want when I press back out of the activity that it goes to a previous fragment apart from the fragment that calls the activity.
For example: if the user is on HomeFragment and the user clicks the fragment that opens the activity(NewsFragment), and the user press back they Should go back to HomeFragment, not NewsFragment.
What I tried so far:
MainActivity for the BottomnNvigationView and it's On Back Press
private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.nav_library:
viewPager.setCurrentItem(0);
temp = temp.replace("-0", "") + "-0";
break;
case R.id.nav_technology:
viewPager.setCurrentItem(1);
temp = temp.replace("-1", "") + "-1";
break;
case R.id.nav_home:
viewPager.setCurrentItem(2);
temp = temp.replace("-2", "") + "-2";
break;
case R.id.nav_science:
viewPager.setCurrentItem(3);
temp = temp.replace("-3", "") + "-3";
break;
case R.id.nav_news:
viewPager.setCurrentItem(4);
temp = temp.replace("-4", "") + "-4";
Intent intent = new Intent(MainActivity.this,BrowserActivity.class);
startActivity(intent);
return true;
}
return true;
}
};
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout)findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
}
else {
String[] words = temp.split("-");
if(words.length<=2)
if (viewPager.getCurrentItem() != 2) {
temp = "";
viewPager.setCurrentItem(2);
}else
finish();
else {
temp = temp.replace("-" + words[words.length - 1], "");
int pos = viewPager.getCurrentItem();
if (viewPager.getCurrentItem() == pos)
pos = 2;
else
pos = 1;
viewPager.setCurrentItem(Integer.parseInt(words[words.length - pos]));
}
}
}
The Activity that is call from the fragment (BrowersActivity) On Back Press
#Override
public void onBackPressed() {
if (viewPager.getCurrentItem() != 0) {
viewPager.setCurrentItem(viewPager.getCurrentItem() - 1,false);
}else{
finish();
}
}
Any help would be appreciated.
Quickest solution would be to finish the first activity after starting the second one so:
case R.id.nav_news:
viewPager.setCurrentItem(4);
temp = temp.replace("-4", "") + "-4";
Intent intent = new Intent(MainActivity.this,BrowserActivity.class);
startActivity(intent);
finish()
return true;
And in the second activity in onBackPressed, restart the first activity
#Override
public void onBackPressed() {
super.onBackPressed()
startActivity(new Intent(this, FirstActivity.class))
}
I have created an app with a bottom navigation fragment which consists of 5 main fragments and one extra sub fragment (login Fragment). the thing is I want this login fragment to be replaced with the userAccount fragment once user has logged in successfully.
Note: I am running the App statically at first so I am using a variable Boolean Called Status to check whether user has logged in or not
private static final boolean Status = false;
final Fragment f1 = new HomeFragment();
final Fragment f2 = new SearchFragment();
final Fragment f3 = new CameraFragment();
final Fragment f4 = new ChatFragment();
final Fragment f5 = new AccountFragment();
// logginFragment page should be replaced with AccountFragment once user logged in successfully
final Fragment f6 = new logginFragment();
private BottomNavigationViewEx.OnNavigationItemSelectedListener navListener =
new BottomNavigationViewEx.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_home:
fm.beginTransaction().hide(active).show(f1).commit();
active = f1;
return true;
case R.id.nav_search:
fm.beginTransaction().hide(active).show(f2).commit();
active = f2;
return true;
case R.id.nav_camera:
fm.beginTransaction().hide(active).show(f3).commit();
active = f3;
return true;
case R.id.nav_chat:
fm.beginTransaction().hide(active).show(f4).commit();
active = f4;
return true;
case R.id.nav_account:
fm.beginTransaction().hide(active).show(f5).commit();
active = f5;
return true;
}
/* \getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
selectedFragment).commit();*/
return false;
}
};
Your Code changes the fragment only when one of the Bottom Navigation Bar item is selected. You can replace the login fragment with account fragment when the login is successful(i.e when button is tapped) and set it to active rather than listening for the change in selection. Let me know if this helps.
void login()
{
if(Successful)
{
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_login,R.id.fragment_account)
.commit();
}
}
I have a Navigation Drawer which has 5 items.
If user selects an Item, I'm loading respective Fragment in FrameLayout
Now, if user pulls out the Navigation Drawer and selects the same Item as previous, I should not load the same Fragment again, so I'm saving the selected position and if previous selected position equals current selection I'm just closing the Navigation Drawer as follows:
String title = null;
invalidateOptionsMenu();
android.support.v4.app.Fragment fragment = null;
if (position == getPrevSelectedItem()) {
// Already selected fragment is being displayed
} else {
switch (position) {
case Numerics.ZERO:
fragment = new DashBoardFragment();
title = fragment.getClass().getSimpleName();
break;
case Numerics.ONE:
break;
case Numerics.TWO:
break;
case Numerics.THREE:
break;
case Numerics.FOUR:
break;
default:
break;
}
if (fragment != null) {
showFragment(fragment, title);
}
setSelectedItem(position);
}
I'm adding fragments by adding to backstack in order to provide back navigation to previous fragment as follows :
if (fragment != null) {
String backStateName = fragment.getClass().getName();
mFragmentManager = getSupportFragmentManager();
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.dashboard_container, fragment);
mFragmentTransaction.addToBackStack(backStateName);
mFragmentTransaction.commit();
}
The problem is:
If I select Item no:3 and then select Item:4, if I navigate back the previous selection is still 4, but I'm displaying Fragment with no:3. So, if I select Item no:3 again from Navigation Drawer the Fragment loads again. How to solve this ??
EDIT:
public int getPrevSelectedItem() {
return selectedItem;
}
public void setSelectedItem(int selectedItem) {
this.selectedItem = selectedItem;
}
try this
Fragment currentFragment = getActivity().getFragmentManager().findFragmentById(R.id.dashboard_container);
if(currentFragment instanceof YouFragmentName)
return
you can check the instance of loaded fragment on clicking the menu
Fragment loadedFragment= getFragmentManager().findFragmentById(R.id.fragmentLoadingSpace);
if( !(loadedFragment instanceof FragmentName1)){
// load fragment
}
I think there is no need of else statement or you can use else only for closing drawer
public int prevPosition=-1;
if (getPrevSelectedItem() != prevPosition) {
// Already selected fragment is being displayed
prevPosition =getPrevSelectedItem();
callFragment(position);
}
private void callFragment(int position) {
// TODO Auto-generated method stub
switch (position) {
case Numerics.ZERO:
fragment = new DashBoardFragment();
title = fragment.getClass().getSimpleName();
break;
case Numerics.ONE:
break;
case Numerics.TWO:
break;
case Numerics.THREE:
break;
case Numerics.FOUR:
break;
default:
break;
}
if (fragment != null) {
showFragment(fragment, title);
}
setSelectedItem(position);
}
From my comment:
The drawer does not get updated when you press back - so you need to add some code to onBackPressed() in the activity, where you update the position according to the popped BackstackEntry.
#Override
public void onBackPressed(){
String backStackEntryName = fragmentManager.getBackStackEntryAt(backCount - 2).getName();
int id = R.id.my_main_frag; //default option
if (MyMainFrag.class.getName().equals(backStackEntryName)){
id = R.id.my_main_frag;
selectedItem = 0;
} else if (MySecondFrag.class.getName().equals(backStackEntryName)){
id = R.id.my_second_frag;
selectedItem = 1;
}
...
navigation.setCheckedItem(id);
super.onBackPressed();
}
My app has a navigation drawer with three items linking to three fragments A, B and C
when I click on the back button from any of the Fragments, the app exits.I solved this by declaring these constants in my base activity:
public static boolean IS_FRAGMENT_A = false;
public static boolean IS_FRAGMENT_B = false;
public static boolean IS_FRAGMENT C = false;
and then in the selectView method I did this:
private void displayView(int position) {
IS_FRAGMENT_A = false;
IS_FRAGMENT_B = false;
IS_FRAGMENT_C = false;
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 0:
fragment = new FragmentA();
IS_FRAGMENT_A = true;
break;
case 1:
fragment = new FragmentB();
IS_FRAGMENT_B = true;
break;
case 2:
fragment = new FragmentC();
IS_FRAGMENT_C = true;
break;
default:
break;
}
And in the overriden onBackPressed() method I did this
public void onBackPressed() {
if (IS_FRAGMENT_A) {
finish();
} else {
displayView(0);
}
}
This works fine when am navigating to these fragments from the navigation drawer.However, when I go to any of the fragments through an ActionBar button, the onBackPressed method does not work.
In Fragment A, I have an ActionBar button that takes me to Fragment B:
public boolean onOptionsItemSelected(MenuItem menuItem) {
int id = menuItem.getItemId();
switch (id) {
case R.id.action_new:
Fragment fragmentB = new FragmentB();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_container, fragmentB);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
return true;
default:
return super.onOptionsItemSelected(menuItem);
}
}
When I press the back button from FragmentB after navigating to it via this method the app exits, unlike when I navigate to it through the navigation drawer.
I have tried adding this to the onCreate() method of FragmentB with no luck:
BaseActivity.IS_FRAGMENT_B = true;
My question is, how do I make the back button work in all fragments irrespective of how I got there?
I'm using NavigationDrawer with some fragments, the problem is when I'm in a fragment and hit the back button, it makes the app close, then I have to open it again, put my username and password all over again to use the app, how can I prevent that from happen?
public class NavigationMain extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
}
public void setFragmentList(int posicao) {
Fragment fragment = null;
switch (posicao) {
case 0:
fragment = new MainFragment();
break;
case 1:
fragment = new MensagensFragment();
break;
case 2:
fragment = new EscolasFragment();
break;
case 3:
fragment = new AutorizadasFragment();
break;
case 4:
fragment = new CadastroFragment();
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
// update selected item and title, then close the drawer
navigationAdapter.resetarCheck();
navigationAdapter.setChecked(posicao, true);
layoutDrawer.closeDrawer(linearDrawer);
} else {
// error in creating fragment
Log.e("MainActivity", "Error in creating fragment");
}
}
}
#Override
public void onBackPressed() {
int count = getFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
//additional code
} else {
getFragmentManager().popBackStack();
}
}
I think you missed to add the fragment transaction in your back stack. Try the following:
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).addToBackStack(null).commit();