Android BottomNavigationView menuItem set checked doesn't work properly - android

In my bottomNavigationView I can change programmaticaly my menu items everything it seems to work, but in fact my layout is diferent from if is checked or if I click directly on tab. Please look at differences bellow:
1) for menuItem.setChecked(true):
2) when a user clicks directly on icon it will perform the animation and show it on the correct
Well what I real want is to select the menuItem as if the user clicked. Isn't supposed to work by doing menuItem.setChecked(true)?
Please take into consideration the following definition layout for menu items:
<item android:id="#+id/menu_home"
android:title="#string/menu_home"
android:icon="#drawable/ic_home_black_24dp"
app:showAsAction="ifRoom" />
<item android:id="#+id/menu_hall_of_fame"
android:title="#string/menu_hall_of_fame"
android:icon="#drawable/ic_stars_black_24dp"
app:showAsAction="ifRoom" />
<item android:id="#+id/menu_info"
android:title="#string/menu_info"
android:icon="#drawable/ic_info_black_24dp"
app:showAsAction="ifRoom" />
<item android:id="#+id/menu_settings"
android:title="#string/menu_settings"
android:icon="#drawable/ic_settings_black_24dp"
app:showAsAction="ifRoom" />
and how I'm checking the correct menuItem:
MenuItem item = mBottomNav.getMenu().findItem(R.id.menu_about);
// update selected item
mSelectedItem = item.getItemId();
// uncheck the other items and select the one.
for (int i = 0; i< mBottomNav.getMenu().size(); i++) {
MenuItem menuItem = mBottomNav.getMenu().getItem(i);
menuItem.setChecked(menuItem.getItemId() == mSelectedItem);
}
There is another method to perform a selection of a menuItem? What am I missing here?

See This i post here all code
public class MainActivity extends AppCompatActivity {
private static final String SELECTED_ITEM = "arg_selected_item";
private BottomNavigationView mBottomNav;
private int mSelectedItem;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBottomNav = (BottomNavigationView) findViewById(R.id.navigation);
mBottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
selectFragment(item);
return true;
}
});
MenuItem selectedItem;
if (savedInstanceState != null) {
mSelectedItem = savedInstanceState.getInt(SELECTED_ITEM, 0);
selectedItem = mBottomNav.getMenu().findItem(mSelectedItem);
} else {
selectedItem = mBottomNav.getMenu().getItem(0);
}
selectFragment(selectedItem);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(SELECTED_ITEM, mSelectedItem);
super.onSaveInstanceState(outState);
}
#Override
public void onBackPressed() {
MenuItem homeItem = mBottomNav.getMenu().getItem(0);
if (mSelectedItem != homeItem.getItemId()) {
// select home item
selectFragment(homeItem);
} else {
super.onBackPressed();
}
}
private void selectFragment(MenuItem item) {
Fragment frag = null;
// init corresponding fragment
switch (item.getItemId()) {
case R.id.menu_home:
frag = MenuFragment.newInstance(getString(R.string.text_home),
getColorFromRes(R.color.color_home));
break;
case R.id.menu_notifications:
frag = MenuFragment.newInstance(getString(R.string.text_notifications),
getColorFromRes(R.color.color_notifications));
break;
case R.id.menu_search:
frag = MenuFragment.newInstance(getString(R.string.text_search),
getColorFromRes(R.color.color_search));
break;
}
// update selected item
mSelectedItem = item.getItemId();
// uncheck the other items.
Menu menu = mBottomNav.getMenu();
for (int i = 0, size = menu.size(); i < size; i++) {
MenuItem menuItem = menu.getItem(i);
((MenuItemImpl) menuItem).setExclusiveCheckable(false);
menuItem.setChecked(menuItem.getItemId() == R.id.menu_home);
((MenuItemImpl) menuItem).setExclusiveCheckable(true);
}
updateToolbarText(item.getTitle());
if (frag != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, frag, frag.getTag());
ft.commit();
}
}
private void updateToolbarText(CharSequence text) {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(text);
}
}
private int getColorFromRes(#ColorRes int resId) {
return ContextCompat.getColor(this, resId);
}
}
you can use this code
Menu menu = mBottomNav.getMenu();
for (int i = 0, size = menu.size(); i < size; i++) {
MenuItem menuItem = menu.getItem(i);
((MenuItemImpl) menuItem).setExclusiveCheckable(false);
menuItem.setChecked(menuItem.getItemId() == R.id.menu_home);
((MenuItemImpl) menuItem).setExclusiveCheckable(true);
}

