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);
Related
I have only one user setting in my app, and I want to put it into the navigation drawer with a switch added to the given menu item.
Here is the relevant menu code:
<item
android:id="#+id/nav_dark"
android:checkable="true"
android:icon="#drawable/round_brightness_4_24"
android:title="#string/menu_dark"
app:actionViewClass="android.widget.Switch" />
The switch does appear on the right side of the menu item.
My listener:
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
if (item.getItemId() == R.id.nav_dark) {
// code to apply dark or light theme
// works as expected
}
else {
// code to handle regular menu items
// it works too
}
return true;
}
My problems:
When I tap on R.id.nav_dark the item gets selected. I would like the colored overlay to stay on (or jump back to) the previous menu item, whose fragment is actually shown behind the drawer.
The switch does not react accordingly, even if I use item.setChecked(true) manually. I would like the switch to be turned on when the dark theme is enabled and turned off when it's disabled.
Tapping on the switch itself does not pass the event to the menu item. I would like them to work in sync.
I have seen checkboxes and swiches working like this in other applications, although, most of them were in the app bar's overflow menu. (I have tried mine with a checkbox too, but no difference.)
I solved this problem using this thread: Switch in Navigation drawer item with Design Support Library on Android
In this example the dedicated menu item switches between a light and dark theme, but you can use it to toggle any settings, of course.
Problems to solve
Implement our own onNavigationItemSelected listener, because the default solution created by Android Studio prevents the use of a dedicated menu item.
Implement the fragment transaction and toolbar handling logic.
Implement the onCheckedChange listener of the switch.
What we do is capture clicks on the menu items. If it's a regular item, we change the fragment behind the drawer. If it's the dedicated item with the switch, we manually toggle the switch, which calls its listener.
The actual code (changing the theme in this case) is handled by the listener of the switch. If you click on the switch itself, the listener will be called directly.
Relevant code from activity_main_drawer.xml menu file
<item
android:id="#+id/nav_dark"
android:checkable="true"
android:icon="#drawable/round_brightness_4_24"
android:title="#string/menu_dark"
app:actionViewClass="android.widget.Switch" /> <!-- you can also use a CheckBox -->
Relevant code from MainActivity.java
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, Switch.OnCheckedChangeListener {
private Toolbar toolbar;
private DrawerLayout drawerLayout;
private ActionBarDrawerToggle toggle;
private NavigationView navigationView;
private Switch switchDark;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = findViewById(R.id.toolbar);
toolbar.setTitle(getResources().getString(R.string.toolbar_title));
setSupportActionBar(toolbar);
// We have to handle the fragment changes manually,
// because what we do conflicts with the default solution created by Android Studio
drawerLayout = findViewById(R.id.drawer_layout);
toggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawerLayout.addDrawerListener(toggle);
toggle.setDrawerIndicatorEnabled(true);
toggle.syncState();
navigationView = findViewById(R.id.nav_view);
// Check the menu item connected to the default fragment manually
navigationView.getMenu().findItem(R.id.nav_item1).setChecked(true);
navigationView.setNavigationItemSelectedListener(this); // See below!
switchDark = (Switch)navigationView.getMenu().findItem(R.id.nav_dark).getActionView();
// Set the default state of the switch connected to the menu item
switchDark.setChecked(AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES);
switchDark.setOnCheckedChangeListener(this); // See below!
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
// Handle the menu item with the switch
if (item.getItemId() == R.id.nav_dark) {
((Switch)item.getActionView()).toggle(); // Call the onCheckedChangeListener of the switch and let it do the work
return false; // Prevent the menu item to get selected (No overlay indicator will appear)
}
// Handle the other menu items
// We have to do this, because we deleted the default solution created by Android Studio
Fragment newFragment = null;
if (item.getItemId() == R.id.nav_item1) {
newFragment = new CustomFragment();
toolbar.setTitle(getResources().getString(R.string.custom_fragment_title));
}
else if (item.getItemId() == R.id.nav_item2) {
newFragment = new OtherFragment();
toolbar.setTitle(getResources().getString(R.string.other_fragment_title));
}
// Start the fragment transition manually
if (newFragment != null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.nav_host_fragment, newFragment);
transaction.addToBackStack(null);
transaction.commit();
drawerLayout.close();
}
return true; // The selected item will have the overlay indicator
}
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(buttonView.getContext());
SharedPreferences.Editor editor = sharedPreferences.edit();
int themeID;
if (isChecked) {
themeID = AppCompatDelegate.MODE_NIGHT_YES;
}
else {
themeID = AppCompatDelegate.MODE_NIGHT_NO;
}
AppCompatDelegate.setDefaultNightMode(themeID); // Change the theme at runtime
editor.putInt("themeID", themeID); // Save it to be remembered at next launch
editor.apply();
}
}
try this one.
<item
app:actionViewClass="androidx.appcompat.widget.SwitchCompat"
android:icon="#drawable/message"
android:title="All inboxes"
android:id="#+id/inbox"
/>
this above is the menu item we need
in order to get click events follow below steps mentioned
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
if (item.getItemId()==R.id.inbox){
((SwitchCompat) item.getActionView()).setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked){
Toast.makeText(buttonView.getContext(), "Checked", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(buttonView.getContext(), "unChecked", Toast.LENGTH_SHORT).show();
}
}
});
}
Toast.makeText(MainActivity.this, ""+item.getTitle(), Toast.LENGTH_SHORT).show();
drawerLayout.closeDrawer(GravityCompat.START);
return true;
}
});
we already given our action class in menu item from xml .
we just need to verify which item it was and when it happens we can get the actionviewclass that we had assigned
and an onclicklistener on it .. this one worked for me .
mDrawerLayout = findViewById(R.id.drawer_layout)
val navigationView: NavigationView = findViewById(R.id.nav_view)
navigationView.setNavigationItemSelectedListener { menuItem ->
// set item as selected to persist highlight
menuItem.isChecked = true
// close drawer when item is tapped
mDrawerLayout.closeDrawers()
// Add code here to update the UI based on the item selected
// For example, swap UI fragments here
true
}
I have a navigation drawer in my app, and I can access it and click on the items listed there. However, what is the code I need to add above so that when an item is clicked, it opens up a new activity? I have 10 activities and don't know anything about fragments yet so have to set it so it opens a new activity for now.
#override
public boolean onNavigationItemSelected(MenuItem item)
{int id = item.getItemId();
// then use if and else to know which is selected}
'
In my app, I need to change the menu of the navigationView, when I click on the header
First state
Second state
I wanted to get the currently active menu of my navigationView to toggle between the two menus. This is what I have written so far:
public void toggleMenu(){
navigationView.getMenu().clear();
navigationView.inflateMenu(R.menu.menu_trips);
}
Instead of inflating the same menu all the time, I need to create an if to inflate the menu which is not currently active, something like this:
if (navigationView == R.menu.menu_trips){
navigationView.inflateMenu(R.menu.activity_main_drawer);
} else if (navigationView == R.menu.activity_main_drawer){
navigationView.inflateMenu(R.menu.menu_trips);
}
I do not want to add an MenuItem, I just want to replace the menu. Clearing it and then inflating is the best option I found.
If you have a better solution, please tell me :)
You can not get menu id from Menu class.
I suggest you to keep a global variable that keeps your current menu id. Or you can compare first items to understand which menu is currently active.
Solved it:
String activeMenu;
protected void onCreate(){
activeMenu = "main";
}
public void toggleMenu(){
navigationView.getMenu().clear();
if (activeMenu.equals("main")){
navigationView.inflateMenu(R.menu.menu_trips);
activeMenu = "trips";
} else if (activeMenu.equals("trips")){
navigationView.inflateMenu(R.menu.activity_main_drawer);
activeMenu = "main";
}
}
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).
Can anyone give a quick example of how to change the contents of an Activity action bar based on something that takes place in a fragment? My intent:
Normal menu items -> Something in the fragment is moved -> menu items change to save / discard buttons.
My first impulse is to setup Broadcast Receivers in both the activity and the fragment to cross talk, but I am not sure if this is correct.
Fragments can change menu in actionbar. For that you have to add necessary flag in fragment's oncreate() using method setHasOptionsMenu(true);
When your fragment is loaded you will get call at onCreateOptionsMenu(Menu menu, MenuInflater inflater) just like in an activity. Then do necessary changes to your menu.
Save you menu as global in fragment, and whenever you want to make a change, apply on it.
The following works for me. I have a custom class that implements ListView.MultiChoiceModeListener inside a Fragment:
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
// Choose the correct Action Bar menu to display
int menu = myCondition == true ? R.menu.my_default_menu : R.menu.my_menu_2;
// Configure to use the desired menu
mode.getMenu().clear();
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(menu);
}
Given how you detect 'something in the fragment has moved', extending ListView.MultiChoiceModeListener may not work for you, but hopefully this illustrates how to change the menu. The key is to get access to a ActionMode instance.
I think you want to use a contextual action mode. On the drag event, you will start a new ActionMode which can replace the contents of the action bar with menu items specific to what you want to allow the user to do. Once the user chooses an action, you finish the action mode and the action bar returns to its previous state.
Not sure if an ActionBar instance would help with the menu you but would surely be useful.. Here's a way to get about it
Try this to get the ActionBar from the FragmentActivity using the onAttach(Activity activity) method in the Fragment.
First of all make a global object of your FragmentActivity in the Fragment like this
public class YourFragment extends Fragment {
private YourFragmentActivity context;
}
Override this in the YourFragment class
#Override
public void onAttach(Activity activity){
context = (YourFragmentActivity)activity;
super.onAttach(activity);
}
Then in the OnCreate method in the YourFragment do this
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState){
...
android.support.v7.ActionBar actionBar = context.getSupportActionBar();
...
}