When you create a button, you can assign a listener to capture user actions like clicks.
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//do some stuff
}
});
}
My question is why menu items don't need a listener? All I need is just write
getMenuInflater().inflate(R.menu.main, menu);
inside of
public boolean onCreateOptionsMenu(Menu menu).
and use
public boolean onOptionsItemSelected(MenuItem item)
to define behaviour when an Item is clicked. I didn't see any setListener method. Besides, the main activity class does not implement any Listener. How does a menuItem work?
How does a menuItem work?
So OptionsMenu is build-in widget in Android OS
It works simply said like when you'll click on an item then is immediately called "OnItemSelectedListener" (you don't need to implement it, it's automatic called whenever you'll click on the item). This listener is already implemented. You don't have to implement it and i think you shouldn't and can't.
An onOptionsItemSelected method is called by listener that is called when you'll click on the item.
And what docs exactly say:
This hook is called whenever an item in your options menu is selected.
The default implementation simply returns false to have the normal
processing happen (calling the item's Runnable or sending a message to
its Handler as appropriate). You can use this method for any items for
which you would like to do processing without those other facilities.
Derived classes should call through to the base class for it to
perform the default menu handling.
Related
I'm practising adding menu items and trying to react to menu item clicks. According to the developer's guide, it says:
Tip: Android 3.0 adds the ability for you to define the on-click behavior for a menu item in XML, using the android:onClick attribute. The value for the attribute must be the name of a method defined by the activity using the menu. The method must be public and accept a single MenuItem parameter—when the system calls this method, it passes the menu item selected. For more information and an example, see the Menu Resource document.
However, the sample code in the same page doesn't follow the rule: the methods do not pass the MenuItem parameter. The sample code is:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.new_game:
newGame();
return true;
case R.id.help:
showHelp();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
My question is: Shouldn't method calls be newGame(MenuItem item) and showHelp(MenuItem item), instead of newGame() and showHelp()? When I tested my own, (MenuItem item) argument was needed in fact, otherwise, the app was crashing, even though it compiles correctly.
Any help would be appreciated.
onOptionsItemSelected is the alternative to defining onClick attributes and what is available prior to Android 3.0 (important if you want to be backward compatible). It is simply a different way of providing the same process flow. Of course, onClick has the potential to crash your application on runtime, rather than onOptionsItemSelected not handling a menu item (simply causing it to do nothing).
I'm implementing a actionmode is'm doubts as whether the done button was clicked,
Thanks
You need to use:onActionItemClicked(ActionMode, MenuItem)
Docs
I'm using this approach - set a boolean flag when any action item is clicked (in onActionItemClicked). Then in callback's onDestroyActionMode I check this flag and is it is not set then the done button was tapped. It assumes that you finish action mode in onActionItemClicked.
if the Done button was clicked 。
this method onDestroyActionMode(ActionMode mode) {} will call back .
so you can call your method onSave().
if you can't find this method, you can gooogle find which interface you
need implements.
I use some custom ActionModes in my application. When an action mode is closed, I do some housekeeping, like closing related views, updating changes, etc.. I detect the action mode has been closed in OnDestroyActionMode.
My problem is, when inside of some of my ActionModes, the user may trigger another system actionmode (The text copy/paste/select). In that case, onDestroyActionMode is called and I erroneously asume the user is done with the first actionmode, rather than implement a "stack" functionality, so can I ignore this onDestroyActionMode, let the user edit / cut / etc the text, then reopen the former actionmode when done.
How can I achieve this?
Shedding further light on your situation: prior to honeycomb, longPress on a TextView will yield a popup window with options (like 'Select word', 'Select all', and 'Add "someword" to dictionary') while NOT affecting any existing ActionMode both when shown and when dismissed (by pressing back). So this isn't really a problem pre-honeycomb.
More light regarding HTC Sense: Sense does NOT honour TextView.setCustomSelectionActionModeCallback() because Sense doesn't use an ActionMode for the Text selection feature (and clearly don't care if the rest of the world do!). So this problem has a different smell in that situation (I haven't tested the following solution under Sense, so not sure how it'll behave).
A solution is to create your own custom ActionMode.Callback to replace the OS's one and apply it in setCustomSelectionActionModeCallback() of any TextView and/or EditText you desire (though only if device is running honeycomb or greater). Pass a custom onTextSelectionCABDestroyed callback interface to your custom ActionMode.Callback, call it in the onDestroyActionMode method.
Firstly create an interface and implement it where you want to handle the recreation of your original ActionMode (alternatively you may want to use a bus event with something like Otto):
public interface YourCallbackInterface {
public void onTextSelectionCABDestroyed();
}
and create a new class:
public final class CustomTextSelectionActionModeCallback implements ActionMode.Callback {
WeakReference<YourCallbackinterface> mYourCallbackinterface;
public CustomTextSelectionActionModeCallback(YourCallbackinterface yourCallbackInterface) {
mYourCallbackinterface = new WeakReference<YourCallbackinterface>(yourCallbackInterface);
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return true; //returning true will create the ActionMode
}
#Override
public void onDestroyActionMode(ActionMode mode) {
//this is the magic where we actually capture the destroy event for TextSelectionCAB and can subsequently do things like recreate the ActionMore that TextSelectionCAB greedily destroyed!
mYourCallbackinterface.get().onTextSelectionCABDestroyed();
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
}
And remember to avoid StackOverflowException when recreating an ActionMode from the onDestroyActionMode of an ActionMode, postDelayed a Runnable to a Handler like this I explain here: Reopen ActionMode (or CAB) after onDestroyActionMode is called
Lastly, if you're using ActionBarSherlock, make sure that your CustomTextSelectionActionModeCallback implements android.view.ActionMode.Callback rather than com.actionbarsherlock.view.ActionMode.Callback.
Note: I haven't played with ActionBarCompat so not sure how all this applies there. If someone knows, please post as comment!
I see that it's possible to handle a tap on a icon menù item or by implementing
onOptionsItemSelected
inside the acivity, or by using
onMenuItemClickListener
like onclick listener on a button. When is better to use the fist one method, and when the second one?
Because for my opinion, using an external listener makes more modular the code, but create a new class, but using the first way don't create new class, but makes code less modular...
There are use cases other than the ones outlined below, but I'm putting in the general cases that come up regularly.
onOptionsItemSelected
If you're using Fragments, you may want to use onOptionsItemSelected and consider adding menu items to the Action Bar the way that is described in Adding items to the Action Bar.
What this describes is implementing onCreateOptionsMenu inside your Fragment. To make this happen, you must call setHasOptionsMenu in onCreate.
protected void onCreate(Bundle savedInstanceState) {
this.setHasOptionsMenu(true);
}
Setting this will actually make the Activity call onCreateOptionsMenu which allows you to add the menu items.
#Override
public boolean onCreateOptionsMenu(Menu menu){
super.onCreateOptionsMenu(menu);
// add items corresponding to this Fragment
menu.add(...);
return true;
}
The reason I recommend this is that it allows you to put more of the menu handling code into your Fragment instead of the Activity to figure out which Fragment to call, etc.
In this case, clicking the menu item will call onOptionsItemSelected inside of your Fragment which I suggest.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.my_id1:
dothing1();
return true;
case R.id.my_id2:
dotghing2();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
More of a long winded answer, but this is the way to handle menu clicks inside your Fragment.
onMenuItemClickListener
In the case of onMenuItemClickListener, this is used when you DON'T want to use the pre-ready method above and implement your own.
What I mean by that is you implement OnMenuItemClickListener and generate the methods in the interface. You then assign the menu to call the Activity that implemented this where as the above option assumes what Activity to use based on the pre-ready implementation of the Activity to Fragment relationship.
If you are targeting API 14 or greater (ICS or above) you could implement an ActionProvider. If that's not an option then you could implement a base activity that will always populate the menu and handle any menu clicks using onOptionsItemSelected. This is a good approach to implement "About" or "Settings" menu items through all your activities.
Inside of my onCreateOptionsMenu function I implemented this:
mymenuitem.setOnMenuItemClickListener(new OnMenuItemClickListener(){
public boolean onMenuItemClick(MenuItem item){
update_freq=1;
showChosen(); (some user defined function)
update_time();
return true;
}
});
However, the .setOnMenuItemClickListener only be called the first time I click my preference, later on when I went back to menu and click preference buttons, it never be called.
can anyone tell me what is the problem? My menu is written in xml file and inflated.
I think you need to override onOptionsItemSelected. The OnMenuItemClickListener is set on a single, specific MenuItem.