I made a NavigationView on MainActivity (AppCompatActivity).
I have multiple items on that NavigationView each one is a Fragment.
When I use back button I want to go to previous Fragment instead of put my app on background. Thus to change between Fragments I use:
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.layout, fragment).addToBackStack(null).commit();
When I press back button it goes to the previous Fragment, but the item checked of NavigationView remains. Which is the best way to update item checked of NavigationView on back button press?
i have used the following code into my project....and it worked....
I have inflated menu items into navigation drawer.....
you have to implement it in your every fragment...in onActivityCreated() method....because this method will certainly called after activity is created so we can use UI elements...
//code.....
NavigationView navigation = (NavigationView)getActivity().findViewById(R.id.navigation_view);
Menu drawer_menu = navigation.getMenu();
MenuItem menuItem;
menuItem = drawer_menu.findItem(R.id.Id_ofYourMenuItem);
if(!menuItem.isChecked())
{
menuItem.setChecked(true);
}
So, every time your fragment is called(via navigation drawer or via pressing back button) ,it will set menu item checked itself.
for future users here is another solution :
my drawer_menu.xml is like :
<item
android:id="#+id/Home"
android:title="Home"
android:icon="#drawable/ic_account_balance_black_24dp"
>
</item>
<item
android:id="#+id/courses"
android:title="courses"
android:icon="#drawable/ic_airplay_black_24dp"
>
</item>
<item
android:id="#+id/download"
android:title="Download"
android:icon="#drawable/ic_file_download_black_24dp"
>
</item>
0 :home
1 :courses
2 :download
Now in your Mainactivity : (im showing you only navigation view purpose code)
private private NavigationView navigationView;
protected void onCreate(Bundle savedInstanceState)
{
navigationView= (NavigationView) findViewById(R.id.navview);
}
Now create a manual method in mainactivity to call this method from fragment when fragment resume:
public void SetNavItemChecked(int id)
{
Menu m=navigationView.getMenu();
MenuItem mi=m.getItem(id);
mi.setChecked(true);
}
Now in All fragments in this exmple Homefragment,CoursesFragment,DownloadFragments are the fragments
in HomeFragment (YourFragment) :
override onresume method :
#Override
public void onResume() {
super.onResume();
((MainActivity)getActivity()).SetNavItemChecked(0);
// MainActivity is your activity
//SetNavItemChecked is method from activity and 0 is first item in menu for this example o is HomeFragment
}
and for all remaining fragment you can write in resume method like above
Alternatively, you can create a Stack, which stores the MenuItems of the NavigationDrawer when they are selected and then use the poll method in the onBackButtonPressed method to get and uncheck the MenuItem and the peek method to setChecked(true) the current MenuItem.
Probably not the most efficient way, but very easy to implement.
If you are using NavigationComponents, this is one of the ways
override fun onBackPressed() {
super.onBackPressed()
navController.currentBackStackEntry?.destination?.id?.let {
binding.navView.setCheckedItem(it)
}
}
Instead of using boiling code in every fragments, you can override this method in the mainActivity (fragment container).
Related
Generally switching from one activity to another activity hamburger icon is replaced with back arrow. I want to control the functionality of that arrow. I have seen many contents here but most of them were related to hardware's back button. How can I control that?
I am trying the functionality in case of fragments. Also I have Navigation drawer attached with the hamburger icon.
I tried this-
if(id == android.R.id.home){
getSupportFragmentManager().beginTransaction().replace(R.id.main_container, new AmbulanceMap()).commit();
getSupportActionBar().setTitle("Book A Ride");
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
}
but doesnt work as I hoped.
I want my back button to change the fragmentto previous fragment.
I had the same problem once. Just like you, things like checking if Android.R.id.home is clicked didn't work.
But I solved it using that:
Set navigation listener to toolbar:
toolbar.setToolbarNavigationClickListener(v -> onBackPressed());
If it should be within fragment:
Create an public method in activity.
In fragment's onAttach (or later) cast getActivity() to your activity and call method you was defined previously.
Example:
// YourActivity
public void setHomeListener(OnLickListener listener){
toolbar.setToolbarNavigationClickListener(listener);
}
//Fragment's onCreate
((YourActivity)getActivity()).setHomeListener(v -> onBackPressed());
//Fragment's onDestroy
((YourActivity)getActivity()).setHomeListener(null);
And, of course, set home us up enabled to show back arrow.
EDIT
if you don't use labmdas u should use:
(YourActivity)getActivity()).setHomeListener(new OnClickListener() {
#Override
public void onClick(View v) {
YourFragment.this.onBackPressed();
}
});
The back button of the ActionBar is a menuItem so you need to override onOptionsItemSelected like this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
//Your back button logic here
break;
}
return true;
}
Also donĀ“t forget to add getSupportActionBar().setDisplayHomeAsUpEnabled(true); after setting the Toolbar
In my case, I have activity with 2 containers for fragments.
One container show Fragment with list, second show detail information on the selected list item. Second container GONE by default.
In activity I have SearchView, which instance I get from fragment like that:
#Override
public void onPrepareOptionsMenu(Menu menu) {
MenuItem searchMenuItem = menu.findItem(R.id.action_search);
rxSearchView = (RxSearchView) searchMenuItem.getActionView();
rxSearchView.setSearchListener(taskListPresenter);
rxSearchView.setOnCloseListener(() -> {
taskListPresenter.clearSearch();
return false;
});
}
and, I use method setHasOptionsMenu(true); in OnCreateView();
Problem case:
1.User click on the searchView, and get filtered element:
2. User click on the element, calling next method:
`((MainActivity)getActivity()).showSecondaryFragment(TaskDetailFragment.newInstance();`
In MainActivity it's look like that:
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.ltRightContainer, baseFragment)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit();
After that, searchView automatically closed, like screen below.
How fix that moment? I don't want it automatically closing.
RxSearchView just wrapper with RxJava implementation, without ovverride methods.
Second fragment just call method setupMenu(R.menu.menu_my_task);
It makes searchView from first fragment close.
When I created a new project I used Navigation Drawer Activity
app screen
Now each menu item when I click on it will open a fragment by calling a method name replacement.
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_home) {
replaceFragment(0);
setTit = "Your State Info.";
setTitle(setTit);
} else if (id == R.id.nav_flashcards) {
replaceFragment(1);
setTit = "Flash Cards";
setTitle(setTit);
in fragment 1 I have a RadioGroup when the checked change will open the fragmet depends on the radio checked.
#Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
RadioButton radioButton = (RadioButton)getActivity().findViewById(i);
if(radioButton.getTag()==1)
((MainActivity) getActivity()).replaceFragment(0);
else if ((radioButton.getTag()==2))
((MainActivity) getActivity()).replaceFragment(2);
}
The App work fine , but the issue is how can I change the Navigation Item Selected and also change the title for the action bar.
it's possible to use this way
((MainActivity) getActivity()).onNavigationItemSelected(menuitem);
but from the fragment how can I access the the items in the menu>activity_main_drawer.xml and pass it through menuitem
This works for me..
NavigationView navigationView = (NavigationView) getActivity().findViewById(R.id.nav_view);
navigationView.getMenu().getItem(2).setChecked(true);
In your fragment you have to add setOptionsMenu(true)
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// TODO Add your menu entries here
super.onCreateOptionsMenu(menu, inflater);
}
question is not clear.
whole point of navigation drawer with fragments is to access navigation and its main toolbar all over the fragments with a single main activity.(the blue color one in your image, you should be able to change this anytime when you load a fragment)
But you need to make the frame/parent view of the fragments blow the tool bar view(that's why normally it comes with two XMLs, activtyMain.xml and contentMain.xml where content main is included below the tool bar in activityMain.XML) so you create fragments view match_parent to this contentMain.xml ,you can see toolbar is accessible to the each and every fragment you add in that view because its in the main activity where fragment/s add.
so you have a main activity and inside that you have fragment/s frame. Doesn't matter what fragment you load you can still have the access to main toolbar.
so once you check which item got clicked in navigationDrawer you load the fragment related to that right?. and there access the main toolbar of the mainActivity and do the changes that you need to display.That's it!
if (id == R.id.nav_whatever) {
// access toolBar or any view in main activity and do the changes
// call relevant fragment
}
But you cannot access that toolbar or mainActivity views inside your Fragment class that you try to attempt.
Edit :
Keep a Boolean in a Constant class or something similar,
then when you click on your button on second fragment change the value .
Now let's say Boolean is true
Then you click the navigation drawer again
// keep the id as it is and use the Boolean to check where you needs to go
if (id == R.id.nav_whatever) {
if(boolianName){
// boolianName is true go load second fragment
}else{
// load firstfragment
}
}
If you use Navegation drawer, you can use this code, put it on onCreate method:
NavigationView navigationView = (NavigationView) getActivity().findViewById(R.id.nav_view);
navigationView.getMenu().getItem(2).setChecked(true);
I implemented the new NavigationView (from the support library) and a couple of Fragments, I then overrided the onBackPressed function and added this:
getFragmentManager().popBackStack();
which returns me to the previous fragment.
So what I need is this: how I can change the navigationview's current selected item to the Fragment it is popping back to?
Finally i got it,
Firstly, i made the instance of the navigation global and public.
public NavigationView navigationview;
I then added in the onCreate and onResume of my fragment:
NavigationView navigationView = ((MainActivity) getActivity()).navigationview;
navigationView.getMenu().getItem(index).setChecked(true);
and the onResume:
navigationView.getMenu().getItem(index).setChecked(true);
This solved my problem, Hope this helps someone.
I know this is a little late but I found a solution that is maybe a little faster to code for Activities that have a large amount of fragments.
(In your activity)
Implement FragmentManager.OnBackStackChangedListener
In onCreate() add fragmentManager.addOnBackStackChangedListener(this);
Add Method from interface...
#Override
public void onBackStackChanged() {
MainActivityFragment f = (MainActivityFragment) fragmentManager.findFragmentById(R.id.fragment_container);
//Log.v(TAG, "OnBackStackChanged to fragment with index: " + f.getMenuIndex());
navigationView.getMenu().getItem(f.getMenuIndex()).setChecked(true);
}
(Create an interface in a separate file, name it MainActivityFragment) or whatever your activity is named.
public interface MainActivityFragment {
int getMenuIndex();
}
(All fragments that are used in that Activity)
Implement MainActivityFragment
Add Method from interface...
#Override
public int getMenuIndex() {
return 2;
}
It may seem like some extra work but in the long run it makes it pretty easy as all you have to do for new Fragments is implement the Activity's Interface and return the index of it's menu item.
I have a navigation drawer based on the example in the Android documentation.
When you open the navigation drawer it shows a MainMenuFragment inside the drawer. When you select a menu item, it replaces the fragment inside the drawer with a SubMenuFragment. This works fine expect for the back button.
Pressing the back button always closes the drawer but I want to use the back button to show the MainMenuFragment in the drawer when the SubMenuFragment is showing. How can you handle the back button inside the navigation drawer to replace the fragment showing inside the drawer.
Replacing the fragment inside the drawer is not the issue here. I can not figure out how to stop the back button from closing the drawer and have it show the MainMenuFragment instead.
My main activity XML (shortened):
<android.support.v4.widget.DrawerLayout ....>
<FrameLayout android:id="#+id/container" .../>
<FrameLayout android:id="#+id/drawer" android:layout_gravity="start" .../>
</android.support.v4.widget.DrawerLayout>
and the relevant parts of my class:
public class MainActivity extends Activity {
...
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getFragmentManager().beginTransaction()
.replace(R.id.drawer, new MainMenuFragment()).commit();
// setup DrawerLayout and ActionBarDrawerToggle
...
}
private void showSubMenu() {
getFragmentManager().beginTransaction()
.replace(R.id.drawer, new SubMenuFragment()).commit();
}
}
What I've used before in different cases is to add fragments to Fragment BackStack.
So when changing fragment added it to the back stack first.
getFragmentManager().beginTransaction()
.replace(R.id.drawer, new MainMenuFragment()).addToBackStack(null).commit();
And when handling back do the following.
int count = getSupportFragmentManager().getBackStackEntryCount();
if(count > 1)
getSupportFragmentManager().popBackStack();
Try this and see if it works.
Also check this out : http://developer.android.com/training/implementing-navigation/temporal.html#back-fragments