Related

BottomNavigationView keeps checking last menuitem (when it starts up) but displays first menuitem

When the app first starts up, it checks the last menuitem as if it was clicked. It displays the first menuitem content. In Android Studio, no errors, warnings, or logs are displayed that hint at anything going wrong.
Once the app is running, if I click on any of the other menuitems, it works normal. I can click on each of the menuitems and the correct fragment populates accordingly.
Here is MainActivity.java:
public class MainActivity extends AppCompatActivity {
private static final String SELECTED_ITEM = "arg_selected_item";
private BottomNavigationView mBottomNav;
private int mSelectedItem;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBottomNav = (BottomNavigationView) findViewById(R.id.navigation);
mBottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
selectFragment(item);
return true;
}
});
MenuItem selectedItem;
if (savedInstanceState != null) {
mSelectedItem = savedInstanceState.getInt(SELECTED_ITEM, 0);
selectedItem = mBottomNav.getMenu().findItem(mSelectedItem);
} else {
selectedItem = mBottomNav.getMenu().getItem(0);
}
selectFragment(selectedItem);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(SELECTED_ITEM, mSelectedItem);
super.onSaveInstanceState(outState);
}
#Override
/* This is never called on start up */
public void onBackPressed() {
MenuItem homeItem = mBottomNav.getMenu().getItem(0);
if (mSelectedItem != homeItem.getItemId()) {
// select home item
selectFragment(homeItem);
} else {
super.onBackPressed();
}
}
private void selectFragment(MenuItem item) {
Fragment frag = null;
// init corresponding fragment
switch (item.getItemId()) {
case R.id.menu_home:
frag = HomeFragment.newInstance();
break;
case R.id.menu_archives:
frag = ArchivesFragment.newInstance();
break;
case R.id.menu_inspirational:
frag = InspirationalFragment.newInstance();
break;
case R.id.menu_search:
frag = SearchFragment.newInstance();
break;
}
// update selected item
mSelectedItem = item.getItemId();
// unchecked the other items.
//THIS LINE HERE
for (int i = 0; i < mBottomNav.getMenu().size(); i++) {
MenuItem menuItem = mBottomNav.getMenu().getItem(i);
menuItem.setChecked(menuItem.getItemId() == mSelectedItem);
}
updateToolbarText(item.getTitle());
if (frag != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, frag, frag.getTag());
ft.commit();
}
}
private void updateToolbarText(CharSequence text) {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(text);
}
}
Here is activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:design="http://schemas.android.com/apk/res-auto"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.ourdailystrength.mobile.android.MainActivity">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#f1f1f1">
</FrameLayout>
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
design:menu="#menu/bottom_nav_items" />
</LinearLayout>
Here is bottom_nav_items.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/menu_home"
android:title="#string/menu_home"
android:icon="#drawable/ic_home_black_48dp"
android:checked="true" <!-- Doesn't matter if this line is included or not -->
app:showAsAction="ifRoom"/>
<item
android:id="#+id/menu_archives"
android:title="#string/menu_archives"
android:icon="#drawable/ic_archive_black_48dp"
app:showAsAction="ifRoom"/>
<item
android:id="#+id/menu_search"
android:title="#string/menu_search"
android:icon="#drawable/ic_search_black_48dp"
app:showAsAction="ifRoom"/>
<item
android:id="#+id/menu_inspirational"
android:title="#string/menu_inspirational"
android:icon="#drawable/ic_photo_black_48dp"
app:showAsAction="ifRoom"/>
</menu>
Here is a screenshot of when it first boots up:
Why is the last menuitem being checked and not the first menuitem?
EDIT:
So, from answers given below, I made this change and it works:
private void selectFragment(MenuItem item) {
Fragment frag = null;
// update selected item
mSelectedItem = item.getItemId();
// unchecked the other items.
for (int i = 0; i < mBottomNav.getMenu().size(); i++) {
MenuItem menuItem = mBottomNav.getMenu().getItem(i);
menuItem.setChecked(false);
}
// init corresponding fragment
switch (mSelectedItem) {
case R.id.menu_home:
frag = HomeFragment.newInstance();
mBottomNav.getMenu().findItem(R.id.menu_home).setChecked(true);
break;
case R.id.menu_archives:
frag = ArchivesFragment.newInstance();
mBottomNav.getMenu().findItem(R.id.menu_archives).setChecked(true);
break;
case R.id.menu_inspirational:
frag = InspirationalFragment.newInstance();
mBottomNav.getMenu().findItem(R.id.menu_inspirational).setChecked(true);
break;
case R.id.menu_search:
frag = SearchFragment.newInstance();
mBottomNav.getMenu().findItem(R.id.menu_search).setChecked(true);
break;
}
updateToolbarText(item.getTitle());
if (frag != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, frag, frag.getTag());
ft.commit();
}
}
Why would the THIS LINE HERE in the above code cause it to do this weird error?
Hope this may help you to resolve your issue.
Call this method whenever you change the Fragment. Pass checkedcolor and unchecked color according to your needs.
private void changeMenuItemCheckedStateColor(int checkedColor, int uncheckedColor) {
int[][] states = new int[][]{
new int[]{-android.R.attr.state_checked}, // unchecked
new int[]{android.R.attr.state_checked}, // checked
};
int[] colors = new int[]{
uncheckedColor,
checkedColor
};
ColorStateList colorStateList = new ColorStateList(states, colors);
bottomNavigationView.setItemTextColor(colorStateList);
bottomNavigationView.setItemIconTintList(colorStateList);
}
There is 2 Solutions
1) Use Group
<group android:checkableBehavior="single">
<item .../>
<item .../>
<item .../>
</group>
2) Do it by programmatically
Menu bottomMenu;
BottomNavigationView bottomNavigationMenu = (BottomNavigationView) findViewById(R.id.bottom_navigation);
bottomMenu = navigation.getMenu();
bottomMenu.findItem(R.id.menu_home).setChecked(true);
Hope it will help , If you have any queries please comment.
Remove below code:
// unchecked the other items.
for (int i = 0; i < mBottomNav.getMenu().size(); i++) {
MenuItem menuItem = mBottomNav.getMenu().getItem(i);
menuItem.setChecked(menuItem.getItemId() == mSelectedItem);
}
and give tint color in BottomNavigationView:
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
app:itemIconTint="#drawable/nav_item_color_state"
design:menu="#menu/bottom_nav_items" />

