I have a working app with an overflow menu. All the code in the menu works, but no checkmarks are being shown after I click on a single-clickable, grouped menu item.
Am I doing something fundamentally wrong? I thought that this displaying of the checkmark was automatic to Android and that the system would do this for me. Android knows it is in a group, it knows that only one can be selected, and it knows which one I selected! So..... Android should know how to display the checkmarks.
Code
XML
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".Calculator">
<group
android:checkableBehavior="single"
android:visible="true">
<item
android:id="#+id/ui_simple"
android:orderInCategory="100"
app:showAsAction="ifRoom|withText"
android:title="Regular"
android:checkable="true"/>
<item
android:id="#+id/ui_doge"
android:orderInCategory="100"
app:showAsAction="ifRoom|withText"
android:title="Doge"
android:checkable="true"/>
<item
android:id="#+id/ui_static"
android:orderInCategory="100"
app:showAsAction="ifRoom|withText"
android:title="Static"
android:checkable="true"/>
</group>
<item android:title="Display Mode"
android:orderInCategory="101" >
<menu>
<group android:checkableBehavior="single" android:visible="true" >
<item
android:id="#+id/mode_sign"
android:orderInCategory="100"
app:showAsAction="collapseActionView"
android:title="Sign Form"
android:checkable="true"/>
<item
android:id="#+id/mode_noun"
android:orderInCategory="100"
app:showAsAction="collapseActionView"
android:title="Noun Form"
android:checkable="true"/>
<item
android:id="#+id/mode_verb"
android:orderInCategory="100"
app:showAsAction="collapseActionView"
android:title="Verb Form"
android:checkable="true"/>
</group>
</menu>
</item>
</menu>
UI
Note: I have tried switching all the breaks to return true, but nothing happens.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
switch (item.getItemId()) {
case R.id.ui_simple :
startActivity(new Intent(this, Calculator.class));
break;
case R.id.ui_doge :
startActivity(new Intent(this, CalculatorDoge.class));
break;
case R.id.ui_static :
startActivity(new Intent(this, CalculatorStatic.class));
break;
case R.id.mode_sign : display = BinaryOperation.Display.SIGN; break;
case R.id.mode_verb : display = BinaryOperation.Display.VERB; break;
case R.id.mode_noun : display = BinaryOperation.Display.NOUN; break;
}
return super.onOptionsItemSelected(item);
}
While #Elltz provides a valuable solution to a problem in the code, there are a total of 2 issues in the code.
Problem 1
Do not set a checkable XML attribute in both the Menu Group and the individual MenuItems.
since in the XML there is <group android:checkableBehavior="single" it shows that radio buttons are desired; therefore, no item within the group should have android:checkable="true"
<group
android:checkableBehavior="single" <!-- ONLY HERE -->
android:visible="true" >
<item
android:id="#+id/mode_sign"
android:orderInCategory="100"
app:showAsAction="collapseActionView"
android:title="Sign Form" />
<item
android:id="#+id/mode_noun"
android:orderInCategory="100"
app:showAsAction="collapseActionView"
android:title="Noun Form"/>
<item
android:id="#+id/mode_verb"
android:orderInCategory="100"
app:showAsAction="collapseActionView"
android:title="Verb Form"/>
</group>
Problem 2
Again, #Elltz provides a good solution; however, it is slightly more complex than what it needs to be.
For Single Selection Only
switch (item.getItemId()) {
case R.id.ui_simple : startActivity(new Intent(this, Calculator.class)); return true;
case R.id.ui_doge : startActivity(new Intent(this, CalculatorDoge.class)); return true;
case R.id.ui_static : startActivity(new Intent(this, CalculatorStatic.class)); return true;
// Single Selection - Radio Buttons
case R.id.mode_sign :
item.setChecked(true); // ONLY THIS....HERE
display = BinaryOperation.Display.SIGN;
return true;
case R.id.mode_verb :
item.setChecked(true); // HERE
display = BinaryOperation.Display.VERB;
return true;
case R.id.mode_noun :
item.setChecked(true); // AND HERE
display = BinaryOperation.Display.NOUN;
return true;
default : return super.onOptionsItemSelected(item);
}
For Single OR Multi Selection
// Single OR Multi Select - Radio Buttons or CheckBoxes
switch (item.getItemId()) {
case R.id.ui_simple : startActivity(new Intent(this, Calculator.class)); return true;
case R.id.ui_doge : startActivity(new Intent(this, CalculatorDoge.class)); return true;
case R.id.ui_static : startActivity(new Intent(this, CalculatorStatic.class)); return true;
case R.id.mode_sign :
item.setChecked(!item.isChecked()); // LIKE THIS...HERE
display = BinaryOperation.Display.SIGN;
return true;
case R.id.mode_verb :
item.setChecked(!item.isChecked()); // HERE
display = BinaryOperation.Display.VERB;
return true;
case R.id.mode_noun :
item.setChecked(!item.isChecked()); // AND HERE
display = BinaryOperation.Display.NOUN;
return true;
default : return super.onOptionsItemSelected(item);
}
No
Menu items in the Icon Menu (from the options menu) cannot display a checkbox or radio button. If you choose to make items in the Icon Menu checkable, you must manually indicate the checked state by swapping the icon and/or text each time the state changes.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.ui_simple:
if (item.isChecked()){
item.setChecked(false);
}else{
item.setChecked(true);
}
startActivity(new Intent(this, Calculator.class));
break;
case R.id.ui_doge:
//same goes here and everyone
break;
....
}
}
Hope it helps
Related
I have three groups of menu items that are checkable.
Each group is configured with single checkable behavior, but checking an item in group A will uncheck items in group B and C.
How can i solve this?
You just need to add unique IDs to each of the group items in the xml file.
<group
android:id="#+id/menuGroup_1"
android:checkableBehavior="single">
<item android:id="#+id/group_1_item_1"/>
<item android:id="#+id/group_1_item_2"/>
</group>
<group
android:id="#+id/menuGroup_2"
android:checkableBehavior="single">
<item android:id="#+id/group_2_item_1"/>
<item android:id="#+id/group_2_item_2"/>
</group>
Then implement your logic here:
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.group_1_item_1:
item.setChecked(true);
return true;
case R.id.group_1_item_2:
item.setChecked(true);
return true;
case R.id.group_2_item_1:
item.setChecked(true);
return true;
case R.id.group_2_item_2:
item.setChecked(true);
return true;
default:
return super.onOptionsItemSelected(item);
}
I have map activity and I am trying to add toggle button to the actionbar next to the setting menu which contains the map type but I am facing a problem: the toggle button is being added to the setting items menu and not directly to the actionbar.
How can I add this toggle button to the actionbar next to the setting menu?
map_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/mapTypeNormal"
android:title="Normal"/>
<item
android:id="#+id/mapTypeSatellite"
android:title="Satellitte"/>
<item
android:id="#+id/mapTypeTerrain"
android:title="Terrain"/>
<item
android:id="#+id/mapTypeHybrid"
android:title="Hybrid"/>
<item
android:id="#+id/mapTypeNone"
android:title="None"/>
<item android:id="#+id/menu_toggle"
android:showAsAction="ifRoom"
android:icon="#drawable/off"
android:title="Share"
/>
</menu>
map activity:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.map_menu, menu);
System.out.println("ABC MAP onCreateOptionsMenu was invoked.");
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.mapTypeNone:
map.setMapType(GoogleMap.MAP_TYPE_NONE);
break;
case R.id.mapTypeNormal:
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
break;
case R.id.mapTypeSatellite:
map.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
break;
case R.id.mapTypeTerrain:
map.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
break;
case R.id.mapTypeHybrid:
map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
break;
default:
break;
}
switch (item.getItemId()) {
case R.id.menu_toggle:
if (birthSort) {
// change your view and sort it by Alphabet
item.setIcon(R.drawable.on);
item.setTitle("On");
birthSort = false;
} else {
// change your view and sort it by Date of Birth
item.setIcon(R.drawable.off);
item.setTitle("Off");
birthSort = true;
}
}
return super.onOptionsItemSelected(item);
}
}
Use additional attribute always on menu item:
app:showAsAction="always"
and it can be combined with text as well:
app:showAsAction="withText|always"
Adjust your namespace accordingly. Here is a complete sample:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_sync"
android:title="#string/action_sync"
app:showAsAction="withText|always"/>
</menu>
Pay attention to the app: prefix for showAsAction and the corresponding namespace declaration.
I have a submenu with buttons set up in xml which works fine.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Single menu item
Set id, icon and Title for each menu item
-->
<item android:id="#+id/menu_level"
android:title="Set Level" >
<menu>
<group android:checkableBehavior="single">
<item android:id="#+id/one"
android:checked="false"
android:title="One" />
<item android:id="#+id/two"
android:title="Two" />
<item android:id="#+id/three"
android:title="Three" />
</group>
</menu>
</item>
<item android:id="#+id/menu_save"
android:icon="#drawable/icon_save"
android:title="Save" />
<item android:id="#+id/menu_about"
android:icon="#drawable/icon_bookmark"
android:title="About">
<menu>
<item android:id="#+id/copyright"
android:title="(c) John Beukema 2012">
</item>
</menu>
<item/>
</menu>
I access it as follows:
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
Editor editor = PreferenceManager
.getDefaultSharedPreferences(this).edit();
switch (item.getItemId())
{
case R.id.menu_save:
return true;
case R.id.menu_recall:
return true;
case R.id.menu_level: {
return true;
}
case R.id.menu_about:
return true;
case R.id.one:
star = 1;
editor.putInt("Star", 1);
editor.commit();
item.setChecked(true);
return true;
case R.id.two:
star = 2;
editor.putInt("Star", 2);
editor.commit();
item.setChecked(true);
return true;
case R.id.three:
star = 3;
editor.putInt("Star", 3);
editor.commit();
item.setChecked(true);
return true;
case R.id.menu_delete:
return true;
case R.id.menu_preferences:
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
So far no problem. But I want to load the buttons on start up from preferences.
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences preferences = PreferenceManager
.getDefaultSharedPreferences(this);
star = preferences.getInt("Star", 1);
MenuItem one = (MenuItem) findViewById(R.id.one);
MenuItem two = (MenuItem ) findViewById(R.id.two);
MenuItem three = (MenuItem) findViewById(R.id.three);
switch(star)
{
case 1:
one.setChecked(true); break;
case 2:
two.setChecked(true); break;
case 3:
three.setChecked(true); break
}
}
}
This compiles but hangs. How do I address the submenu buttons?
I dont think you can do findviewbyid on menuitem. You need to set or unset the checked items in onprepareoptionsmenu
I am writing an Android app where the user must choose how and what to display on a graph. These options are expressed in two single-selection menu groups (radio buttons), both of which should be accessible from the action bar.
The first group works fine. It's added at the end of my ActionBar XML like this:
<group android:checkableBehavior="single" android:showAsAction="never" >
<item android:id="#+id/menu_choice_1" android:title="Choice 1" />
<item android:id="#+id/menu_choice_2" android:title="Choice 2" android:checked="true"/>
</group>
When I add a second <group> below the first one, however, the two merge into one single-selection list. In other words, the options from both lists are rendered together and if I choose an option pertaining to the first list, I cannot choose anything from the second.
Instead, I want two separate lists of radio buttons. My next idea was to add another button the ActionBar that, when clicked, would launch a pop-up menu. But when I click the button, I get an IllegalStateException, saying that my "MenuPopupHelper cannot be used without an anchor".
Here is my attempted pop-up menu code:
In my ActionBar XML:
<item android:id="#+id/menu_openothermenu"
android:title="#string/openothermenustr"
android:showAsAction="always" />
My new menu XML:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item android:id="#+id/menu_2_choice_1" android:title="#string/2_choice_1" />
<item android:id="#+id/menu_2_choice_2" android:title="#string/2_choice_2" android:checked="true"/>
</group>
</menu>
Code in my Activity:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor;
switch (item.getItemId()) {
case R.id.openothermenu:
Menu m = (Menu) findViewById(R.menu.other_menu);
PopupMenu popup = new PopupMenu(this, findViewById(R.menu.main_menu));
popup.setOnMenuItemClickListener(this);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.other_menu, popup.getMenu());
/* This commented block doesn't work either, and prevents execution
// Restore saved chosen value
int chosen = settings.getInt(MENU_2_PREFS, -1);
switch(chosen)
{
case 1:
m.findItem(R.id.menu_1_choice_1).setChecked(true);
updateVisibleThings();
break;
default:
case 2:
m.findItem(R.id.menu_2_choice_2).setChecked(true);
updateOtherVisibleThings();
break;
}
*/
popup.show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public boolean onMenuItemClick(MenuItem item) {
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor;
switch(item.getItemId()) {
case R.id.menu_2_choice_1:
if (item.isChecked()) item.setChecked(false);
else item.setChecked(true);
updateVisibleThings();
// save chosen setting
editor = settings.edit();
editor.putInt(MENU_2_PREFS, 1);
editor.commit(); // Commit the edits!
return true;
case R.id.menu_2_choice_2:
if (item.isChecked()) item.setChecked(false);
else item.setChecked(true);
updateOtherVisibleThings();
// save chosen setting
editor = settings.edit();
editor.putInt(MENU_2_PREFS, 2);
editor.commit(); // Commit the edits!
return true;
default:
return true;
}
}
How can I create two sets of checkable menu items such that both are attached to the ActionBar?
I found an elegant way to solve this that was unfortunately not in the documentation. Add the following code to your ActionBar menu XML:
<item android:id="#+id/menu_openothermenu"
android:title="#string/openothermenustr"
android:showAsAction="always">
<menu>
<group android:checkableBehavior="single">
<item android:id="#+id/menu_2_choice_1" android:title="#string/2_choice_1" android:showAsAction="never" />
<item android:id="#+id/menu_2_choice_2" android:title="#string/2_choice_2" android:showAsAction="never" android:checked="true" />
</group>
</menu>
</item>
No extra handler code or popup menu implementation is necessary for such a menu to appear.
Alright, this might be simple but I dunno how to do it! I have my menu defined through XML, as shown below. It loads and everything.
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/home"
android:title="Home" />
<item android:id="#+id/about"
android:title="About" />
<item android:id="#+id/quit"
android:title="Quit" />
</menu>
Now, going through onOptionsItemSelected(), how do I tell which menu item is selected?
This is from an example... What would the case's be?
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 1:
Toast.makeText(this, "Home", Toast.LENGTH_LONG).show();
return true;
case 2:
Toast.makeText(this, "About", Toast.LENGTH_LONG).show();
return true;
case 3:
Toast.makeText(this, "Quit", Toast.LENGTH_LONG).show();
return true;
}
return false;
}
Your case statements should use the ids defined in your xml:
case R.id.home:
....
case R.id.about:
....
case R.id.quit:
....
default:
throw new IllegalStateException("oops, forgot to code something");
the default case is just good practice imho. :)