I'm supporting down to API 15 in my app, and I'm getting a crash for those users when I try to get the searchView from my menu.
Below is my code:
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
MenuItem menuItem = menu.getItem(0);
searchView = (SearchView)menuItem.getActionView();
searchView.setIconifiedByDefault(false);
searchView.setQuery("", true);
menuItem.expandActionView();
}
I'm getting a NullPointerException on this line:
searchView.setIconifiedByDefault(false);
because the searchView is null. This works perfectly fine on devices at API 16 and above. Has anyone run into this issue before?
While inflating a layout usually causes an immediate crash if there is a problem, inflating a menu resource does not. If there is some problem, a stack trace is logged, but otherwise the exception is handled, and so execution continues. It is only some time later that we realize that something did not work, when things break later on.
Custom action bar items (actionLayout, actionViewClass, actionProvider) are especially prone to this. If there is some problem loading any of those -- such as the actionViewClass not implementing the proper constructor -- we only find out about it when we try to retrieve the custom item and get null back. The solution is to rummage through LogCat and look for the stack trace associated with the handled exception, to see what really went wrong.
In an API level-dependent case, like this one, the most likely scenario would be where initialization of custom action item refers to a method that does not exist on the older version of Android, and therefore fails.
I also had just the same problem as you and came to this stackoverflow question. With some struggle, I have found the heart of this problem and a solution.
In API15, during app's initialization, only onCreateOptionsMenu is called but onPrepareOptionsMenu is not.
In API16 and later, onPrepareOptionsMenu is called right after onCreateOptionsMenu.
So my solution is to call onPrepareOptionsMenu at the ending point of onCreateOptionsMenu:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
(...)
if (Build.VERSION.SDK_INT < 16) {
onPrepareOptionsMenu(menu);
}
}
Related
I am developing an Android app. Firstly, let me tell you that I am not professional. What I am doing now is I am adding submenu to menu depending on a condition. But I need to do it very often in my app. But my problem is I added a submenu to the menu as first time.
But second time when I update menu depending on condition, existing submenu is not removed and new submenu is appended to navigation drawer. How can I remove submenu that is programmatically added to menu? Why my code is not removing it?
Here is my code
public void updateAuthUI()
{
isLoggedIn = tempStorage.getBoolean(getResources().getString(R.string.pref_is_logged_in),false);
Menu menu = leftDrawer.getMenu();
menu.removeItem(getResources().getInteger(R.integer.logout_item_id));
menu.removeItem(getResources().getInteger(R.integer.login_item_id));
menu.removeItem(getResources().getInteger(R.integer.register_item_id));
SubMenu authSubMenu = menu.addSubMenu("Auth");
if(isLoggedIn)
{
authSubMenu.add(1,getResources().getInteger(R.integer.logout_item_id),99,"Sign out");
}
else{
authSubMenu.add(1,getResources().getInteger(R.integer.register_item_id),97,"Register");
authSubMenu.add(1,getResources().getInteger(R.integer.login_item_id),98,"Sign in").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
openLoginActivity();
item.setChecked(true);
return true;
}
});
}
}
Here is the screenshot of my problem
As you can see Auth submenu is appended without removing existing one.
Try
authSubMenu.clear();
before your first
authSubMenu.add();
I just used SubMenu.clear() in an Android app where I was using a third-party library, and I needed to clear out an unwanted submenu from the action bar. (I actually wanted to remove the submenu completely, and this was the only way I could find to do it. It seemed to work.)
That's different from your situation, where authSubMenu is a menu you just added via menu.addSubMenu("Auth"), so you would expect it to be empty. But, as you've seen, it apparently isn't empty: rather, addSubMenu("Auth") returns the existing submenu of that title. (I can't find documentation to that effect; I'm just going by the results you've reported.)
If that really is the case, as it appears to be, then authSubMenu.clear() will remove all existing items from the submenu.
As #slymm said in a comment you can remove all menu and submenu items using
navigationView.getMenu().clear();
This can be used to remove submenu (and menu elements) and then recreate them with the new required items
I'm trying to implement search into my app and have trouble understanding the difference between these two methods. Why is it that we have to define a search configuration (described here: http://developer.android.com/guide/topics/search/search-dialog.html), add a bunch of meta-data to the manifest, and have a separate activity just for search, when we can treat it like any other TextView, grab it's text, and query the database with that? Is there any advantage to the former method, or any disadvantage to the latter? In my mind directly getting the text and doing my own stuff off of that seems a lot easier, especially when after dealing with the search interface I'll still need to get the query from the intent and perform the actual search with that. Am I missing something here? Thanks!
Here's what I mean by directly getting the search query (without using the search interface):
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
MenuItem search = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) search.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
// Do stuff with query
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
// Do stuff with newText
return true;
}
});
}
You have few advantages in working with the "standard" searching feature:
The search will look as the user is use to have is "search" boxes on any device. If you design something this will be for all devices. I love to be in the "standard" because in this way for the users is very simple to use it and compatibility over devices is much wider
Activity Life Cycle : see here. This a huge advantage.
If the Look & Feel fit's with your design you have a lot of other features that are available and checked and working and almost bugles.
Daniel
Getting an error and not sure why.
I'm trying to get icons beside the icon of my app and the title of my app at the top of the screen.
I've tried to implement the onCreateOptionsMenu method however I'm getting this error.
'The method inflate(int, Menu) in the type MenuInflater is not applicable for the arguments (int, Menu).
This is the code I tried
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.testmenu, menu);
return true;
}
I've read that sometimes it can be related to the theme or the SDK version you're trying to target however I've checked both and they're fine. Version 11 is the min and I have the Holo.Light theme currently
Are you using ActionBarSherlock? If so, you have to use
getSupportMenuInflater().inflate(R.menu.testmenu, menu);
i need to be able to change the options menu (the one that is shown upon pressing the menu button) on android , so that on one case (for example upon a button being pressed) , it will use a specific menu resource (XML file as in /res/menu/... ) for the menu , and on another case , use a different XML file.
so far i've seen only examples of doing it without xml (example here and here) , and they worked fine , but i want to be able to change the entire menu on some cases.
i've tried to modify the solutions i've found , but none of my trials worked.
if possible , i would prefer to re-create the menu only if the it needs to be updated with a menu resource that is different from the current one.
please help me.
If you want to change the Options Menu any time after it's first created, you must override the onPrepareOptionsMenu() method.
public boolean onPrepareOptionsMenu (Menu menu) {
menu.clear();
if (CASE_1 == 0) {
CASE_1 = 1;
getMenuInflater().inflate(R.menu.secondmenu, menu);
}
else {
CASE_1 = 0;
getMenuInflater().inflate(R.menu.firstmenu, menu);
}
return super.onPrepareOptionsMenu(menu);
}
where CASE_1 refer to the which menu you want to display depending on your requirement.
I realise this is a specific problem however I feel like others who are dealing with compatibility must have dealt with this.
As the user swipes through various fragments in the ViewPager I would also like the actionBar menu items to change. I am not sure if this is easily doable for the compatibility actionbar, any direction or help would be extremely appreciated. I am changing the title simply via setTitle() since the ActionBarHelper handles this however i cant find anything for updating the menu items. I tried the following but it fails..
public void setMenuDynamically(int resId){
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(resId, menu);
}
Looking through the code it seems there should be an easy/obvious way to get a handle to the SimpleMenu and add an item and set its icon.
Thanks in advance ( I am hoping the google boys are reading this as the android developers Google+ suggests)
Ok well please let me know if I suck as describing things or if there just is not much knowledge on this topic. If the first I am really sorry guys. Regardless I seemed to get this to work but am unsure if this is the correct way.
AcitonBarHelper
public void updateMenu(MenuItem item) {
}
ActionBarHelperBase (for 2.2 - 3.0 devices )
#Override
public void updateMenu(MenuItem item){
addActionItemCompatFromMenuItem(item);
}
And create similar methods for honeycomb and ICS
finally i have a listener for page changing and in that listener i call...
public void setMenuDynamically(int resId, String title){
MenuItem item = menu.add(title);
item.setIcon(resId);
getActionBarHelper().updateMenu(item);
MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
}
I am not sure if the MenuItemCompat is necessary but I included it nonetheless. Everything seems to work great for 2.2 at least. I will most likely have to make changes in the Overrides but I can handle myself from here.