BottomNavigationView text overlaps on icon

I have used BottomNavigationView in my app, but the text of menu item overlaps on menu icon in small devices as shown in below screenshot.
Edit:
Here is the java code:
public class MainActivity extends AppCompatActivity {
private static final String SELECTED_ITEM = "arg_selected_item";
private BottomNavigationView mBottomNav;
private int mSelectedItem;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBottomNav = (BottomNavigationView) findViewById(R.id.navigation);
BottomNavigationViewHelper.disableShiftMode(mBottomNav);
mBottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
selectFragment(item);
return true;
}
});
MenuItem selectedItem;
if (savedInstanceState != null) {
mSelectedItem = savedInstanceState.getInt(SELECTED_ITEM, 0);
selectedItem = mBottomNav.getMenu().findItem(mSelectedItem);
} else {
selectedItem = mBottomNav.getMenu().getItem(0);
}
selectFragment(selectedItem);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(SELECTED_ITEM, mSelectedItem);
super.onSaveInstanceState(outState);
}
#Override
public void onBackPressed() {
MenuItem homeItem = mBottomNav.getMenu().getItem(0);
if (mSelectedItem != homeItem.getItemId()) {
// select home item
selectFragment(homeItem);
} else {
super.onBackPressed();
}
}
private void selectFragment(MenuItem item) {
// init corresponding fragment
switch (item.getItemId()) {
case R.id.menu_explore:
pushFragment(new ExploreFragment());
break;
case R.id.menu_how_it_works:
pushFragment(new HowItWorksFragment());
break;
case R.id.menu_contact_us:
pushFragment(new ContactUsFragment());
break;
case R.id.menu_profile:
pushFragment(new MyProfileFragment());
break;
}
// update selected item
mSelectedItem = item.getItemId();
// uncheck the other items.
for (int i = 0; i < mBottomNav.getMenu().size(); i++) {
MenuItem menuItem = mBottomNav.getMenu().getItem(i);
menuItem.setChecked(menuItem.getItemId() == item.getItemId());
}
updateToolbarText(item.getTitle());
}
protected void pushFragment(Fragment fragment) {
if (fragment == null)
return;
FragmentManager fragmentManager = getFragmentManager();
if (fragmentManager != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (ft != null) {
ft.replace(R.id.container, fragment);
ft.commit();
}
}
}
private void updateToolbarText(CharSequence text) {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(text);
}
}
}
Here is the xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:design="http://schemas.android.com/apk/res-auto"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:background="#android:color/white"
design:menu="#menu/bottom_nav_items" />
</LinearLayout>
How to resolve this issue ?
Please Help!!
Do not use long texts on bottom bar. It's out of guideline. Bottom Bar is not developed to use like that.
Text labels provide short, meaningfully definitions to bottom
navigation icons. Avoid long text labels as these labels do not
truncate or wrap.
Read all documentation and usage descriptions at this Source.

