Android: how to detect click on disabled menu item? - android

I have some items in an ActionBar sub menu which I would like to conditionally disable, because they are not applicable for some contexts. I would like them to appear disabled (greyed out) to discourage users from clicking them; but if clicked, I would like to show a toast informing the user of why it is disabled ("can't do A because there is no B", etc). However, if I call MenuItem.setEnabled(false), it seems all the menu item click events do not occur. So, how do I detect click on the disabled menu item?
public class Temp extends Activity implements OnMenuItemClickListener
{
boolean mConditional = true;
protected void onCreate(Bundle state)
{
super.onCreate(state);
}
public boolean onMenuOpened(int featureId, Menu menu)
{
MenuItem item = (MenuItem) menu.findItem(R.id.item2);
if(item != null && mConditional)
{
item.setEnabled(false);
item.setOnMenuItemClickListener(this);
}
return super.onMenuOpened(featureId, menu);
}
#Override
public boolean onMenuItemClick(MenuItem item)
{
//does not fire if item is disabled
Log.e("", item.getTitle().toString());
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
//does not fire if item is disabled
Log.e("", item.getTitle().toString());
return super.onOptionsItemSelected(item);
}
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item)
{
//does not fire if item is disabled
Log.e("", item.getTitle().toString());
return super.onMenuItemSelected(featureId, item);
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
}
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/menu"
android:icon="#drawable/ic_launcher"
android:showAsAction="always"
android:title="menu">
<menu>
<item
android:id="#+id/item1"
android:showAsAction="always"
android:title="item 1"/>
<item
android:id="#+id/item2"
android:showAsAction="always"
android:title="item 2"/>
<item
android:id="#+id/item3"
android:showAsAction="always"
android:title="item 3"/>
</menu>
</item>
</menu>

You cannot use setEnabled for this. You need to keep menu items enabled all the time and simulate the "disabled" state by changing the drawable (or modifying it using porterduff filter - have a look at this question on how to dim images in android). Separately, you need to keep a flag indicating the state of the item - tag of the menu item is a good option. Ideally, you'd have something like this:
private void setMenuItemEnable(MenuItem item, boolean enabled) {
int curstate = ((Integer)item.getTag()).intValue();
if(curState == 1 && enabled || curstate == 0 && !enabled) {
return;
}
if(enabled) {
... //update image to remove dimming
item.setTag(1);
}
else {
... //update image by dimming it
item.setTag(0);
}
}
Finally, in your onOptionsItemSelected() method, check the tag of the chosen menu item and either perform the action if the tag is 1 or display the toast if the tag is 0. Visually it will be just what you want, and functionally it'll do what you're after.

Related

How to set toggle for Android MenuItems. How to show one when the other is clicked?

i have a note taking activity where i would like to be able to edit and save (basically overwrite) the same note.
Once i click the edit MenuItem, I would like it to hide and then show the save MenuItem.
I can get the edit MenuItem to be invisible but i cant get the save MenuItem to show. i keep getting a null pointer exception.
here's my edit_question_menu.xml
<?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/edit_question"
android:icon="#drawable/ic_edit_black_24dp"
android:title="Edit"
app:showAsAction="ifRoom"
android:visible="true">
</item>
<item
android:id="#+id/save_question"
android:icon="#drawable/ic_save_black_24dp"
android:title="Edit"
app:showAsAction="ifRoom"
android:visible="false">
</item>
</menu>
activity.java file
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.edit_question_menu, menu);
MenuItem itemSave = menu.findItem(R.id.save_question);
itemSave.setVisible(false);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.save_question:
saveQuestion();
return true;
case R.id.edit_question:
item.setVisible(false);
// MenuItem save_Question_MenuItem = findViewById(R.id.save_question);
// save_Question_MenuItem.setVisible(true);
enableEditMode();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void enableEditMode(){
MenuItem saveButton = findViewById(R.id.save_question);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_close_black_24dp);
questionEditText = findViewById(R.id.questionEditTextID);
mPostAnswerButton.setEnabled(false);
mPostAnswerButton.setBackgroundColor(getResources().getColor(android.R.color.darker_gray));
mCommentButton.setEnabled(false);
mCommentButton.setBackgroundColor(getResources().getColor(android.R.color.darker_gray));
saveButton.setVisible(true); **ERROR HAPPENS HERE**
}
Any and all help is appreciated. This seems fairly simple but I cant find a way to get it to work.
Add flag to your activity that indicates where the save MenuItem should be visible or not:
private boolean mShowSaveIcon
Override onPrepareOptionsMenu (UPDATE):
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem item = menu.findItem(R.id.save_question);
item.setVisible(mShowSaveIcon);
menu.findItem(R.id.edit_question).setVisible(!mShowSaveIcon); // you can use negation of the same flag if one and only one of two menu items is visible; or create more complex logic
return true;
}
In the click handler, change flag value and request invalidation:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.save_question:
mShowSaveIcon = false;
break;
case R.id.edit_question:
item.setVisible(false);
enableEditMode();
mShowSaveIcon = true;
break;
}
invalidateOptionsMenu();
return true;
}
Change handler:
private void enableEditMode(){
/// MenuItem saveButton = findViewById(R.id.save_question); // <--- NO THIS LINE
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_close_black_24dp);
questionEditText = findViewById(R.id.questionEditTextID);
mPostAnswerButton.setEnabled(false);
mPostAnswerButton.setBackgroundColor(getResources().getColor(android.R.color.darker_gray));
mCommentButton.setEnabled(false);
mCommentButton.setBackgroundColor(getResources().getColor(android.R.color.darker_gray));
/// saveButton.setVisible(true); **ERROR HAPPENS HERE** // <--- NO THIS LINE
}

