Couldn't resolve menu item onClick handler - android

Im stuck and just exhausted, what am I doing wrong here and what do I need to do to get it to work right? Thanks
API 11.
I setup a item in menu.xml:
<item android:id="#+id/action_add_shindig"
**android:onClick="showCamera"**
android:icon="#drawable/shindig_new"
android:title="#string/shindig_new"
android:showAsAction="ifRoom" />
And in mainActivity I added a method to fire off an intent for the camera in another Activity.
/**
* Method to handle launching the Camera view activity.
* #param view
*/
public void showCamera(View view) {
}
But I get this error:
Couldn't resolve menu item onClick handler showCamera in class com.shindiggy.shindiggy.MainActivity

I resolved it by changing the method to onCameraClick(MenuItem item) and updating the onClick to reflect its name "onCameraClick".

It seems you already solved it, but this is something that has troubled me and is definitely something you would like to read the answer to in the actual documentation. (Just to make sure whatever fix you come up with works on all phones - not just your own...)
Look here: https://developer.android.com/guide/topics/resources/menu-resource#item-element
The android:onClick property of a item in the menu needs a public method with MenuItem as its parameter.
Note that this is different from, say, a Button!
http://developer.android.com/reference/android/widget/Button.html
http://developer.android.com/reference/android/R.attr.html#onClick
Here, a method taking View as its parameter is needed.

I don't believe menuItem has an onClick(). Use onOptionsItemSelected instead. Use themenuItemid` to know which item was clicked.
Menu Docs
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.action_add_shindig:
// run your showCamera code or call that method
return true;
Handling click events
That is for an OptionsMenu but it also discusses ContextMenus

dont use OnClick Method .
use if statement in Method below:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
else if (id==R.id.action_other)
{
Toast toast=Toast.makeText(this, "Other Clicked.", Toast.LENGTH_LONG);
toast.show();
}
else if (id==R.id.action_Exit)
{
finish();
}
return super.onOptionsItemSelected(item);
}

According to Android Doc - https://developer.android.com/guide/topics/resources/menu-resource#item-element
android:onClick
Method name. The method to call when this menu item is
clicked. The method must be declared in the activity as public and
accept a MenuItem as its only parameter, which indicates the item
clicked. This method takes precedence over the standard callback to
onOptionsItemSelected(). See the example at the bottom.
Warning: If
you obfuscate your code using ProGuard (or a similar tool), be sure to
exclude the method you specify in this attribute from renaming,
because it can break the functionality.
Introduced in API Level 11.

Related

What does return super.onOptionsItemSelected(item) do? [duplicate]

I am new to android. I know this question have been asked before but, i am still confuse . What this method does when returning them inside my onCreateOptionMenu() and onOptionItemSelected()
Can any one help me what effect i will have
1)if i return true
2)if i return false
3)What will happen when i return super.onCreateOptionMenu() and super.onOptionItemSelected
Can anyone please explain me this with good example. I am still confuse.
Ok, let's first see the two methods of your interest
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
if return true ==>>> It means you want to see the option menu which you have inflated.
if return false ==>>> you do not want to show it
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
// Activate the navigation drawer toggle
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
As per documentation
true --> Event Consumed now It should not be forwarded for other event
false --> Forward for other to consume
This Boolean return type actually benefits when we are working with multiple fragments and every fragment has their own Option menu and Overriding of OnOptionItemSelected(Mainly in tablet design)
In this case android trace every fragments OnOptionItemSelected method so to avoid that
a) If any fragment is consuming event in onOptionsItemSelected() so return "true" else return "false"
b) If We return false then It will trace other connected fragment's (onOptionsItemSelected)
method until it ends all fragment or Somebody consumes It.
And your 3rd answer is as KrishnaJ written
super.onCreateOptionMenu() and super.onOptionItemSelected
If you write this then It will first call your parent class this method If you extend any class in this class.It will work as parent class if Methods are in parent class too.
Ok. I got you question:
Que 1 :
What this method does when returning them inside my onCreateOptionMenu() and onOptionItemSelected()
Ans :
onCreateOptionMenu() used for inflate menu in action bar.
onOptionItemSelected() used for capture onclick of that menus
Que 2 :
if i return true or false
Ans :
ref !!! you should return true if you have inflated menu in that file or your defined menu is clicked. else u should return false. so compiler will find for men or menu item in other page.
eg. you have one activity and two fragment, then if menu or menu item not find in activity then compiler will find it in fragment. if you return true then no further search.
Que 3 :
why to use super ?
Ans :
so compiler get to know that in this file there is no user defined menu or item value.
onCreateOptionMenu() method used to create an option menu.
onOptionsItemSelected() method used to handling the event of option menu i.e. which menu action is triggered and what should be the outcome of that action etc.
I like to add your 3rd question answer in answer of Dnyanesh
super.onCreateOptionMenu() and super.onOptionItemSelected
If you write this then It will first call your parent class this method If you extend any class in this class.It will work as parent class if Methods are in parent class too.