How to get MenuItem position in the listener using the new NavigationView

The topic says it all. How should I go about retrieving the item position on the onClick listener using NavigationView? Also, why is there no getHeader method? Lastly I am doing everything programmatically, but the header is still clickable. Any thoughts?
Thanks!
I found a simple solution. You can assign an order using Menu's add(...) method. Then you can retrieve the order using MenuItems's getOrder(...) method. If you are using xml, you can use android:orderInCategory="...".
NavigationView navigationView = (NavigationView) findViewById(R.id.navigation);.
Menu menu = navigationView.getMenu();
for(int i=0; i < menu.size(); i++){
items.add(Menu.NONE, Menu.NONE, i, menu.getItem(i));
}
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener(){
#Override
public boolean onNavigationItemSelected(final MenuItem menuItem) {
// update highlighted item in the navigation menu
menuItem.setChecked(true);
int position=items.getOrder();
return true;
}
});
UPDATE
You can get position using this trick
final List<MenuItem> items = new ArrayList<>();
Menu menu;
NavigationView navigationView = (NavigationView) findViewById(R.id.navigation);.
menu = navigationView.getMenu();
for(int i = 0; i < menu.size(); i++){
items.add(menu.getItem(i));
}
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener(){
#Override
public boolean onNavigationItemSelected(final MenuItem menuItem) {
// update highlighted item in the navigation menu
menuItem.setChecked(true);
int position = items.indexOf(menuItem);
return true;
}
});
You can just take its order if you specify the "android:orderInCategory" attribute for menu items:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:orderInCategory="0"
android:title="#string/news" />
<item
android:orderInCategory="1"
android:title="#string/search" />
</menu>
val navigationView = findViewById<NavigationView>(R.id.navigation)
navigationView.setNavigationItemSelectedListener { menuItem ->
val menuItemOrder = menuItem.order
true
}
Or, use this in case you don't want to specify orders by hand:
val navigationView = findViewById<NavigationView>(R.id.navigation)
navigationView.setNavigationItemSelectedListener { menuItem ->
val menuItemIndex = bottomNavigation.menu.children.indexOf(menuItem)
true
}
If you are using menu_drawer.xml, you just have to add an id in the items like this:
<item
android:id="#+id/nav_top_stories"
android:title="#string/txt.menu.item1"
/>
With this you just have to test on menuItm.getId():
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener(){
#Override
public boolean onNavigationItemSelected(final MenuItem menuItem) {
// update highlighted item in the navigation menu
menuItem.setChecked(true);
switch(menuItem.getId()){
case R.id.txt_menu_item1 : //do what you want to do;
break;
case R.id.txt_menu_item2 : // etc,
}
return true;
}
});
If you are using dynamic menu, just use this method to add an item to you navigation drawer:
NavigationView.getMenu().add(int groupId, int itemId, int order, CharSequence title)
And then test by the order:
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener(){
#Override
public boolean onNavigationItemSelected(final MenuItem menuItem) {
// update highlighted item in the navigation menu
menuItem.setChecked(true);
switch(menuItem.getOrder()){
case 0 : //do what you want to do;
break;
case 1 : // etc,
default : //do whatever you want ;
}
return true;
}
});
In my case, i use
first test whit this..
Log.d(TAG, navigationView.getMenu().getItem(0).isChecked());
Log.d(TAG, navigationView.getMenu().getItem(1).isChecked());
Log.d(TAG, navigationView.getMenu().getItem(2).isChecked());
next this...
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
if(navigationView.getMenu().getItem(0).isChecked()) {
cerrarSesion();
}else {
navigationView.getMenu().getItem(0).setChecked(true);
seleccionarItem(navigationView.getMenu().getItem(0));
}
}
return false;
}
The easy, and most clean (in my opinion) way:
private int getBottomNavigationItemPosition(#MenuRes int itemId) {
final Menu bottomNavigationMenu = mBottomNavigationView.getMenu();
final int menuItemCount = bottomNavigationMenu.size();
for (int i = 0; i < menuItemCount; i++) {
if (bottomNavigationMenu.getItem(i).getItemId() == itemId) return i;
}
return -1; // the item with itemId was not found in Menu
}