Android onMenuItemClick() - detect which menu clicked?

I'm currently writing a simple application that uses 2 buttons anchored with Pop Up Menus that will display when the button is pressed. That was simple enough, however i'm having trouble with onMenuItemClick() method, which I want to use to change the text of the button to the menu item that was clicked.
Since I have two Pop Up Menus, each with 3 items, does this mean I would have to write 6 different if statements in the onMenuItemClick(), each one attempting to detect which item from which menu was clicked? Or is there a more simple way of doing this, for example specifying 2 onMenuItemClick() methods, each linked to the separate 2 menus?
public class MainActivity extends AppCompatActivity implements OnMenuItemClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void showColourPopUpMenu(View v){
PopupMenu coloursPopUpMenu = new PopupMenu(this, v);
coloursPopUpMenu.setOnMenuItemClickListener(this);
coloursPopUpMenu.inflate(R.menu.colours_menu);
coloursPopUpMenu.show();
}
public void showShapePopUpMenu(View v){
PopupMenu shapesPopUpMenu = new PopupMenu(this, v);
shapesPopUpMenu.setOnMenuItemClickListener(this);
shapesPopUpMenu.inflate(R.menu.shape_menu);
shapesPopUpMenu.show();
}
#Override
public boolean onMenuItemClick(MenuItem item) {
//How to determine which menu clicked?
return false;
}
}
#Override
public boolean onMenuItemClick(MenuItem item) {
int id = item.getItemId()
switch(id) {
case R.id.item1:
return true;
case R.id.item2:
return true;
default:
return false;
}
}
Create the listener when asigning it.
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
return true;
}
});
It's not possible directly. You'd at least need to map the item ids item.getItemId() to the menu (button) they're connected to.
Maybe a little simpler might be using groups like: menu/colours_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<group android:id="#+id/colours_menu" >
<item android:id="#+id/item1" ... />
<item android:id="#+id/item2" ... />
<item android:id="#+id/item3" ... />
</group>
</menu>
With item.getGroupId() you'd get the group ids and only need to map these to the buttons:
#Override
public boolean onMenuItemClick(MenuItem item) {
if (item.getGroupId() == R.id.colours_menu) {
// edit colors menu
} else {
// edit shape menu
}
}

Animate Between Visibility Modes For Menu Item

