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
Related
I want to implement a BottomNavigationView and have added one of material.io's icons as a png to my drawables. When I insert it as:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/navigation_home"
android:icon="#drawable/ic_home_black_24dp"
android:title="#string/title_home" />
<item
android:id="#+id/navigation_dashboard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="#drawable/ic_dashboard_black_24dp"
android:title="#string/title_dashboard" />
<item
android:id="#+id/navigation_notifications"
android:icon="#drawable/ic_notifications_black_24dp"
android:title="#string/title_notifications" />
<!-- This is my item added to the normal template -->
<item
android:id="#+id/navigation_more"
android:icon="#drawable/ic_more_horiz_black_24dp"
android:title="#string/title_more" />
</menu>
And use it in the main activity, It shows up, but the item will not highlight when pressed on the simulator, whereas the others will ( by highlight, I mean it will slightly blow up and change to the primary color, showing some text underneath). I tried both vectors and .pngs, nothing will work. I am running backwards compatible to Android 5.0 (Target Version 27).
The home Activity currently looks like:
public class HomeActivity extends AppCompatActivity {
private TextView mTextMessage;
private BottomNavigationView.OnNavigationItemSelectedListener
mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
mTextMessage.setText(R.string.title_home);
return true;
case R.id.navigation_dashboard:
mTextMessage.setText(R.string.title_dashboard);
return true;
case R.id.navigation_notifications:
mTextMessage.setText(R.string.title_notifications);
return true;
case R.id.navigation_more:
mTextMessage.setText(R.string.title_more);
}
return false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mTextMessage = (TextView) findViewById(R.id.message);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
}
The text view is set correctly, the icon just won't highlight.
your navigation method always return false, try return true when there is a case handled by the switch ;)
for example:
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
mTextMessage.setText(R.string.title_home);
return true;
case R.id.navigation_dashboard:
mTextMessage.setText(R.string.title_dashboard);
return true;
case R.id.navigation_notifications:
mTextMessage.setText(R.string.title_notifications);
return true;
case R.id.navigation_more:
mTextMessage.setText(R.string.title_more);
return true; // this was my mistake...
default:
return false;
}
return false;
}
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 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
Anyone know how to create the submenu with radio buttons like in the screenshot?
If you want a submenu with checkable radio buttons you should use something like that:
<?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/red"
android:title="#string/red" />
<item android:id="#+id/blue"
android:title="#string/blue" />
</group>
</menu>
And then in the code:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.red:
return true;
case R.id.blue:
return true;
default:
return super.onOptionsItemSelected(item);
}
}
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. :)