How to save instance state of selected radiobutton on menu

I have options menu in my toolbar with radibutton item :
<item
android:id="#+id/map_menu"
android:icon="#drawable/ic_layer"
android:orderInCategory="102"
app:showAsAction="always"
android:title="#string/action_settings">
<menu>
<group
android:id="#+id/map_types_group"
android:checkableBehavior="single" >
<item
android:id="#+id/map_terrain"
android:orderInCategory="1"
app:showAsAction="ifRoom"
android:title="#string/map_terrain"/>
<item
android:id="#+id/map_normal"
android:orderInCategory="2"
android:checked="true"
app:showAsAction="ifRoom"
android:title="#string/map_normal"/>
<item
android:id="#+id/map_hybrid"
android:orderInCategory="3"
app:showAsAction="ifRoom"
android:title="#string/map_hybrid"/>
</group>
</menu>
</item>
I want to restore selected radiobutton when orientation change happened in onSaveInstanceState,onRestoreInstanceState but i can't understand how to get selected button from radiogroup in options menu.
Here is a fully working and tested example. With this code in place, no matter how many times you rotate the screen, the currently selected item will persist.
First, create these instance variables to keep track of the state of the menu and have a name for the preference you will be saving in the Bundle:
private final static String MENU_SELECTED = "selected";
private int selected = -1;
MenuItem menuItem;
The saveInstanceState() method should save off the currently selected value:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt(MENU_SELECTED, selected);
super.onSaveInstanceState(savedInstanceState);
}
Update the currently selected item in onOptionsItemSelected():
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
Log.d("settings", "id: " + id);
return true;
}
if (id == R.id.map_terrain){
Log.d("menuitem", "terrain id: " + id);
selected = id;
item.setChecked(true);
return true;
}
if (id == R.id.map_normal){
Log.d("menuitem", "normal id: " + id);
selected = id;
item.setChecked(true);
return true;
}
if (id == R.id.map_hybrid){
Log.d("menuitem", "hybrid id: " + id);
selected = id;
item.setChecked(true);
return true;
}
return super.onOptionsItemSelected(item);
}
In onCreate(), load the saved data if it exists:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null){
selected = savedInstanceState.getInt(MENU_SELECTED);
}
}
And then re-select the previously selected item in onCreateOptionsMenu():
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
if (selected == -1){
return true;
}
switch (selected){
case R.id.map_terrain:
menuItem = (MenuItem) menu.findItem(R.id.map_terrain);
menuItem.setChecked(true);
break;
case R.id.map_normal:
menuItem = (MenuItem) menu.findItem(R.id.map_normal);
menuItem.setChecked(true);
break;
case R.id.map_hybrid:
menuItem = (MenuItem) menu.findItem(R.id.map_hybrid);
menuItem.setChecked(true);
break;
}
return true;
}
MenuItem in onOptionsItemSelected has item.isChecked() method, just use it. You can store one boolean field(it wouldn't be a bad thing in my opinion) and change it whenever change in radiog group occurs
Then you can have your id by simply calling:
if(item.isChecked()) {
your_id_field = item.getItemId()
}
Create a variable eg: menu_selection to store the id of the menu item selected. Initially you can define 0
private int menu_selection = 0;
Save and restore the value of the variable using onSaveInstanceState and onRestoreInstanceState
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the id of radio button selected in the menu
savedInstanceState.putInt("selection", menu_selection);
super.onSaveInstanceState(savedInstanceState);
}
#Override
public void onRestoreInstanceState(#NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore state members from saved instance
menu_selection = savedInstanceState.getInt("selection");
}
In onOptionsItemSelected , assign the id of the menu item selected item.getItemId() to the variable
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
if (item.isChecked()) {
item.setChecked(false);
} else {
item.setChecked(true);
menu_selection = item.getItemId();
}
switch (item.getItemId()) {
case R.id.map_terrain:
//some action here
return true;
case R.id.map_normal:
//some action here
return true;
case R.id.map_hybrid:
//some action here
return true;
default:
return super.onOptionsItemSelected(item);
}
}
In onCreateOptionsMenu , find the menu item identified with the value in the variable and check it
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
if (menu_selection != 0) {
MenuItem selected = (MenuItem) menu.findItem(menu_selection);
selected.setChecked(true);
}
return true;
}

