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}
'
Related
Hi guys I have a navigation drawer with several menu items. I am currently implementing a logout feature and I added a logout menu item in the drawer. I currently already have a drawer configuration which opens the previously configured menu items and their corresponding fragments using this configuration.
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_my_products, R.id.nav_profile, R.id.nav_offers,
R.id.nav_my_cart, R.id.nav_my_orders, R.id.nav_log_out)
.setOpenableLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this,
R.id.nav_host_fragment_content_main);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
I already have the nav controller doing the work for me on opening up the fragments
on drawer menu click but the problem for me is that if I click "Log out" in the menu this
default to looking for the Log Out fragment to open the corresponding layout. SO I searched for some ways to override this behavior and below seems to be working fine but the problem is it would override selecting each menu items and you would need a very long switch case to implement
the override to each which is bit of a hustle not to mention the unnecessary code required
with the switch case having to do it for all the menu items when the controller above can
already do the work of opening the fragments.
Is there a way to do the override to only 1 menu item selected that does the logout only and preserve the previous controller code that automatically opens up fragment.
navigationView.setNavigationItemSelectedListener(new
NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.nav_home:
//also if I use this switch case instead how do I open a drawer not an activity that opens on menu click
return true;
} switch (item.getItemId()){
case R.id.nav_log_out:
logOut();
return true;
} switch (item.getItemId()){ so on for eahc menu item....
public void logOut() {
mFirebaseAuth.getInstance().signOut();
startActivity(new Intent(this, LoginActivity.class));
finish();
}
navView.menu.findItem(R.id.nav_delete_account).setOnMenuItemClickListener {
Toast.makeText(this, "Delete account", Toast.LENGTH_SHORT).show()
true
}
This worked for me you can override specific menu item behavior by accessing the click listener.
Just override the onOptionsItemSelected to handle the click on the item menu:
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId) {
R.id.action_logout -> //....) return true
}
return super.onOptionsItemSelected(item)
}
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 .
Hello I'm wondering how can I change a Menu ID from a NavigationView, in this case it is triggered when the user clicks on a RadioButton. I have that part already but I just need to know how to change the Menu, so in the menu it will display different options when RadioButton is clicked.
private var radioAdm:RadioButton? = null
private var radioAtle:RadioButton? = null
private var atletanav:BottomNavigationView? = null
private var menuopt = "#menu/admin_menu"
override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) {
// Here is where I need to put that code
}
I've tried this already but no success:
atleta_navbar.set(menu){menu=menuopt}
atleta_navbar.setTag(menuopt)
So in the NavigationView it will go from this:
To this:
In java you could try this to re-inflate NavigationView at runtime.
navigationView.getMenu().clear(); //clear old inflated items.
navigationView.inflateMenu(R.menu.new_navigation_drawer_items);
I don't know kotlin,but the thought is same.
this code work for me as explain by navylover answer
1- make sure you have different menu in my case i have R.menu.navigation and R.menu.navigation_normal
private fun User() {
// clear previous menu
binding.navi.menu.clear()
// add new menu item
binding.navi.inflateMenu(R.menu.navigation)
//add listener for new bottom naviagtion
binding.navi.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
// when using Navigation component
//set up bottom navigation bar with navigation graph
NavigationUI.setupWithNavController(binding.navi, navController)
}
If I add a custom item to my NavigationView menu, like so:
Menu menu = navigationView.getMenu();
MenuItem item = menu.add("Item 1");
How can I set data to the item (like an object) so that, when it's clicked/selected, I can pass that data to the activity it opens?
You can't set/add data to menu items. By looking at the documentation of add() method, it can be seen that you can set:
groupId - int: The group identifier that this item should be part of. This can be used to define groups of items for batch state changes. Normally use NONE if an item should not be in a group.
itemId - int: Unique item ID. Use NONE if you do not need a unique ID.
order - int: The order for the item. Use NONE if you do not care about the order. See getOrder().
title - CharSequence: The text to display for the item.
Therefore:
You need to set itemId and handle specific tasks inside onNavigationItemSelected()
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.id_of_menu_item_1) {
// handle intents and passing data
} else if (id == R.id.id_of_menu_item_2) {
// handle intents and passing data
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
This doesn't make sense for me. MenuItem class only holds attributes relative to menu item. You cannot put other objects inside MenuItem instance. Take a look about MenuItem class:
MenuItem class
You can use repository pattern to get needed data on new activity or load object on current activity and pass to new activity using intent, just create a Bundle and put your serializable or parcelable object on it. You can make this when you handle onNavigationItemSelected(MenuItem item)
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);