In my application, I manage the options menu to reflect the state my application is in. Three menus are possible.
In the onCreateOptionsMenu function, I inflate the basic entries from an XML file.
In the onPrepareOptionsMenu function, I clear the menu and then inflate the XML file which corresponds to the current state of my application.
And this leads to unexpected results!!!
When I change the menu from state 1 to state 2 and then revert to state 1, the "more" entry is visually replaced by one of the entries of my menu. But it's function is correct : if I click on it, the overflow menu appears!
And then, if I change for state 3, no menu appears when I try to open it. And if I debug the code, I see the menu is correctly filled with the result of the inflation (the size of the menu changes accordingly).
I can add that the code works perfectly with Android 2.3.3. The problem only occurs when I execute it on Android 4 (not tested with Android 3).
Any idea?
As requested, I have simplified my code to let you see the problem.
The code of the application is below :
public class MainActivity extends Activity{
private boolean m2=false,m3=false;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflateur;
inflateur = getMenuInflater();
inflateur.inflate(R.menu.menu_1,menu);
return (true);
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuInflater inflateur;
inflateur = getMenuInflater();
menu.clear();
if (m2){
inflateur.inflate(R.menu.menu_2,menu);
} else {
if(m3) {
inflateur.inflate(R.menu.menu_3, menu);
} else {
inflateur.inflate(R.menu.menu_1, menu);
}
}
return (true);
}
#Override
public boolean onOptionsItemSelected(MenuItem entréeMenu) {
switch (entréeMenu.getItemId()) {
case R.menu.m1_4: {
return true;
}
case R.menu.m1_5: {
return true;
}
case R.menu.m1_7: {
return true;
}
case R.menu.m1_8: {
return true;
}
case R.menu.m1_10: {
return true;
}
case R.menu.m1_12: {
return (true);
}
case R.menu.m1_13: {
return (true);
}
case R.menu.m1_1: {
return true;
}
case R.menu.m1_11: {
// change for menu_2
m2=true;
m3=false;
return true;
}
case R.menu.m3_1: {
return true;
}
case R.menu.m3_2: {
return true;
}
case R.menu.m2_1: {
// revert to menu_1
m2=false;
return true;
}
case R.menu.m2_2: {
return true;
}
case R.menu.m1_2: {
// change for menu_3
m2=false;
m3=true;
return true;
}
case R.menu.m1_3: {
return true;
}
case R.menu.m3_3: {
// revert to menu_1
m3=false;
return true;
}
case R.menu.m2_5: {
return true;
}
case R.menu.m2_3: {
return true;
}
case R.menu.m2_4: {
return true;
}
case R.menu.m1_6: {
return (true);
}
case R.menu.Options: {
return (true);
}
case R.menu.m1_14:{
return(true);
}
default: {
return super.onOptionsItemSelected(entréeMenu);
}
}
}
}
Only four menu entries are active : 1.11 changes from menu_1 to menu_2, 2.1 reverts to menu_1; 1.2 changes from menu_1 to menu_3 and 3.3 reverts to menu_1.
The problems encountered so far :
1) click on 1.11 to change for menu_2. Open the menu : only 5 menu items are displayed. Close the menu and re-open it : the 6 menu items are now correctly displayed.
2) click on 2.1 to return to menu 1. In the sixth position, you can see "2.6" instead of "more". If you click on "2.6", the behaviour corresponds to a click on "more".
And now, the XML files for the menus :
menu_1 :
<?xml version="1.0" encoding="UTF-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+menu/m1_1"
android:title="1.1">
</item>
<item android:id="#+menu/m1_2"
android:title="1.2">
</item>
<item android:id="#+menu/m1_3"
android:title="1.3">
</item>
<item android:id="#+menu/m1_4"
android:title="1.4">
</item>
<item android:id="#+menu/m1_5"
android:title="1.5"
android:checkable="true">
</item>
<item android:id="#+menu/m1_6"
android:title="1.6"
android:checkable="true">
</item>
<item android:id="#+menu/m1_7"
android:title="1.7"
android:checkable="true">
</item>
<item android:id="#+menu/m1_8"
android:title="1.8"
android:checkable="true">
</item>
<item android:id="#+menu/m1_9"
android:title="1.9"
android:enabled="false"
android:visible="false"
android:checkable="true">
</item>
<item android:id="#+menu/m1_10"
android:title="1.10">
</item>
<item android:id="#+menu/m1_11"
android:title="1.11">
</item>
<item android:id="#+menu/m1_12"
android:title="1.12">
</item>
<item android:id="#+menu/m1_13"
android:title="1.13">
</item>
<item android:id="#+menu/m1_14"
android:title="1.14">
</item>
<item android:id="#+menu/Options"
android:title="1.15">
</item>
menu_2 :
<item android:id="#+menu/m2_2"
android:title="2.2">
</item>
<item android:id="#+menu/m2_3"
android:title="2.3">
</item>
<item android:id="#+menu/m2_4"
android:title="2.4">
</item>
<item android:id="#+menu/m2_5"
android:title="2.5">
</item>
<item android:id="#+menu/Options"
android:title="2.6">
</item>
</menu>
and menu_3 :
<?xml version="1.0" encoding="UTF-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+menu/m3_1"
android:title="3.1">
</item>
<item android:id="#+menu/m3_2"
android:title="3.2">
</item>
<item android:id="#+menu/m3_3"
android:title="3.3">
</item>
<item android:id="#+menu/m1_4"
android:title="3.4">
</item>
<item android:id="#+menu/Options"
android:title="3.5">
</item>
</menu>
Related
I tried
#Override
public boolean onCreateOptionsMenu(Menu menu) {
Log.v(
this.getClass().getName() + "!!!",
new Exception().getStackTrace()[0].getMethodName()
);
MenuItem m_item = (MenuItem)menu.findItem(R.id.action_settings);
if(m_item != null)
m_item.setTitle("Back to test");
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.settings, menu);
return true;
}
but it always gets null.And also,onCreate seems to have it as null as well. Is there a function that i can modify the text on it during runtime??? And if so, is there an easy way to find it?
You should add items in the menu xml. You can find it on the folder res/menu. There you have all the menus available for inflation.
I suppose that you have only one. This is how it could look with added options:
<?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/searchMain"
android:icon="#drawable/ic_action_search"
app:showAsAction="ifRoom|withText"
android:title="Search"/>
<item
android:id="#+id/searchBarcodeScan"
android:icon="#drawable/ic_launcher"
app:showAsAction="always|withText"
android:title="Scanner"/>
<item
android:id="#+id/seeList"
android:icon="#drawable/ic_launcher"
app:showAsAction="ifRoom|withText"
android:title="See list"/>
<item
android:id="#+id/settings"
android:icon="#drawable/ic_settings"
app:showAsAction="ifRoom|withText"
android:title="Settings"/>
</menu>
Then in your activity you can react to the option selected by overriding this method and doing things inside it:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.searchMain:
doSomething();
return true;
case R.id.searchBarcodeScan:
doSomething2();
return true;
case R.id.seeList:
doSomething3();
return true;
case R.id.settings:
doSomething4();
return true;
}
return super.onOptionsItemSelected(item);
}
EDIT
In order to change menus in runtime, you should call the method invalidateOptionsMenu(). This method will force the recreation of the menu and this time onPrepareOptionsMenu method will be called. You should override it in your Activity this way:
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
if(someCondition){
getMenuInflater().inflate(R.menu.main_menu, menu);
}
else if(someOtherCondition){
getMenuInflater().inflate(R.menu.other_menu, menu);
}
return true;
}
Instead of
getMenuInflater().inflate(R.menu.settings, menu);
do something like:
getMenuInflater().inflate(R.menu.menu_custom, menu);
where res/menu/menu_custom.xml is something like:
<?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_search"
android:icon="#drawable/ic_action_search"
android:title="#string/search"/>
<item android:id="#+id/menu_settings"
android:icon="#drawable/ic_action_settings"
android:title="#string/settings" />
</menu>
This will give you two items in the dropdown. It looks like your res/menu/settings.xml only has one item in it.
![Layout Look like this][1]
[1]strong text: http://i.stack.imgur.com/CIsz8.png
I am trying to create a menu, but I am unable to see the menu.i am able to see menu in fragments properly. but cannot see in the sherlockfragmentactivity that is my main frame for fragment.
when i click on menu they doesn't take any action.
menu code
<group android:id="#+id/dashbardmenu">
<item
android:id="#+id/abc"
android:title="ABC">
</item>
<item
android:id="#+id/setting"
android:title="Setting">
</item>
</group>
<group android:id="#+id/fragmentmenu" >
<item
android:id="#+id/form"
android:icon="#drawable/ic_send"
android:showAsAction="ifRoom"
android:title="Form">
</item>
<item
android:id="#+id/resetform"
android:title="Reset Form">
</item>
</group>
im using visibility & invisibility for particular file.
java code
1st way
public boolean onCreateOptionaMenu(Menu menu ){
MenuInflater inflater = this.getSupportMenuInflater();
inflater.inflate(R.menu.activity, menu);
menu.setGroupVisible(R.id.fragmentmenu, false);
return super.onCreateOptionsMenu(menu);
}
2nd way
public boolean onCreateOptionaMenu(Menu menu,MenuInflater inflater ){
inflater.inflate(R.menu.activity, menu);
menu.setGroupVisible(R.id.fragmentmenu, false);
return true;
}
public boolean onOptionsItemSelected(MenuItem item){
super.onOptionsItemSelected((MenuItem)item);
switch (item.getItemId()){
case R.id.abc:
//Some action
case R.id.setting:
//Some action
default:
return false;
}
}
public boolean onOptionsItemSelected(MenuItem item){
super.onOptionsItemSelected((MenuItem)item);
switch (item.getItemId()){
case R.id.abc:
//Some action
case R.id.setting:
//Some action
default:
return true;
}
}
Where is my Mistake Anyone help me???
Did you call this?
setHasOptionsMenu(true);
Also you have a typo - method name is onCreateOptionsMenu but you have twice onCreateOptionaMenu
I'm trying to highlight menu item title when it is selected in action bar and display its corresponding view in a fragment below. Fragment loading is working good but I'm not able to style menu items when they are clicked.
What I would like to have is something like below mentioned methods-
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// item.setSiblingsStyle(R.style.passive_menu_item);
// item.setStyle(R.style.active_menu_item);
}
Is it possible to style menu title in "onOptionsItemSelected" method? Please help !
You could try to use selector definition:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
<item android:state_pressed="true" android:color="#color/blue_light"/> <!-- pressed -->
<item android:state_enabled="false" android:color="#color/grey_cloud"/> <!-- focused -->
<item android:color="#color/black"/> <!-- default -->
</selector>
I've figured using just text is not a good way. So I decide to add icons and use state of items to toggle by maintaining few variables. Here is an implementation:
private current_selected_menu;
private main_menu;
public void updateMenuState(){
if (main_menu==null){
return;
}
int sz = main_menu.size();
for(int i=0;i<sz;i++){
if(main_menu.getItem(i).getItemId()==current_selected_menu){
main_menu.getItem(i).setEnabled(false);
}
else{
main_menu.getItem(i).setEnabled(true);
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.sample_menu, menu);
current_selected_menu = menu.getItem(0).getItemId(); // I'm using first item as enabled by default
main_menu = menu;
int sz = menu.size();
for(int i=0;i<sz;i++){
if(menu.getItem(i).getItemId()==current_selected_menu){
menu.getItem(i).setEnabled(false);
}
else{
menu.getItem(i).setEnabled(true);
}
}
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item1:
// Do something
current_selected_menu = item.getItemId();
updateMenuState();
return true;
case R.id.item2:
// Do something
current_selected_menu = item.getItemId();
updateMenuState();
return true;
default:
// Do Something
return super.onOptionsItemSelected(item);
}
}
As suggested by Xingchen, One can use selectors to define multiple icons. Below is a sample implementation:
icon_selector.xml file in res/drawable:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/icon_passive" android:state_enabled="false"/>
<item android:drawable="#drawable/icon_active" android:state_enabled="true"/>
</selector>
Note: icon_passive.png and icon_active.png are two image files used as icons.
sample_menu.xml file in res/menu:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/menu1" android:icon="#drawable/icon_selector" android:title="menu1" android:showAsAction="always|withText" android:visible="true"></item>
<item android:id="#+id/menu2" android:icon="#drawable/icon_selector" android:title="menu2" android:showAsAction="always|withText" android:visible="true"></item>
<item android:id="#+id/menu3" android:icon="#drawable/icon_selector" android:title="menu3" android:showAsAction="always|withText" android:visible="true"></item>
</menu>
I feel there could be better ways than above mentioned. I'll keep this open. Please feel free to suggest better solutions or better practices : )
I am new to android and stuck at the point where i have to detect clicks on submenus that are defined in XML file
my XML file is :
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/ccard_menu1"
android:title="Select from Profile?"
></item>
<item android:id="#+id/ccard_menu2"
android:title="Add Field"
>
<menu >
<item android:id="#+id/submenu1"
android:title="Add Products"
></item>
<item android:id="#+id/submenu2"
android:title="Add Clients"
></item>
<item android:id="#+id/submenu3"
android:title="Add a Custom Field">s</item>
</menu>
</item>
</menu>
how do i detect clicks on "submenu 1,2,3" in onOptionsItemSelected method?
how do i have to structure the switch case?
I you are looking for something like this:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.your_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.submenu1:
// do something
return true;
case R.id.submenu2:
//do something else
return true;
// etc..
default:
return super.onOptionsItemSelected(item);
}
}
Please correct me if I am mistaken.
I feel this may be a stupid question but I have no idea what to do.
I have a menu which works correctly. One of the items in the menu: "Search" brings up a submenu with different items like "Restaurant", "Cafe", etc.
Below is the XML code for creating the menu and sub menu:
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/new_entry"
android:title="#string/new_entry"
android:icon="#drawable/add_new">
</item>
<item android:id="#+id/search"
android:title="#string/search"
android:icon="#drawable/search">
<menu>
<item android:id="#+id/five"
android:title="#string/five">
</item>
<item android:id="#+id/ten"
android:title="#string/ten">
</item>
<item android:id="#+id/fifteen"
android:title="#string/fifteen">
</item>
<item android:id="#+id/restaurant"
android:title="#string/restaurant">
</item>
<item android:id="#+id/cafe"
android:title="#string/cafe">
</item>
<item android:id="#+id/sandwich"
android:title="#string/sandwich">
</item>
</menu>
</item>
<item android:id="#+id/info"
android:title="#string/info_short"
android:icon="#drawable/info">
</item>
Then in my Activity Class I have:
// Initialise Menu.
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_services, menu);
return true;
}
and:
// Create cases for each menu selection.
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.new_entry:
createFood();
return true;
case R.id.search:
return true;
case R.id.cafe:
Log.d(TAG, "In Cafe SubMenu");
Toast.makeText(getApplicationContext(), TAG, Toast.LENGTH_SHORT);
return true;
case R.id.info:
info();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Each case in "onOptionsItemSelected" does what it is supposed to do, except "case R.id.cafe:" which is the submenu. Here it should post to the LogCat and a Toast for testing but does neither.
What am I missing?
Thanks
I have tried your code and it is working perfectly. Only the Toast is not displaying when I select 'cafe'. That is because, you did not call show() in your code. Your code is
Toast.makeText(getApplicationContext(), TAG, Toast.LENGTH_SHORT);
to show the toast on run time it should call as follows
Toast.makeText(getApplicationContext(), TAG, Toast.LENGTH_SHORT).show();
:)
I think you should remove following lines:
case R.id.search:
return true;