I am trying to animate between the visibility mode for a menu.
By default all menu items are hidden but when the user clicks on the edit button i want to show all the items with an animation.
I have achieved the first part of changing the visibility of the menu items and that works fine but the animation part crashes the app.
Here is my code.
When user clicks on edit this is called.By default edit_mode is false.
if (!edit_mode) {
edit_mode = true;
supportInvalidateOptionsMenu();
}
This is the menu code.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_add__custom, menu);
return true;
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem photo = menu.findItem(R.id.photo);
photo.setVisible(edit_mode);
if (edit_mode)
photo.getActionView().animate().alpha(1.0f);
MenuItem date = menu.findItem(R.id.date);
date.setVisible(edit_mode);
if (edit_mode)
date.getActionView().animate().alpha(1.0f);
MenuItem done = menu.findItem(R.id.done);
done.setVisible(edit_mode);
if (edit_mode)
done.getActionView().animate().alpha(1.0f);
return edit_mode;
}
menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<item
android:id="#+id/date"
android:icon="#drawable/ic_event_white_24dp"
android:orderInCategory="200"
android:title="Date"
app:showAsAction="ifRoom" />
<item
android:id="#+id/done"
android:icon="#drawable/ic_done_white_24dp"
android:orderInCategory="300"
android:title="Done"
app:showAsAction="ifRoom" />
<item
android:id="#+id/photo"
android:icon="#drawable/ic_photo_white_24dp"
android:orderInCategory="100"
android:title="Done"
app:showAsAction="ifRoom" />
I sure that crash that you are having is there because of NullException thrown by getActionView(). First of all to animate that way you have set the actionView first during onCreateOptionMenu(). That way when you get the actionView in onPrepareOptionsMenu it wont crash because of that and then you can animate it. The onPrepareOptionsMenu executes when you press the menu button so your logic to animate it that time is correct.
If its just the text you want to show in menu item, it should go like this,
final MenuItem photo;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_my_report, menu);
photo = menu.findItem(R.id.action1);
TextView textView = new TextView(this);
textView.setText("I am menu item");
photo.setActionView(textView);
return true;
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
if(someCondition)
{
photo.getActionView().animate().alpha(1.0f);
}
return super.onCreateOptionsMenu(menu);
}
In case you want to have the a complex and customise text you can set it using the layoutInflator service. This could go in your onCreate,
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ImageView view = (ImageView)inflater.inflate(R.layout.some_view, null);
Animation rotation = AnimationUtils.loadAnimation(this, R.anim.fade);
and onCreateOptionMenu,
view.startAnimation(rotation);
photo.setActionView(view);
Its just to get you an idea what needed to be done, you can play around with this and can suit your need.

How do I create a "Search" field in a contextual action bar?