PopupMenu with checkableBehavior="single" group ignores setCheck() on items

I have a PopupMenu define in XML below being part of a Fragment
<menu xmlns:com.itrash.android="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="#+id/order_by_menu" android:checkableBehavior="single">
<item android:id="#+id/action_show_discounts_only"
android:title="#string/discounts_only_title" />
<item android:id="#+id/action_show_all"
android:title="#string/all_title" />
</group>
The menu is linked to ImageButton (snippet from onActionCreated() )
final SharedPreferences prefs = getActivity().getPreferences(Context.MODE_PRIVATE);
this.onlyDiscounts = prefs.getBoolean(PROPERTY_ONLY_DISCOUNTS, false);
this.orderBy = prefs.getString(PROPERTY_ORDER_BY, ORDER_BY_NAME);
this.filterButton = (ImageButton) getActivity().findViewById(R.id.filter_button);
this.filterButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
filterMenu.show();
}
});
this.filterMenu = new PopupMenu(getActivity(), getActivity().findViewById(R.id.filter_button));
this.filterMenu.inflate(R.menu.product_filter_menu);
this.filterMenu.setOnMenuItemClickListener(new OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
onFilterClick(item);
return true;
}
});
When clicked the following method is called
private void onFilterClick(MenuItem item) {
boolean showDiscountsOnly = item.getItemId() == R.id.action_show_discounts_only ? true : false;
item.setChecked(!item.isChecked());
if (this.onlyDiscounts != showDiscountsOnly) {
this.onlyDiscounts = showDiscountsOnly;
productSearchResultAdapter.clear();
this.curPage = 1;
doSearchProducts();
}
final SharedPreferences prefs = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(PROPERTY_ONLY_DISCOUNTS, showDiscountsOnly);
editor.commit();
}
Problem I am facing is how to restore state of menu items according to attribute onlyDiscounts when retrieved from SharedPreferences?
In other words I want to have the menu item *action_show_discounts_only* checked if onlyDiscounts is true.
I have tried to place inside onActionCreated() something along the lines
for (int i = 0; i < this.filterMenu.getMenu().size(); i++) {
MenuItem item = this.filterMenu.getMenu().getItem(i);
if (item.getItemId() == R.id.action_show_discounts_only) {
item.setChecked(true);
} else {
item.setChecked(false);
}
}
or even
this.filterMenu.getMenu().findItem(R.id.action_show_discounts_only).setChecked(this.onlyDiscounts);
this.filterMenu.getMenu().findItem(R.id.action_show_all).setChecked(!this.onlyDiscounts);
Both attempts were ignored, *R.id.action_show_all* item is always check no matter what value onlyDiscounts is.
Any idea how to resolve this?

Categories

Resources