Navigation in Navigation Drawer - android

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();
}

Related

RecyclerView in fragment(bottomNavigationView) doesn't shown up when reselected

I have bottomNavigationView with 3 menus. Middle item is selected by default when app starts.
Middle fragment contains a recycler view which fetches data from sharesPreferences.
But when I select different menu and again select middle menu(middle fragment), the recylerview from middle fragment just disappers...
Anyone know what could be the reason?
Created fragments
homeFragment = new HomeFragment(); //(middle fragment contains recycler view)
appSettingFragment = new AppSettingFragment();
infoFragment = new InfoFragment();
Changing fragments
//this method is used for changing first and last fragment
bottomNavigation.setOnNavigationItemSelectedListener(item -> {
switch (item.getItemId()) {
case R.id.settings:
btnAdd.setImageResource(R.drawable.ic_baseline_home_24);
addvis = false;
openFragment(appSettingFragment);
return true;
case R.id.info:
btnAdd.setImageResource(R.drawable.ic_baseline_home_24);
addvis = false;
openFragment(infoFragment);
return true;
}
return true;
});
// this is used for middle fragment
btnAdd.setOnClickListener(v -> {
if (addvis) {
startCreateFormActivity("Untitled Form");
} else {
addvis = true;
btnAdd.setImageResource(R.drawable.ic_baseline_add_24);
bottomNavigation.setSelectedItemId(R.id.home);
//homeFragment = new HomeFragment();
openFragment(homeFragment);
}
});
}
public void openFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container, fragment);
transaction.commit();
}

save changes of fragment when fragment is replaced

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.

Handling back button with fragments and activity?

I have an "activity A" that launches two fragments, with the home button being part of the activity A, and when the back button is pressed from the createFragment it should go back to the activity before activity A, which it does fine with the finish() method but when I have the second fragment, followersFragment which is added ontop of createFragment and hides createFragment (because I do not want the information being lost in the create), then I hit the back button and it switches back to the create fragment but then when I hit the back button from createFragment it does not go back to activity A anymore and does nothing... no error...
This is my code on the activity that holds the fragments(not activity A):
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar actions click
switch (item.getItemId()) {
// lets user travel back to where they came from
case android.R.id.home:
if(displayShown == 1) {
displayView(2, 0);
} else {
}
return true;
private void displayView(int i, int position) {
Log.d(Constants.DEBUG, "display view called " +position);
boolean createPost = true;
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 0:
//avoid recreating createPostFragment if already created because all data will be erased
if(createPostFragment == null){
createPost = false;
Log.d(Constants.DEBUG, "fragment create DOES NOT EXIST ");
createPostFragment = new CreatePostFragment();
}
fragment = createPostFragment;
break;
case 1:
followerFragment = new FollowerFragment();
fragment = followerFragment;
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
trans = fragmentManager.beginTransaction();
//if createpostfrag already created just show
if (createPost && position == 0) {
trans.remove(followerFragment);
trans.show(createPostFragment);
trans.commit();
//hide createpostfrag so we can reuse
} else {
if(position == 1) {
Bundle extraData = new Bundle();
extraData.putInt("follow", i);
fragment.setArguments(extraData);
trans.add(R.id.frame_container, fragment, null).commit();
trans.hide(createPostFragment);
}
if(position == 0) {
trans.add(R.id.frame_container, fragment, "keepAlive").commit();
}
}
} else {
// error in creating fragment
Log.d(Constants.DEBUG, "Error in creating fragment or no fragment needed");
}
}

onBackPressed closing app in fragments using NavigationDrawer

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();

How can I assure that a View is available when I call a Fragment method?

I'm using the native Android drawer for my menu, here in MainActivity :
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 0:
//Home
fragment = new EntryFragment();
break;
case 1:
//Journal
fragment = new JournalFragment();
break;
case 2:
// Medications
fragment = new RxFragment();
break;
case 3:
// Reminders
fragment = new ReminderFragment();
break;
case 4:
// Counselor Locator
fragment = new LocatorFragment();
break;
case 5:
// Library
fragment = new LibraryFragment();
break;
case 6:
// Settings
break;
case 7:
// About
break;
default:
break;
}
if (fragment != null) {
fm.beginTransaction()
.replace(R.id.container, fragment).addToBackStack(String.valueOf(position)).commit();
String fragmentTitles[] = getResources().getStringArray(R.array.menu_array);
if(mActionBar != null) {
mActionBar.setTitle(fragmentTitles[position]);
}
} else {
Log.e("MainActivity", "Error in creating fragment");
}
But I'm repurposing EntryFragment for another activity (EntryDetailActivity), so in EntryFragment I defined a couple of methods to modify the view based on which activity is hosting it:
// Runs on the home page, shows/hides appropriate views
public void prepareForHomeView() {
mTxtDate.setVisibility(View.GONE);
mBtnDiffDay.setVisibility(View.GONE);
mEdtNotes.setVisibility(View.GONE);
mBtnSave.setVisibility(View.GONE);
mBtnDelete.setVisibility(View.GONE);
}
// Runs on the detail page, shows/hides appropriate views
public void prepareForDetailView() {
mBtnLog.setVisibility(View.GONE);
}
In EntryDetailActivity, I can easily call prepareForDetailView() in onResumeFragments(), but I'm having an issue of where to call prepareForHome() in MainActivity, since I am swapping fragments in and out based on the menu. Any suggestions?
/** Update **/
I assigned the fragments a tag that is the position of the menu through addToBackstack(). I also added the following method to my MainActivity:
#Override
public void onAttachFragment(Fragment fragment) {
super.onAttachFragment(fragment);
FragmentManager fm = getSupportFragmentManager();
EntryFragment entryFrag = (EntryFragment)fm.findFragmentByTag("0");
if(entryFrag != null) {
Log.v("rx", "Home frag is not null");
} else {
Log.v("rx", "Home frag is null");
}
}
Activity (or FragmentActivity) has onAttachFragment(Fragment fragment) - you could do an instanceof on fragment to determine if it is the correct type of fragment (or use the id, tag, etc) and call the appropriate method.
Alternatively, you could have the Fragment check the getActivity() (in onCreateView / onViewCreated).

Categories

Resources