I have an activity with an ActionBar. One of the options is to search a document (not necessarily local). I want to use a contextual action bar (CAB) with the following items:
edit field - place for user to enter text they want to search for
Previous Button - moves to the previous item that matches the search
Next Button - moves to the next item that matches the search
I want to use a CAB for several reasons. Primarily, I want the user to pick an option which will bring up the CAB defined above. When the user is done with the search, they select the done button and the ActionBar returns to previous state.
Here's the problem. I can't get the search item to appear in my CAB in an expanded state. NOTE: The activity I'm attempting to modify is NOT the main activity but is an activity launched by the user based on certain events. Once this activity is loaded, the user may or may not decide to use the 'search' functionality I'm describing. I also do not want Android to do the searching. I have an API that will search for the results I want and allow me to navigate to the prev/next search result.
My code for the CAB (which is being called correctly) is:
protected ActionMode mActionModeSearch;
private ActionMode.Callback mActionModeSearchCallback = new ActionMode.Callback()
{
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu)
{
actionMode.getMenuInflater().inflate(R.menu.pdf_menu_search, menu);
// Associate searchable configuration with the SearchView
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.pdf_menu_search_item).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setIconifiedByDefault(false);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
{
#Override
public boolean onQueryTextSubmit(String s)
{
return false;
}
#Override
public boolean onQueryTextChange(String s)
{
return false;
}
});
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu)
{
return false;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem)
{
switch(menuItem.getItemId())
{
case R.id.pdf_menu_search_prev:
findPrevSearchResult();
return true;
case R.id.pdf_menu_search_next:
findNextSearchResult();
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode actionMode)
{
//resetHideToolbarsTimer();
}
};
The CAB menu code is:
<?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">
<group android:id="#+id/group_search_mode">
<item
android:id="#+id/pdf_menu_search_item"
android:title="#string/search"
android:icon="#drawable/ic_pdf_action_search"
app:showAsAction="collapseActionView|ifRoom"
app:actionViewClass="android.support.v7.widget.SearchView"/>
<item
android:id="#+id/pdf_menu_search_prev"
android:title="#string/search_prev"
android:icon="#drawable/ic_pdf_action_search_prev"
app:showAsAction="ifRoom" />
<item
android:id="#+id/pdf_menu_search_next"
android:title="#string/search_next"
android:icon="#drawable/ic_pdf_action_search_next"
app:showAsAction="ifRoom" />
</group>
I also changed my activity definition in AndroidManifest.xml although I'm not sure this is required:
<activity
android:name="com.myapp.myActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.default_searchable"
android:value="com.myapp.myActivity" />
<meta-data
android:name="android.app.searchable"
android:resource="#xml/searchable" />
</activity>
When I run the app, the activity load correctly. When the user selects the search option, I load the CAB and it seems to be running fine. I've stepped through the code to make sure the onCreateActionMode is functioning as expected. But, all I see is the icon for search, next and previous, with the 'Done' button. When I touch the 'Search' icon, it doesn't do anything. No text field is created in the CAB for me to enter text. What am I doing wrong????
Screenshot showing the CAB coming up. As you can see, the search icon shows but doesn't do anything when I press it. What I really need is for the search edit box to appear by default.
First, we should set always value for app:showAsAction of all menu items:
<?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">
<group android:id="#+id/group_search_mode">
<item
android:id="#+id/pdf_menu_search_item"
android:icon="#drawable/ic_pdf_action_search"
android:title="#string/search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"/>
<item
android:id="#+id/pdf_menu_search_prev"
android:icon="#drawable/ic_pdf_action_search_prev"
android:title="#string/search_prev"
app:showAsAction="always"/>
<item
android:id="#+id/pdf_menu_search_next"
android:icon="#drawable/ic_pdf_action_search_next"
android:title="#string/search_next"
app:showAsAction="always"/>
</group>
</menu>
Secondary, in this case we don't need to set intent filter for our Activity and searchable info for our SearchView.
Definition of this Activity in AndroidManifest.xml:
<activity
android:name="com.myapp.myActivity"
android:label="#string/app_name" />
ActionMode.Callback implementation:
private ActionMode.Callback mActionModeSearchCallback = new ActionMode.Callback() {
private SearchView mSearchView;
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
actionMode.getMenuInflater().inflate(R.menu.home, menu);
mSearchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.pdf_menu_search_item));
mSearchView.setIconifiedByDefault(false);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
return false;
}
#Override
public boolean onQueryTextChange(String s) {
return false;
}
});
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
mSearchView.requestFocus();
return true;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.pdf_menu_search_prev:
findPrevSearchResult();
return true;
case R.id.pdf_menu_search_next:
findNextSearchResult();
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode actionMode) {
}
};
I just tried this code on three 4.0+ devices and it was fully working. But I didn't test on devises with lower OS versions.
Hope it will be helpful for you.
i have problem searchView in CAB
so i set layout(with edittext) in manu item, it give me same view as searchview
try this i hope it works for you
menu/search.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/edt_mySearch"
android:actionLayout="#layout/search_bar"
android:enabled="true"
android:showAsAction="always"
android:visible="true"/>
</menu>
layout/search _bar.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<EditText
android:layout_alignParentLeft="true"
android:id="#+id/edt_search"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint=" Search..."
/>
</RelativeLayout>
and myAction mode
mActionModeCallback = new ActionMode.Callback() {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// mode.setTitle("Demo");
getSupportMenuInflater().inflate(R.menu.search, menu);
RelativeLayout m = (RelativeLayout) menu.findItem(
R.id.edt_mySearch).getActionView();
EditText mSearchView = (EditText) m
.findViewById(R.id.edt_search);
mSearchView.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
// TODO Auto-generated method stub
}
#Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
// search here
}
});
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
}
};

Android action bar checkable menu item does not work/show properly?

