I have this recurring issue with the onCreateOptionsMenu method. I have it set up so it enables or disables options depending on the value of some SharedPreferences, but for some reason the first time you open the menu it doesn't work as it should, the options that should be disabled are enabled and the other way around. If I close it and reopen it, it works fine.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
menuConfig(menu);
return true;
}
#Override
public boolean onPrepareOptionsMenu (Menu menu) {
menuConfig(menu);
return true;
}
public void menuConfig(Menu menu){
menu.getItem(getResources().getInteger(R.integer.MENU_ABOUT)).setEnabled(true);
if (preferences.getBoolean(getString(R.string.PREFS_STARTED), false)){
menu.getItem(getResources().getInteger(R.integer.MENU_START)).setEnabled(false);
menu.getItem(getResources().getInteger(R.integer.MENU_STOP)).setEnabled(true);
}else{
menu.getItem(getResources().getInteger(R.integer.MENU_START)).setEnabled(true);
menu.getItem(getResources().getInteger(R.integer.MENU_STOP)).setEnabled(false);
}
if(!preferences.getBoolean(getString(R.string.PREFS_STARTED),false) && preferences.getBoolean(getString(R.string.PREFS_FILES_CREATED),false)){
menu.getItem(getResources().getInteger(R.integer.MENU_DELETE)).setEnabled(true);
menu.getItem(getResources().getInteger(R.integer.MENU_SET_ID)).setEnabled(true);
}
else{
menu.getItem(getResources().getInteger(R.integer.MENU_DELETE)).setEnabled(false);
menu.getItem(getResources().getInteger(R.integer.MENU_SET_ID)).setEnabled(false);
}
}
These two pics are taken subsequently with a few seconds between each menu key press.
The first one is wrong, it should look like the second one.
I fixed it by changing the default value returned by the queries to the SharedPreferences object but I have no idea of what is actually happening.
Related
I want to disable certain features of my app while the user is entering text for a search. The xml for the relevant item in my ActionBar is
<item android:id="#+id/actionbar_search"
android:orderInCategory="1"
android:showAsAction="always|withText|collapseActionView"
android:actionViewClass="android.widget.SearchView"
android:icon="#drawable/earth_2508858_search_en"
android:inputType="textPostalAddress" />
and in the corresponding code that I have at present to cater for the search is
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.action_menu, menu);
MenuItem DestinationTxt = menu.findItem(R.id.actionbar_search);
final SearchView mySearchView = (SearchView)DestinationTxt.getActionView();
mySearchView.setOnQueryTextListener(new OnQueryTextListener() {
#Override
public boolean onQueryTextChange(String newText) { return false; }
#Override
public boolean onQueryTextSubmit(String query) {
//Hide the Keyboard
imm.hideSoftInputFromWindow(mySearchView.getWindowToken(), 0);
// CODE TO DO THE SEARCH
return true;
}
});
}
I've browsed the methods on SearchView, but I didn't see anything that would tell me whether it's active or not. I'm also worried about putting in a boolean state variable to indicate when the text is being typed into the SearchView, in case some behaviour that I haven't catered for occurs (e.g. back button pressed, activity gets suspended), and somehow the state variable gets stale so that the disabled features stay disabled. So I'm looking for a robust way of doing this, all help appreciated :-).
Update. An answer below suggests using the interface OnFocusChangeListener which is implemented by the mySearchView object, and/or the mySearchView.isFocussed() method. Both sounded promising, however I've now tested and neither seem to work. Perhaps their failure has got something to do with the fact that this SearchView is in the ActionBar? In any case, I'm still after a robust solution.
It's right there.
mySearchView.setOnQueryTextListener(new OnQueryTextListener() {
#Override
public boolean onQueryTextChange(String newText) { return false; }
That's where you'll get updates to text changes in the SearchView.
The return value should be as such (documentation):
Returns
false if the SearchView should perform the default action of showing any suggestions if available, true if the action was handled by the listener.
If you want to know if the SearchView has been activated or deactivated, use View.setOnFocusChangeListener(View.OnFocusChangeListener);
public interface OnFocusChangeListener{
public void onFocusChange (View v, boolean hasFocus);
// The boolean will tell you if it's focused or not.
}
Since monitoring the focus didn't work, I looked at the SearchView documentation again. It's a bit convoluted, but it seems like the intended solution to this problem.
If your SearchView is inflated from a menu XML in onCreateOptionsMenu(), then you can add this line:
menu.findItem(/* your SearchView's ID here */).setOnActionExpandListener(
new OnActionExpandListener(){
#Override
public boolean onMenuItemActionCollapse (MenuItem item){
enableInteraction();
return true; // Allow the SearchView to collapse.
}
#Override
public boolean onMenuItemActionExpand(MenuItem item){
disableInteraction();
return true; // Allow the SearchView to expand.
}
}
);
Then enable and disable your Activity's views in enableInteraction() and disableInteraction(), respectively. You should retain the MenuItem in your Activity so you can query it in onResume() like so:
#Override
public void onResume(){
super.onResume();
searchViewMenuItem.isActionViewExpanded() ?
disableInteraction() : enableInteraction();
}
This part might not be needed. The SearchView might automatically get collapsed when the Activity is hidden and stay that way, so you can simply call enableInteraction() in onResume() so your user isn't locked out.
If you just need to reference the state of the SearchView, use
searchViewMenuItem.isActionViewExpanded();
In short, here's my question:
Can option menus (shown in the actionbar) be modified programatically on android 3.0+?
I have a wizard-style activity in which I use a ViewFlipper to switch between views, or steps.
The steps are: 1 -> 2 -> 3. Only the second screen (2) has a menu item, while the others don't. I have tried hanging on to the Menu reference (source) and either removing/adding items or just hiding/showing them.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
this.mMenu = menu;
getMenuInflater().inflate(R.menu.my_menu, menu);
mMenu.getItem(0).setVisible(false);
return super.onCreateOptionsMenu(menu);
}
Switch to the second screen ->
public void showNext(View v) {
if (mVFlipper.getDisplayedChild() < (mVFlipper.getChildCount() - 1)) {
mVFlipper.showNext();
if (mVFlipper.getDisplayedChild() == 1) {
setTitle("Second screen");
mMenu.getItem(0).setVisible(true);
}
}
}
This works fine on 2.2, but fails miserably on 4.1. Starting off with a visible MenuItem and hiding it later works. Starting off with an invisible menu item and showing it later -
There is a bug in Android's MenuItem setVisible that causes problems when turning items back to visible.
In your onCreateOptionsMenu(), add a check to see if the displayed page needs the Menu, if it does, add the MenuItem. Then, call invalidateOptionsMenu() whenever the page changes. That will rebuild the Menu.
I was also struggling with this issue, then I applied a small hack:
menu1.setEnabled(false);
menu1.setTitle("");
Then where you want to visible it again:
menu1.setEnabled(true);
menu1.setTitle("Okay"); //or you can set text according to your given updated values.
Problem fixed by having the MenuItem be visible after onCreateOptionsMenu finishes and then hiding it from a callback called after onCreateOptionsMenu:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
this.mMenu = menu;
getMenuInflater().inflate(R.menu.my_menu, menu);
boolean dummyVal = super.onCreateOptionsMenu(menu);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD_MR1) {
mMenu.getItem(0).setVisible(true);
} else {
mMenu.getItem(0).setVisible(false);
}
return dummyVal;
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
if (mMenu != null) {
mMenu.getItem(0).setVisible(false);
}
}
}
If anyone has this problem, I recommend trying toadzky's suggestion first: calling "invalidateOptionsMenu()".
I have a basic problem where an initially hidden MenuItem is unable to be toggled to visible. As a caveat, I am using ActionBarSherlock, but I wanted to see if anyone knew if this was a known issue of Android or I am doing something terrible before investigating whether this is an issue inside of ABS. Code as follows:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.menu_xml, menu);
mMenuItem = menu.findItem(R.id.menu_item);
mMenuItem.setVisible(false);
return true;
}
// Somewhere elsewhere
// MenuItem is never visible after this line is executed
mMenuItem.setVisible(true);
I have also tried to move the mMenuItem assignment and visibility into a call to onPrepareOptionsMenu but the same behavior is shown.
Thanks!
The problem is you are not telling Android that it needs to update the menu. This drove me nuts for the last hour until I figured out a solution. I don't think it's as apparent on pre-HC because menu items aren't always visible on the screen like they are in HC+.
On your activity, simply call:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
this.invalidateOptionsMenu();
}
That will trigger a call to the onCreateOptionsMenu() event again, so if you're setting the visibility in that function for initialization you'll need to take into account then if you want the option to show or not.
I had the same problem and I found out that setVisible(true) works when there is at least another MenuItem visible. I hope this can be helpful to someone.
I understand this is old question.
But I've solved it by placing inside onPrepareOptionMenu() {...}
private boolean mShowVisible=false;
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.menu_item).setVisible(mShowVisible);
return super.onPrepareOptionsMenu(menu);
}
whenever you want to set visible or not just call it as:
mShowVisible = true; // or false
invalidateOptionMenu();
I found that using a view's post(Runnable) method to setVisible does the trick, so something like...
view.post(new Runnable() {
#Override
public void run() {
menu.findItem(id).setVisible(true);
}
});
I have a custom menu options that I want to disable it from popping up if a button on screen is clicked..
I thought of using this code but it doesnt work:
#Override
public boolean onPrepareOptionsMenu (Menu menu) {
if (Schedule)
menu.getItem(1).setVisible(View.GONE);
return true;
}
Is there a way to prevent the menu button from doing anything? Thanks.
According to the documentation:
You must return true for the menu to be displayed; if you return false it will not be shown.
So I'm guessing this will work:
#Override
public boolean onPrepareOptionsMenu (Menu menu) {
.... Code .....
return !Schedule;
}
That is assuming that you want the menu to display when Schedule is equal to false.
I have been running into some troubles recently and I think I need your help :).
I am currently trying to show a menu on top of a dialog, I know that it could be far easier to launch a new activity yet doing so would compell me to store/pass a lot of data.
I managed to show an optionmenu by writing a custom dialog and rewriting the oncreateOptionMenu method.
My problem is I can't get any listener to these button, I tried to rewrite the onoptionitemselectedmethod but nothing happens.
Ps: my dialog is nearly full screen so i can't see the activity dialog (i didn't find any put on top method)
I would be glad to try any solution you could provide.
Thanks a lot
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(Menu.NONE,0,Menu.NONE,c.getString(R.string.home));
menu.add(Menu.NONE,4,Menu.NONE,c.getString(R.string.report));
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
if(item.getItemId()==0){
getOwnerActivity().startActivity(new Intent(c,Home.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
}
else
if(l>1)
getOwnerActivity().startActivity(new Intent(c,report.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
else
dismiss();
return true;
}
Maybe this little snippet out of my app helps you:
private static final int REFRESH_ID = Menu.FIRST + 1;
public boolean onCreateOptionsMenu(Menu menu) {
boolean result = super.onCreateOptionsMenu(menu);
menu.add(0, REFRESH_ID, 0, R.string.menu_refresh).setIcon(R.drawable.and_refresh);
return result;
}
public boolean onMenuItemSelected(int featureId, MenuItem item) {
switch (item.getItemId()) {
case REFRESH_ID: {
// Do whatever you want here!
return true;
}
}
return super.onMenuItemSelected(featureId, item);
}
As you can see, I've got constants for my menu-items. Those items get the Menu.First + n number as integer. For every item, I count it up. Easier, then change it everytime ;)
And in the onMenuItemSelected you can switch those constants easily.
Hope that helps!