Add MenuItem to NavigationView programmatically - item not checked - android

I've added items to NavigationView programmatically:
**HERE ADD ITEMS**
Menu rightMenu = mRightDrawerView.getMenu();
for (DataParking dataParking : dataParkingList) {
MenuItem menuItem = rightMenu.add(dataParking.getTimeParking());
}
**HERE ADD CLICK LISTENER**
mRightDrawerView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
// Select menu
menuItem.setChecked(true);
// Closing left_drawer on item click
mDrawerLayout.closeDrawer(mRightDrawerView);
return false;
}
});
Items in navigation drawer are correctly clickable, but the selection is not persistent. If I add the same items via XML all works well.

When you are adding an item programmatically, the item's checkable flag is not set. You should just add this line:
menuItem.setCheckable(true);
after adding an item to menu.

As #Oncky answered, you can just setCheckable on your menuItem like this:
Menu rightMenu = mRightDrawerView.getMenu();
for (DataParking dataParking : dataParkingList) {
MenuItem menuItem = rightMenu.add(dataParking.getTimeParking()).setCheckable(true);
}

Related

Android: Handling a switch in drawer menu

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 .

Want to add Bottom and Side navigation in one activity but How?

I want to add Bottom navigation and Side navigation drawer in one activity like LinkedIn. I tried to add bottom navigation to the navigation drawer activity but unsuccessful as navigationListener of both can have same names and in one listener how can i separate bottom navigation items and side navigation items.
it doesn't matter if the two listener have the same name, you can add add listener to each one by their full package name.for example you can add listener to Navigation view like this:
navigationView.setNavigationItemSelectedListener(new android.support.design.widget.NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
///your code here
return false;
}
})
and add listener to Bottom navigation view like this :
bottomNavigationView.setOnNavigationItemSelectedListener(new android.support.design.widget.BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
return false;
}
});

How to make "my account or settings " clickable?

Here is the screen shot of my sidebar navigation bar.
I want to make the items in the sidebar navigation Menu clickable so that I can move to another Activity how can I do this?
You have to treat these as Menu items.
When you set up the navigation bar from the layout XML you attach a menu.xml to it which contains menu items that are then displayed in the navigation bar.
Method 1:
Now from the activity where you have your navigation bar variable you need to get the menu from the navigation view object.
Menu menu = navigation_view.getMenu();
Then you can get individual menuItems from this menu object.
MenuItem myAccount = menu.getItem(0);
MenuItem settingsItem = menu.getItem(1);
MenuItem logoutItem = menu.getItem(2);
Now you can use each of this menuItem objects to set menu click listeners on them and then start the next activity from there. e.g.
myAccount.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
Intent intent = new Intent(context, ToAcitivity.class);
startActivity(intent);
return true;
}
});
Similarly, you can use rest of the objects and make them clickable.
Method 2:
You can also use
navigation_view.setNavigationItemSelectedListener(new
NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()){
case 1:
break;
case 2:
}
return false;
}
});
Second one being more simpler to use

Remove item at given position in Navigation Drawer

My users can delete items in my Navigation Drawer, they select which one they wish to delete and it should be removed from the menu.
Here is how I try to do it so far:
// Should remove item at position 'which'
private void removeTab(int which) {
NavigationView navView = (NavigationView) findViewById(R.id.nav_view);
Menu menu = navView.getMenu();
menu.removeItem(which + 1);
}
But it does not remove the item.
I'm not sure this is how removeItem should work, is there a way to remove an item in a Navigation Drawer using its position in the menu?
EDIT:
I get the idea of hiding the item, but that is problematic as I will have to keep track of the number of items hidden in order to hide the next one. (If Item1 and Item2 are hidden then Item3 is still at position 3 and not 1 when displayed).
NavigationView navigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
hideItem();
}
private void hideItem()
{
navigationView = (NavigationView) findViewById(R.id.nav_view);
Menu nav_Menu = navigationView.getMenu();
nav_Menu.findItem(R.id.nav_settings).setVisible(false);
}
You can hold the data in an arraylist. When you swipe over an item, you can remove the item from the array list arraylist.remove(index) and call adapter.notifyDataSetChanged().
Important:
If you implement this solution, you have to pass the arraylist to the adapter and work on the same list object.
you need to provide the id of MenuItem to be removed inside removeItem. not position.
like this:
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
navigationView.getMenu().removeItem(item.getItemId());
}
});

Hide/show MenuItem on click actionbar android

I've been trying to get my actionbar buttons to show on click but can't get it to work. I got 2 buttons and if i click on one i want the other to show and the other to get invinsible.
Here is my code:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
MenuItem brandsMenu = (MenuItem)findViewById(R.id.action_brands);
MenuItem categoryMenu = (MenuItem)findViewById(R.id.action_category);
switch (item.getItemId()) {
case R.id.action_category:
brandsMenu.setVisible(true);
return true;
case R.id.action_brands:
categoryMenu.setVisible(true);
}
This only shows errors. Any Suggestions?
You need to call InvalidateOptionsMenu when you want to make changes to your menu.
You then use the onCreateOptionsMenu override to apply those changes.
Define MenuItems named brandsMenu and categoryMenu and initialize them onPrepareOptionsMenu
categoryMenu = menu.findItem(R.id.action_category);
brandsMenu = menu.findItem(R.id.action_brands);
You should be able to change visibility such as categoryMenu.setVisible(true);
You can't set visibility on menuitems.
You should invalidate the options menu and add only the menuItems you want to be visible

Categories

Resources