so I am trying to get my menu item, that is show on the action bar to behave like a checkable menu option. The firs part works, meaning it is checkable and when I press it, and set in code the setChecked(true) it works. But what does not work is the visual part. There is no change in how a menu item looks on the action bar in checked and unchecked states? I tried using invalidateOptionsMenu() but that does not do the job, and not only that, with that line in my code I can't get out of the checked state?!?
What happens is that invalidate OptionsMenu() seams to unset the checked state and I end up 'looping', or on every press of that menu item I keep going to the unchecked part of the code where it gets checked and with invalidate it gets unchecked I guess...
Here is the code from my XML file for menu:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/lenslist_menu_add"
android:showAsAction="always"
android:title="#string/add"/>
<item android:id="#+id/lenslist_menu_delete"
android:showAsAction="always"
android:checkable="true"
android:title="#string/delete"/>
</menu>
And here is the java code:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.lenslist_menu_add:
return true;
case R.id.lenslist_menu_delete:
if (item.isChecked() == true) {
item.setChecked(false);
deleteMode = false;
lensAdapter.setDeleteMode(false);
} else {
item.setChecked(true);
deleteMode = true;
lensAdapter.setDeleteMode(true);
}
lensAdapter.notifyDataSetChanged();
return true;
}
return super.onOptionsItemSelected(item);
}
Thanks!
Checkable items appear only in submenus or context menus.
You are using them as main menu items, hence it will not work.
SOURCE: Download the API DEMOS, and open the file ApiDemos/res/menu/checkable.xml, you'll see it as a comment on line 13. I don't know why they don't mention this in the Developer Documentation
reference with comment.:
http://alvinalexander.com/java/jwarehouse/android-examples/platforms/android-2/samples/ApiDemos/res/menu/checkable.xml.shtml
Or just do it yourself
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.item1).setIcon(menu_checked?R.drawable.menu_ico_checked:R.drawable.menu_ico_unchecked);
return super.onPrepareOptionsMenu(menu);
}
and in onOptionsItemSelected do:
....
menu_checked=!menu_checked;
invalidateOptionsMenu();
The best solution is to set the actionLayout of the <Item> to a CheckBox. This solution gives you a native-looking checkbox (with material animations etc), with a font that matches the other items, and it works both as an action and in the submenu.
Create a new layout called action_checkbox.html:
<?xml version="1.0" encoding="utf-8"?>
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:checked="false"
android:textAppearance="#android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Menu"
android:id="#+id/action_item_checkbox"
/>
Set your <Item> like this. Note that you need the Checkable and Checked still in case it is shown in a sub-menu (in which case the actionLayout is ignored.
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
<item android:id="#+id/menu_action_logging"
android:title="#string/action_logging"
android:orderInCategory="100"
android:showAsAction="always"
android:checkable="true"
android:checked="false"
android:actionLayout="#layout/action_checkbox"
/>
</menu>
In your code, when the menu is created we need to a) set the title of the checkbox to match the menu item title, b) restore the checked state of both the menu checkable, and our extra checkbox, and c) add an onClicked() listener for our extra checkbox. In this code I am persisting the state of the checkbox in a RetainedFragment.
// Set the check state of an actionbar item that has its actionLayout set to a layout
// containing a checkbox with the ID action_item_checkbox.
private void setActionBarCheckboxChecked(MenuItem it, boolean checked)
{
if (it == null)
return;
it.setChecked(checked);
// Since it is shown as an action, and not in the sub-menu we have to manually set the icon too.
CheckBox cb = (CheckBox)it.getActionView().findViewById(R.id.action_item_checkbox);
if (cb != null)
cb.setChecked(checked);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
inflater.inflate(R.menu.menu_main, menu);
super.onCreateOptionsMenu(menu, inflater);
// Restore the check state e.g. if the device has been rotated.
final MenuItem logItem = menu.findItem(R.id.menu_action_logging);
setActionBarCheckboxChecked(logItem, mRetainedFragment.getLoggingEnabled());
CheckBox cb = (CheckBox)logItem.getActionView().findViewById(R.id.action_item_checkbox);
if (cb != null)
{
// Set the text to match the item.
cb.setText(logItem.getTitle());
// Add the onClickListener because the CheckBox doesn't automatically trigger onOptionsItemSelected.
cb.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onOptionsItemSelected(logItem);
}
});
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_action_logging:
// Toggle the checkbox.
setActionBarCheckboxChecked(item, !item.isChecked());
// Do whatever you want to do when the checkbox is changed.
mRetainedFragment.setLoggingEnabled(item.isChecked());
return true;
default:
break;
}
return false;
}

Categories

Resources