Have Up button act the same as android back button

My android application has the following activity flow
Listing -> Buy -> Sell
From the listing when an item is clicked/selected an id is passed to buy to pull the relevant data from the server. If a user owns a certain item there will be a sell option as well from the buy screen (which doubles as an overview of said item).
The problem I am facing is that when you are on the sell screen and press the android back button you are taken back to the buy screen in it's original state, however when you click the back arrow (up) from the activity in the toolbar, it seems that it is actually trying to launch a new activity and throws an exception (since the activity cannot know what the id was). The buy activity is listed as a parent to the sell activity in the manifest.
I need to somehow make the up button to act the same as the back button on this particular activity, or at least pass the id back somehow.
Any suggestions would be appreciated.
If you're using an ActionBar (either platform or AppCompat) override the following method in the activity from which you wish to go back.
#Override
public boolean onOptionsItemSelected(#NonNull final MenuItem item) {
final int id = item.getItemId();
if (id == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
This should be safe to use in a simple navigation hierarchy such as yours.
Just yesterday i did this for my app. This is what I did:
In manifest file I removed
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.app.MainActivity" />
that was part of my DetailsActivity.
In the DetailsActivity I added this line to onCreate
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
and in onOptionsItemSelected() method I added these lines
if (item.getItemId() == android.R.id.home) {
onBackPressed();
}
Not sure if it is the best way to handle this but oh well it works :)
In your Activity, onOptionsItemSelected() method get the clicked item id, if the id is android.R.id.home then just finish() current activity.
Try this:
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch(item.getItemId())
{
case android.R.id.home:
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}

What does this method do super.onCreateOptionMenu() and super.onOptionsItemSelected(item)

I am new to android. I know this question have been asked before but, i am still confuse . What this method does when returning them inside my onCreateOptionMenu() and onOptionItemSelected()
Can any one help me what effect i will have
1)if i return true
2)if i return false
3)What will happen when i return super.onCreateOptionMenu() and super.onOptionItemSelected
Can anyone please explain me this with good example. I am still confuse.
Ok, let's first see the two methods of your interest
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
if return true ==>>> It means you want to see the option menu which you have inflated.
if return false ==>>> you do not want to show it
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
// Activate the navigation drawer toggle
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
As per documentation
true --> Event Consumed now It should not be forwarded for other event
false --> Forward for other to consume
This Boolean return type actually benefits when we are working with multiple fragments and every fragment has their own Option menu and Overriding of OnOptionItemSelected(Mainly in tablet design)
In this case android trace every fragments OnOptionItemSelected method so to avoid that
a) If any fragment is consuming event in onOptionsItemSelected() so return "true" else return "false"
b) If We return false then It will trace other connected fragment's (onOptionsItemSelected)
method until it ends all fragment or Somebody consumes It.
And your 3rd answer is as KrishnaJ written
super.onCreateOptionMenu() and super.onOptionItemSelected
If you write this then It will first call your parent class this method If you extend any class in this class.It will work as parent class if Methods are in parent class too.
Ok. I got you question:
Que 1 :
What this method does when returning them inside my onCreateOptionMenu() and onOptionItemSelected()
Ans :
onCreateOptionMenu() used for inflate menu in action bar.
onOptionItemSelected() used for capture onclick of that menus
Que 2 :
if i return true or false
Ans :
ref !!! you should return true if you have inflated menu in that file or your defined menu is clicked. else u should return false. so compiler will find for men or menu item in other page.
eg. you have one activity and two fragment, then if menu or menu item not find in activity then compiler will find it in fragment. if you return true then no further search.
Que 3 :
why to use super ?
Ans :
so compiler get to know that in this file there is no user defined menu or item value.
onCreateOptionMenu() method used to create an option menu.
onOptionsItemSelected() method used to handling the event of option menu i.e. which menu action is triggered and what should be the outcome of that action etc.
I like to add your 3rd question answer in answer of Dnyanesh
super.onCreateOptionMenu() and super.onOptionItemSelected
If you write this then It will first call your parent class this method If you extend any class in this class.It will work as parent class if Methods are in parent class too.

