I have a NavigationDrawer and hide/show the OptionsMenu (which is located on the bottom due to a split ActionBar) whenever the drawer gets opened/closed:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!isDrawerOpened) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
return false;
}
I would like to hide the Menu with an animation, (for reference: like the animation used by the system when you call ActionBar.hide() ), however I found no way to access the Layout used for the Menu (so I could get a View object to apply the animation to). It seems there's no public API available to perform this, I wouldn't mind some reflection approach if I knew what to look for. Any suggestions?
UPDATE
looking at this source I finally figured out how to access the View of a split ActionBar using a non-public identifier:
private View getSplitActionBarView() {
Window window = getWindow();
View v = window.getDecorView();
return v.findViewById(getResources().getIdentifier("split_action_bar",
"id", "android"));
}
Now I can create an Animation, set an AnimationListener and call invalidateOptionsMenu() as soon as the Animation ends. There's one problem left: doing this will let an ugly white rectangle at the place where the bottom part of the ActionBar was, this white rectangle will stay there until the Animation is complete. To get rid of it I would need to use <item name="android:windowActionBarOverlay">true</item> in my style XML (or doing the same by code) to display the ActionBar in overlay mode. However this is not what I need.
The question is now: is there any way to apply the overlay mode only to the split ActionBar (= the bottom part of the ActionBar)?
You need to call invalidateOptionsMenu() when the drawer is open/close, like this
public void onDrawerOpened(View view) {
invalidateOptionsMenu();
}
Now, onPrepareOptionsMenu() will be called,where you can hide/show the option menu like this..
#Override
public boolean onPrepareOptionsMenu(Menu menu){
// check if drawer is open
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
for(int index = 0 ; index < menu.size() ; index ++){
MenuItem menuItem = menu.getItem(index);
if(menuItem != null) {
// hide the menu items if the drawer is open
menuItem.setVisible(!drawerOpen);
}
}
return super.onPrepareOptionsMenu(menu);
}
You can hide all the menu or any of the required menu item.
Related
I am trying to use this code to show and hide menu icon in toolbar with Fragment in Android Studio:
#Override
public void onPrepareOptionsMenu(Menu menu) {
MenuItem IconBTON = menu.findItem(R.id.myIcon);
if (statusBlueTooth == true){
IconBTON.setVisible(true);
}
if (statusBlueTooth == false){
IconBTON.setVisible(false);
}
}
but the icon is not shown even though the value of the flag statusBlueTooth = true, but just when I touch the toolbar the icon is shown, what do I need to do so that this is shown according to the value of flag statusBlueTooth
Try adding this after in your onCreate of your Fragment:
setHasOptionsMenu(true);
and check IconBTON != null before setting the visibility.
I want to implement my own custom view (not inflating a menu item), I'm planning to use a toolbar to appear each time contextMenu starts, and hide it when finished.
the problem is: there are only answer showing HOW to clear/inflate another menu over the default actionMode menu
what i`ve tried so far:
-> Use a custom contextual action bar for WebView text selection
Overriding the callback at the WebView
#Override
public ActionMode startActionMode(ActionMode.Callback callback) {
callback2 = new customCallBack();
return super.startActionMode(callback2);
}
public class customCallBack implements ActionMode.Callback {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
}
}
changing the return false to true, doesn't result in the desired behavior i.e. hide the cab
Overriding the OnLongClick is not a option too, since it disable the current selection.
This answer solves the problem:
android webview: prevent text selection actionMode actionBar
not the most elegant solution ever, but I just tested it in an app I'm building and it works like a charm.
The Only way that worked for me (only on on Android L+) is clearing all the menu items from context actionbar from the activity
#Override
public void onActionModeStarted(ActionMode mode) {
if (mActionMode == null) {
mActionMode = mode;
Menu menu = mode.getMenu();
// Remove the default menu items (select all, copy, paste, search)
menu.clear();
}
Toast.makeText(this, "onActionModeStarted", Toast.LENGTH_SHORT).show();
super.onActionModeStarted(mode);
}
#Override
public void onActionModeFinished(ActionMode mode) {
mActionMode = null;
Toast.makeText(this, "onActionModeFinished", Toast.LENGTH_SHORT).show();
super.onActionModeFinished(mode);
}
inspired by Use a custom contextual action bar for WebView text selection
Also I wasn't able to implement the custom menu usin popupWindow or dialogs or dialog fragments.
So simply put it with the webView in a frame layout and play with its visability and margin
I'm using a Contextual Action Bar (CAB) in my app and setting the visibility of some menu items depending on which item is selected in my ListView. I've noticed that the CAB doesn't actually reflect the visibility of the menu items until I tap the menu button at the right end of the CAB.
Here is the code for my onPrepareActionMode method:
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu)
{
if (lstSortColumns.getCheckedItemPosition() == 0)
{
menu.findItem(R.id.action_move_up).setVisible(false);
}
else
{
menu.findItem(R.id.action_move_up).setVisible(true);
}
if (lstSortColumns.getCheckedItemPosition() == (lstSortColumns.getCount() - 1))
{
menu.findItem(R.id.action_move_down).setVisible(false);
}
else
{
menu.findItem(R.id.action_move_down).setVisible(true);
}
return true;
}
Am I missing something, or is this a bug in Android?
EDIT:
I was able to get around this by setting android:showAsAction="never" for the menu items in the menu xml file.
My use case is this: the default action bar displays a blueish background and I want the buttons to turn green on press; on the other hand, the contextual action bar is green and I want the button to turn blue on press. (sort of inverse colours)
Default action bar: blue background, green overlay (pressed state)
Contextual action mode: green background, blue overlay (pressed
state)
I have already the selectors, and I can set android:actionBarItemBackground in my theme to set the drawable for both modes. I can also style the close button setting a style in android:actionModeCloseButtonStyle and it works fine.
How can I style the other buttons then?
Thanks all,
Gil
As I said in my comment, the views of the MenuItems weren't made accessible so you don't have any direct options to access them. One way to alternate the selector for those MenuItems is to use MenuItems with action views set to ImageViews to hold the normal icon and change the selector for those ImageViews. An example below:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/menuFirst"
android:showAsAction="always"
android:actionLayout="#layout/image_menu_layout"/>
</menu>
<!-- image_menu_layout.xml -->
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="#style/Widget.ActionButton"/>
The code for the ActionBar part:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.your_menu, menu);
// call this for any menu item that you might have
setUpMenuItem(menu, R.id.menuFirst, false, null);
return super.onCreateOptionsMenu(menu);
}
/**
* This methods set up the MenuItems.
*
* #param menu the menu reference, this would refer either to the menu of the ActionBar or
* the menu of the ActionMode
* #param itemId the id of the MenuItem which needs work
* #param onActionMode flag to indicate if we're working on the ActionBar or ActionMode
* #param modeRef the ActionMode reference(only when the MenuItem belongs to the ActionMode,
* null otherwise)
*/
private void setUpMenuItem(Menu menu, int itemId, final boolean onActionMode,
final ActionMode modeRef) {
final MenuItem menuItem = menu.findItem(itemId);
ImageView itemLayout = (ImageView) menuItem.getActionView();
itemLayout.setBackgroundResource(onActionMode ? R.drawable.selector_for_actionmode : R
.drawable.selector_for_actionbar);
itemLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// for simplicity, wire up the normal selection callbacks(if possible,
// meaning the Activity implements the ActionMode.Callback)
if (onActionMode) {
onActionItemClicked(modeRef, menuItem);
} else {
onOptionsItemSelected(menuItem);
}
}
});
}
The code for the ActionMode part:
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
getMenuInflater().inflate(R.menu.actiomode_menu, menu);
// call this for any menu item that you might have
setUpMenuItem(menu, R.id.menu_item_from_actionmode, true, mode);
return true;
}
This method will also allow you to avoid the need to handle/keeping the status of the ActionBar/ActionMode while the Activity is used.
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()".