I have a simple BottomNavigationView with two menu items (Home Fragment, Settings Fragment) in an activity.
I have implemented onNavigationItemSelectedListener and onNavigationItemSelected.
Also bottomNavigationView.setOnNavigationItemSelectedListener(this);
App page lands on the Home Fragment.
onNavigationItemSelected is being called when I switch between menu items but When I first launch the app and tap on the same menu Item i.e. Home Fragment, onNavigationItemSelected is not being called.
I would need to show a toast whenever the user clicks on the home page when user is already in home page but onNavigationItemSelected event is not triggered.
As Mike M mentioned,
setOnNavigationItemReselectedListener did the trick.
First of all we do this in the MainActivity
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
int v = item.getItemId();
if(v==R.id.home)
{
getSupportActionBar().setTitle("Home");
Fragment fragment = new HomeFragment();
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().replace(R.id.frame_layout, fragment).commit();
}
else if (v==R.id.dash_board)
{
getSupportActionBar().setTitle("Dashboard");
Fragment fragment = new DashboardFragment();
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().replace(R.id.frame_layout, fragment).commit();
}
return true;
}
};
This is a example here
If you want to know in detail then click here
There seem to be many question related to this topic. When i read most of them i had one problem. Usually people try to make a fragment and then spawn a dialog fragment from there. So the dialog fragment is inside the fragment.
In my case i have created a button that opens a dialogfragment on the toolbar. Then i open my main fragment from the navigation bar. So the dialogfragment and my main fragment are getting called through the same main activity, just in different places. I cannot call the dialog fragment from inside the fragment since its getting called when the menu options are selected.
I tried to create a an interface with and a listener when im trying to
newFragment.setTargetFragment(somethinghere, 1); i have no idea on what i should be putting on the somethinghere field. getactivity,mealsworkoutfragment and .this are wrong)
I also tried to make my fragment extends Dialogfragment instead but this spawns my fragment everytime i press the button, which seems like an awful way to do this.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.date_picker) {
DialogFragment newFragment = new DatePickerFragment();
newFragment.show(getSupportFragmentManager(), "datePicker");
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.mealworkoutTab) {
iconShow = true;
invalidateOptionsMenu();
FragmentTransaction mealsworkoutsFrag = getSupportFragmentManager().beginTransaction();
mealsworkoutsFrag.replace(R.id.flMain,new MealsWorkoutsFragment());
mealsworkoutsFrag.commit();
} else if (id == R.id.userinfoTab) {
iconShow = false;
invalidateOptionsMenu();
FragmentTransaction userInfoFrag = getSupportFragmentManager().beginTransaction();
userInfoFrag.replace(R.id.flMain,new UserInfoFragment());
userInfoFrag.commit();
} else if (id == R.id.logoutTab) {
auth.signOut();
}
DrawerLayout drawer = findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
Im guessing that a simple solution must exist since this looks a bit trivial (get sth from a dialogfragment to a fragment)
A suggestion would be to use library like EventBus in such cases to convey and listen listen to "events" and pass data. So in your case, when the user selects the date, an 'event' with the selected date payload is posted. This event is then caught inside your Fragment (because you make your Fragment subscribe to this specific event) and then you can handle the payload (selected date) as you like.
If the above sounds too tough to follow or picture, please visit the link above. It has example codes. This library is extremely simple to implement and quite helpful in such scenarios.
Hi I need to handle back button on fragment. I using this navigation on my mobile apps. The question is how to handle back button when I open new fragment page?
I try using below code on new fragment.
actionBar.setDisplayShowHomeEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
But when click the back button , the navigation will be open. Any solution ?
Thanks
As you know whenever user presses Back button you need to go to the previously loaded fragment and to do that try this (note fragment must be added with transaction.addToBackStack(null);)
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
int backStackCount = fragmentManager.getBackStackEntryCount();//check currently how many frags loaded
if (backStackCount > 0) {
fragmentManager.popBackStack(); //go back to previously loaded fragment
}
}
return super.onOptionsItemSelected(item);
}
I am using SLiding menu at My App and according to menu item , I am changing always the fragment at activity which have binded already to menu. But There is performance issue. it is freezing when i am attaching the fragments. but after the wiew created. the performance is normal. I am replacing the fragments after call the toggle function at menu.
is there anyone to have any opinion about it ?
just call it as:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Pass the event to ActionBarDrawerToggle, if it returns
// true, then it has handled the app icon touch event
if (item.getItemId() == R.id.evnetCalender) {
if (!isToggle) {
item.setIcon(R.drawable.ic_view_list_white_24dp);
setFragment(caldroidCalendarFragment);
isToggle = true;
} else {
item.setIcon(R.drawable.ic_event_white_24dp);
setFragment(scheduleEventFragment);
isToggle = false;
}
}
and set your fragment when you toggle it
private void setFragment(Fragment fragment1) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content, fragment1);
fragmentTransaction.commit();
}
this content identifier is your frame layout id in which your fragment take place
I've got an app with nav drawer, which is switching fragments. From inside one of those fragments, I am calling a new activity. When I click back in this activity (in toolbar), I want to go back to previous selected fragment but instead it puts me back to first fragment. I am adding my fragment to back stack so this should not be a problem.
Here is what I have already tried:
I have overriden the onBackPressed method in my 2nd activity like this:
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() == 0) {
this.finish();
} else {
getFragmentManager().popBackStack();
}
}
It is not working. I also saved index of current fragment inside onsaveinstancestate method and retrieve it but same result. I also tried with always putting current fragment inside variable and try to reshow it but still, it does not work. Anything else I could try?
Fun fact: if I press back inside bottom panel, it does actually goes back to previous fragment.
EDIT: Here is my code for doing this:
private void replaceFragment(Fragment fragment)
{
if (fragment != null)
{
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction()
.replace(R.id.main_content, fragment)
.addToBackStack(null)
.commit();
}
}
I add first fragment only, if savedInstanceState is null, like so:
if (savedInstanceState == null) {
// first time
mTitle = getResources().getString(R.string.home);
replaceFragment(HomeFragment.newInstance());
}
And yes, all this is done inside onCreate() method.
I had the same problem and got fixed. The only thing you need to do is to
override the method "onOptionsItemSelected" in the activity:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
android.R.id.home is your first fragment in the menu.
What I tend to do is this
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() == 0) {
this.finish();
} else {
super.onBackPressed(); //replaced
}
}
This way it handles the fragment stuff on its own within, but when there's no fragments left to go back to, then it finishes the activity.
EDIT: UP navigation can recreate your previous activity even if it already exists. To prevent that from happening, redefine the Up navigation's event in onOptionsItemSelected like so:
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent parentIntent = NavUtils.getParentActivityIntent(this);
if(parentIntent == null) {
finish();
return true;
} else {
parentIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(parentIntent);
finish();
return true;
}
}
return super.onOptionsItemSelected(item);
}
When you call an activity from other activity's fragment, then the previous activity's instance state that is the calling activity which was having fragment's instance state will be saved in stack...so all u need to do is finish the called activity and u will have the fragment from which you called your second activity.
#Override
public void onBackPressed() {
finish();
}
Try
getFragmentManager().popBackStackImmediate();
It worked for me.
Sorry, I don't have enough reputation to leave a comment. So I have to guess. I once had the same issue.
Sounds like a problem related to the activity lifecycle (http://developer.android.com/reference/android/app/Activity.html#ProcessLifecycle). Be sure to add your first fragment only once, because your activity's fragment manager is capable of the lifecycle.
Thus, the statement that adds the first fragment to your fragment manager should be surrounded by if (savedInstanceState == null) { ... }.
I see, that people are still trying to help me. This answer helped me fix my problem: Android - Navigation Up from Activity to Fragment
Override onOptionsItemSelected method in activity as follows,
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
finish();
}
return super.onOptionsItemSelected(item);
}
When you call new Activity from Fragment you should write :
Intent intent = new Intent(getFragment().getContext(),NewActivity.class);
getFragment().getContext().startActivity(intent);
FragmentManager fm = CurrentFragment.getActivity().getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.addToBackStack(CurrentFragment.class.getName()).commit();
fm.executePendingTransactions();
It Works for me.
getSupportFragmentManager().beginTransaction()
.setReorderingAllowed(true)
.addToBackStack("home") // should not be null
.replace(binding.fragmentContainer.getId(), new HomeFragment())
.commit();
Pass name in addToBackStack(String name) method. This function add fragment into backstack if passed name is not null. App automatically start managing backstack of fragment
Remove your override onBackPressed() method. No use of it now