Graying out the Save item in toolbar only happens in design mode but never on runtime.
I'm using this code:
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
if(count > 0) {
menuItemSave.setEnabled(true);
} else {
menuItemSave.setEnabled(false);
}
return true;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
menuItemSave = menu.findItem(R.id.save);
return true;
}
It's enabling/disabling but it just really not turning into gray when disabled.
You can use custom color to change color when button is enabled or disabled. [ Change color according to your requirement ]
colors/custom_button_color.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#FF0000" android:state_enabled="false" />
<item android:color="#CCCCCC"/>
</selector>
In menu.xml file set to your required button item like
android:textColor="#color/custom_button_color"
According to Android docs onPrepareOptionsMenu is called just before menu is opened.But if menu is always open, it will not be called.
So,
On Android 3.0 and higher, you must call invalidateOptionsMenu() when you want to update the menu that is always open. The system will then call onPrepareOptionsMenu() so you can update the menu items.
Related
I have been reading answers to questions on here for hours and no solutions seem to work for me.
I am creating an android app for DnD Character Creations, and if the user selects a magical class, I would like to add a spell book option to the main menu.
For some reason, no matter what I do, it will either show visible or invisible based on the XML and will not change it through the code.
This is my XML:
<?xml version="1.0" encoding="utf-8"?>
<!--TODO: create related icons-->
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_profile"
android:title="Profile"
android:visible="true"/>
<item
android:id="#+id/nav_battle"
android:title="Battle"
android:visible="true"/>
<item
android:id="#+id/nav_items"
android:title="Items"
android:visible="true"/>
<item
android:id="#+id/nav_spellbook"
android:title="Spell Book"
android:visible="false"/>
</group>
This was attempt 1 in java:
public void classBasedTraits() {
int intHealthInitial = 0;
//end attempt
switch (strCharacterClass) {
case "Sorcerer":
case "Wizard":
intHealthInitial = 6; // Sorcerer and Wizard's initial health is 6
break;
case "Bard":
case "Cleric":
case "Druid":
case "Monk":
case "Rogue":
case "Warlock":
intHealthInitial = 8; // Bard, Cleric, Druid, Monk, Rogue, and Warlock's initial health is 8
break;
case "Fighter":
case "Paladin":
case "Ranger":
intHealthInitial = 10; // Fighter, Paladin, and Ranger's initial health is 10
break;
case "Barbarian":
intHealthInitial = 12; // Barbarian's initial health is 12
break;
}
//Attempt to create spellbook for magical classes'
Set<String> setMagical;
setMagical = new HashSet<String>(Arrays.asList("Bard", "Cleric", "Druid", "Paladin",
"Ranger", "Sorcerer", "Warlock", "Wizard"));
if(setMagical.contains(strCharacterClass)){
magical = true;
invalidateOptionsMenu();
}
intTotalHP = intHealthInitial + intConstitutionMod; // Starting HP is initial health + constitution modifier
intRemainingHP = intTotalHP; // Sets character at full health
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.activity_main_drawer, menu);
menu.findItem(R.id.nav_spellbook).setVisible(magical);
return super.onPrepareOptionsMenu(menu);
}
this was attempt 2 in java, in the Profile activity class, because this class is called after the character class has been specified, and this function is when the menu is set up for the first time:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.activity_main_drawer, menu);
Set<String> setMagical;
setMagical = new HashSet<String>(Arrays.asList("Bard", "Cleric", "Druid", "Paladin",
"Ranger", "Sorcerer", "Warlock", "Wizard"));
MenuItem spellbook = menu.findItem(R.id.nav_spellbook);
if(setMagical.contains(characterClass))
{
spellbook.setVisible(true);
}
else
{
spellbook.setVisible(false);
}
return true;
}
Here is the project on github if anyone want's to take a look at the full code
https://github.com/Doszust/RPG-Character-Sheet/tree/master/app/src/main/java/com/ucfknights/dylan_oszust/dungeonsanddragons
You were on the right track with the first attempt. You use invalidateOptionsMenu() to trigger a call to onPrepareOptionsMenu() where you implement your changes to the menu.
You need to return true from onPrepareOptionsMenu() in order for it to be displayed.
Also don't inflate the menu again in onPrepareOptionsMenu(). You are already supplied the menu in the method parameters.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.activity_main_drawer, menu);
return true;
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.nav_spellbook).setVisible(magical);
return true;
}
Your menu file should look like this:
<?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/nav_profile"
android:title="Profile"
android:visible="true"/>
<item
android:id="#+id/nav_battle"
android:title="Battle"
android:visible="true"/>
<item
android:id="#+id/nav_items"
android:title="Items"
android:visible="true"/>
<item
android:id="#+id/nav_spellbook"
android:title="Spell Book"
android:visible="false"/>
</group>
</menu>
So onCreateOptionsMenu() is where you first create the menu. Then onPrepareOptionsMenu() is where you can modifiy it from then on.
For anyone who is also looking to fix this problem with the nav_drawer menu, you have to access it differently than the standard options menu (Thanks to Sound Conception for pointing out the difference). The code should get the menu from the navigation view.
The working code is below, it is the initial menu builder for the app, and it checks to see if the class is a magical class before deciding to show or hide the spellbook option in the nav drawer.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
Set<String> setMagical;
setMagical = new HashSet<String>(Arrays.asList("Bard", "Cleric", "Druid", "Paladin",
"Ranger", "Sorcerer", "Warlock", "Wizard"));
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
Menu nav_Menu = navigationView.getMenu();
MenuItem spellbook = nav_Menu.findItem(R.id.nav_spellbook);
if(setMagical.contains(characterClass))
{
spellbook.setVisible(true);
}
else
{
spellbook.setVisible(false);
}
return true;
}
This question already has answers here:
How to add button in ActionBar(Android)?
(2 answers)
Add button in android action bar
(2 answers)
Closed 5 years ago.
As title says i don't know how to add button to android action bar near title of app with icon.
I need to add it here as shown on picture
enter image description here
First, create a menu resource, name it whatever you want.
Then, add this to your new .xml resource:
<menu xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:ignore="AlwaysShowAction">
<item android:id="#+id/your_item_id"
android:icon="#drawable/your_drawable_id"
android:title="#string/your_string_id"
app:showAsAction="always" />
</menu>
The item tag defines the id, the icon and the title. the showAsAction defines if item is located at the action bar or submenu.
It's recommended to use string resources for your title, specially if you want to translate your app.
The menu icon is defined by your drawable resource. In order to use the correct size, I recommend to use the default icon asset wizard.
Add this to your Activity to add the menu:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.your_menu_name, menu);
return true;
}
In order to detect menu pushes, use this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.your_item_id) {
//Do your stuff here
return true;
}
return super.onOptionsItemSelected(item);
}
More info: https://developer.android.com/guide/topics/ui/menus.html
This is my layout for a menu.
Notice the item:
<?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/action_best_stores"
android:title="#string/showStores"
android:onClick="showHideStores"
android:enabled="true"
android:checkable="true"
app:showAsAction="never"
/>
</menu>
This is the onAction function.
public void showHideStores(MenuItem m) {
m.setChecked(!m.isChecked());
SHOWING_STORES = !SHOWING_STORES;
showStoresProcess(SHOWING_STORES);
refreshData();
invalidateOptionsMenu();
}
Whenever I run my program, the function works because things that are supposed to happen, happen. Except, for the part where the ItemMenu itself changes... It just doesn't do anything, the checkbox stays unchecked... I also tried setTitle, doesn't change anything either.
So, line 1 isn't producing any change.
What is going on?
This is the code where I inflate the Menu
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_list_actions, menu);
super.onCreateOptionsMenu(menu);
this.menu = menu;
refreshData();
return true;
}
Notice how the function works because the screen changes, but the menu itself doesn't get "checked off" or "unchecked".
The problem is explained as follow:
When you call invalidateOptionsMenu(), it will reset to default menu. So nothing happened.
Solution: override onPrepareOptionsMenu()
#override
public bool onPrepareOptionsMenu(Menu menu)
{
super.onPrepareOptionsMenu(menu);
MenuItem m = memenu.findItem(R.id.YourItemId);
m.setChecked(!m.isChecked());//something like this
return true;
}
Remove your call to invalidateOptionsMenu(). Calling invalidateOptionsMenu() is going trigger a call back to onCreateOptionsMenu() which is going to create a new menu which will create a new un-checked MenuItem, basically exactly what you don't want to halpen.
I have a refresh icon on my menu which when clicked will refresh the contents of the Activity. But the problem is that the refresh icon is still clickable while it is refreshing which I do not want. Here is my menu.xml file
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item
android:id="#+id/action_refresh"
android:orderInCategory="100"
android:icon="#mipmap/ic_refresh"
android:enabled="true"
android:title="#string/action_settings"
app:showAsAction="always"/>
And here is where I handle the click event for the icon
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_refresh) {
// getData() fetches the data and updates the display
getData();
return true;
}
return super.onOptionsItemSelected(item);
}
Also, is there a way to maybe dim the icon so that the user knows that they have already clicked the icon?
When you click the icon, use the isEnabled() method of your Menuitem to check if it is currently enabled. If it is, then disable it until the data is loaded. Once the data loads successfully, then you can enable it again. Example:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(item.isEnabled()) {
// "Dim" the icon like you said. You can use other alpha values if you like.
item.getIcon().setAlpha(130);
// Disable the menu icon
item.setEnabled(false);
}
getData();
return true;
}
return super.onOptionsItemSelected(item);
}
Now, you said that you have a getData() method which updates the display after it fetches the data. Once the data is fetched, check if the Menuitem is disabled. If it is disabled, then enable it again. Example:
if(item != null && item.isEnabled() == false) {
// "Undim" the icon
item.getIcon().setAlpha(255);
// Enable it again
item.setEnabled(true);
}
You can use setEnabled(true) method to enable/disable menu item
You could create a second menu.xml, that is used after the refresh button is clicked. To force a menu redraw call invalidateOptionsMenu();
In this second menu.xml, the refresh button could be disabled, or switched to a diffrent one, indicating the user, that the refresh is on going.
Easiest way to fix this is to hold on to the menu item in your activity.
private MenuItem mRefreshItem;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater infl = new MenuInflater(this);
infl.inflate(R.menu.menu, menu);
mRefreshItem = menu.findItem(R.id.action_refresh);
return super.onCreateOptionsMenu(menu);
}
/** Call this when you begin or end loading */
private void setRefreshEnabled(boolean enabled) {
mRefreshItem.setEnabled(enabled);
}
On my ActionBar there is one item that has an icon about a star(without filled).
When the user clicks on it, the icon changes to another icon(filled star).
But the problem is that if the user cliccks again the icon doesn't change one more time.
So, this is what i want
icon1->click->icon2->click->icon1->click->icon2
My item xml:
<item
android:id="#+id/bookmark"
android:icon="#drawable/bookmark"
android:showAsAction="ifRoom"
android:title="Add to Favorites"/>
My Java for actionBar:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
inflater.inflate(R.menu.activity_desc, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.bookmark){
// i tried this: something like: if(item.getIcon() == (R.drawable.nobookmark){} it doesn't work
item.setIcon(R.drawable.nobookmark);
return true;
}
return true;
}
In your item.xml make it checkable:
<item
android:id="#+id/bookmark"
android:icon="#drawable/nobookmark"
android:checkable="true"
android:showAsAction="ifRoom"
android:title="Add to Favorites"/>
In the java you must manually toggle the checked state and select the icon:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.bookmark){
item.setChecked(!item.isChecked());
item.setIcon(item.isChecked() ? R.drawable.bookmark : R.drawable.nobookmark);
return true;
}
return false;
}