Cannot invoke getItemId() on the primitive type boolean

I am new to android development and I have searched most of Menu option examples on the web. I am trying to handle a simple click event using "getItemId" and I get the following error :
Cannot invoke getItemId() on the primitive type boolean.
Here's the code :
public boolean onOptionsItemSelected(MenuItem menu)
{
// Handle Selection of Menu Items
switch (item.getItemId())
{
case(R.id.refresh):Toast.makeText(this, "Refresh", Toast.LENGTH_LONG).show();
break;
case(R.id.info):Toast.makeText(this, "Info", Toast.LENGTH_LONG).show();
break;
}
return true;
Thanks in advance for your help !
not this:
switch (item.getItemId())
but:
switch(menu.getItemId())
The reason this fails is just as the error says. Booleans are primitives, not objects. I am assuming somewhere above this excerpt is the line boolean item;. If you did a switch on a boolean the only possible cases would be true and false.
Instead of item, use menu - this is the menuItem passed to this method as a parameter.
And unfortunately, I don't know if *.getItemId() will work on a menuItem. I haven't tried it. If it doesn't, let me know, and I'll help ya find another way.

How to handle onContextItemSelected in a multi fragment activity?

I'm currently trying to adapt my application to use the "Compatibility Libraries for Android v4" to provide the benefits of the usage of fragments even to Android 1.6 users.
The implementation of a context menu seems to be tricky:
The main activity of the application
is extending the FragmentActivity
class.
The fragments are all based on one
class which extends the Fragment class.
The fragment class is calling
registerForContextMenu() in its onCreateView() method and overrides the methods
onCreateContextMenu() and onContextItemSelected().
For onCreateContextMenu() this works pretty well. The context menu is inflated from a resource file and slightly modified based on the selected item (which is based on a listView... even if the fragment is not an ListFragment).
The problem occurs when a context menu entry is selected.
onContextItemSelected() is called for all currently existing fragments starting with the first added one.
In my case the fragments are used to show the content of a folder structure. When the context menu of a subfolder fragment is opened and a menu item is selected, onContextItemSelected() is first called on the upper levels (depending on how many fragments are allowed/visible in this moment).
Right now, I use a workaround by a field on activity level which holds the tag of last fragment calling its onCreateContextMenu(). This way I can call "return super.onContextItemSelected(item)" in the begin of onContextItemSelected() when the stored tag is not the same as getTag().
But this approach looks a bit dirty to me.
Why is onContextItemSelected() called on all fragments? and not just one the one that was calling onCreateContextMenu()?
What is the most elegant way to handle this?
I'll post an answer even though you found a workaround because I just dealt with a similar issue. When you inflate the context menu for a specific fragment, assign each menu item a groupId that is unique to the fragment. Then test for the groupId in 'onContextItemSelected.' For Example:
public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) {
menu.add(UNIQUE_FRAGMENT_GROUP_ID, MENU_OPTION_1, 0, R.string.src1);
menu.add(UNIQUE_FRAGMENT_GROUP_ID, MENU_OPTION_2, 0, R.string.src2);
}
public boolean onContextItemSelected(MenuItem item) {
//only this fragment's context menus have group ID of -1
if (item.getGroupId() == UNIQUE_FRAGMENT_GROUP_ID) {
switch(item.getItemId()) {
case MENU_OPTION_1: doSomething(); break;
case MENU_OPTION_2: doSomethingElse(); break;
}
}
This way all of your fragments will still receive calls to 'onContextItemSelected,' but only the correct one will respond, thus avoiding the need to write activity-level code. I assume a modified version of this technique could work even though you aren't using 'menu.add(...)'
Another one solution:
#Override
public boolean onContextItemSelected(MenuItem item) {
if (getUserVisibleHint()) {
// context menu logic
return true;
}
return false;
}
Based upon this patch from Jake Wharton.
I liked the simple solution by Sergei G (based on Jake Wharton fix), but inverted because it is easier to add to several fragments:
public boolean onContextItemSelected(android.view.MenuItem item)
{
if( getUserVisibleHint() == false )
{
return false;
}
// The rest of your onConextItemSelect code
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
}
After that, the code same as it was before.
I found out a very easy solution. As onCreateContextMenu() is called every time the ContextMenu is created I set a boolean variable to true.
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.film_menu, menu);
bMenu=true;
}
The only other thing I have to do is ask for that variable OnContextItemSelected()
public boolean onContextItemSelected(MenuItem item) {
if (bMenu) {
bMenu=false;
if (item.getItemId() == R.id.filmProperties) {
///Your code
return true;
} else {
return super.onContextItemSelected(item);
}
} else {
return super.onContextItemSelected(item);
}
}
That's it.
I found an alternative. It does not change anything on my problem above, but it makes it pointless.
I have remove the context menu completely from my application. Instead I capture the longclick on a list item and change the visible buttons of the action bar in this moment.
From the user point of view this is much more tablet like as a context menu.
In backward compatible applications the actionbar does not exist. So I've decided to build my own (kind of toolbar on top) for the devices pre Honeycomb.
If you would like to stay with the context menu, I did not find a better solution as the workaround I've mentioned above.
In my first fragment, i have set all my menu id > 5000 so, as first line of code of onContextItemSelected of first fragment i have
if (item.getItemId() < 5000) return false;
and the second fragment will be invoked.
If you are using adapters with listviews in your fragment this might help.
public boolean onContextItemSelected(final MenuItem item) {
final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
//Check if the context menu call came from the list in this fragment (needed for support for multiple fragments in one screen)
if (info.targetView.getParent() != getView().findViewById(android.R.id.list))
return super.onContextItemSelected(item);
//Handle context menu item call
switch (item.getItemId()) {
...
}
}
Just change
#Override
public boolean onContextItemSelected(MenuItem item) {
return true;
}
to
#Override
public boolean onContextItemSelected(MenuItem item) {
return super.onContextItemSelected(item);
}
and will work great!!!
IMHO we may just check if target view is child of fragment listview. It is very simple and work for me well. I just added to all my fragments:if (getListView.getPositionForView(info.targetView) == -1)
return false when migrate from older API
This is example from one of my parent fragments. This is Scala, but I hope you got an idea.
#Loggable
override def onContextItemSelected(menuItem: MenuItem): Boolean = {
for {
filterBlock <- TabContent.filterBlock
optionBlock <- TabContent.optionBlock
environmentBlock <- TabContent.environmentBlock
componentBlock <- TabContent.componentBlock
} yield menuItem.getMenuInfo match {
case info: AdapterContextMenuInfo =>
if (getListView.getPositionForView(info.targetView) == -1)
return false
TabContent.adapter.getItem(info.position) match {
case item: FilterBlock.Item =>
filterBlock.onContextItemSelected(menuItem, item)
case item: OptionBlock.Item =>
optionBlock.onContextItemSelected(menuItem, item)
case item: EnvironmentBlock.Item =>
environmentBlock.onContextItemSelected(menuItem, item)
case item: ComponentBlock.Item =>
componentBlock.onContextItemSelected(menuItem, item)
case item =>
log.debug("skip unknown context menu item " + info.targetView)
false
}
case info =>
log.fatal("unsupported menu info " + info)
false
}
} getOrElse false
P.S. If you trace calls of onContextItemSelected(...) you may notify that super.onContextItemSelected(item) return always false. Valid onContextItemSelected invoked AFTER, not WITHIN. So super.onContextItemSelected(item) is useless and I replaced it with false.
I found an easier solution than the exposed:
public boolean onContextItemSelected(MenuItem item) {
ListView yourList = (ListView) (ListView) getView().findViewById(R.id.yourList);
if (!yourList.hasFocus())
return false;
switch(item.getItemId()) {
...
}
}
In the method changed return true; to return super.onContextItemSelected(item); in my onContextItemSelected() override and everything started working.

Categories

Resources