i have added overflow icon on action bar but now for some condition i want to hide it, Is there any way to hide this icon programtically.
For the particular condition you want to hide menus, you can manually call invalidateOptionsMenu(); in your activity class and in your onPrepareOptionsMenu method setVisible(false); for all the menu items you have.
For example
public void someMethod(){
if (<somecondition>){
invalidateOptionsMenu();
}
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (<somecondition>){
menu.findItem(R.id.action_one).setVisible(false);
menu.findItem(R.id.action_two).setVisible(false);
menu.findItem(R.id.action_three).setVisible(false);
}else{
menu.findItem(R.id.action_one).setVisible(true);
menu.findItem(R.id.action_two).setVisible(true);
menu.findItem(R.id.action_three).setVisible(true);
}
}
When you want it to be visible again, again call invalidateOptionsMenu(); and make sure the condition inside onPrepareOptionsMenu method gets false so that else part is executed.
Related
I have the below menu item created and is showing always as an action, instead of being hidden in an overflow menu.
<item android:id="#+id/menu_refresh_network"
android:orderInCategory="100"
android:icon="#drawable/ic_menu_action_refresh_network"
android:title="#string/title_refresh_network"
android:enabled="true"
app:showAsAction="always" />
I need it to be hidden when ThreshVoteIntentService.mOpportunistic is TRUE. I have a receiver which is alerted by intent when that value has changed. It's a very simple procedure that invalidates the menu.
IntentFilter filterModeUpdated = new IntentFilter(resources.getString(R.string.action_mode_updated));
mModeUpdatedReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
invalidateOptionsMenu();
}
};
this.registerReceiver(mModeUpdatedReceiver, filterModeUpdated);
I have my options menu then (supposedly) redraw in onPrepareOptionsMenu.
#Override
public boolean onPrepareOptionsMenu (Menu menu) {
menu.findItem(R.id.menu_refresh_network).setVisible(ThreshVoteIntentService.mOpportunistic);
return super.onPrepareOptionsMenu(menu);
}
What actually happens is that the visibility of menu_refresh_network only changes when I open the overflow menu. Have I basically misunderstood how this should work?
onPrepareOptionsMenu() is only called, as you say, just before the overflow menu is show, so that's too late.
You need to call setVisible(false) on the correct MenuItem before invalidating the options menu. So in your onCreateOptionsMenu(), find a reference to the MenuItem with findItem() for the item id that you want to change and store that in a member variable. Then, when the broadcast arrives, change the visibility of that item and then invalidate the options menu.
Here is a sample activity based off a new project I created in Android Studio to demonstrate this. If you run this, you can see that the menu item disappears after 5 seconds, and no invalidate is even required to force the menu to refresh.
public class MainActivity extends AppCompatActivity {
private MenuItem menuItem;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Hide the menu item in 5 seconds
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
menuItem.setVisible(false);
}
}, 5000);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
menuItem = menu.findItem(R.id.action_settings);
MenuItemCompat.setShowAsAction(menuItem, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
return true;
}
}
If you are using AppCompatActivity (as app:showAsAction implies), you should use supportInvalidateOptionsMenu() in place of invalidateOptionsMenu() as invalidateOptionsMenu() does not know about always visible action items (hence, why it only calls onPrepareOptionsMenu() when the menu is opened)
I This is from https://developers.facebook.com/docs/android/scrumptious/authenticate
This is my code (identical from the tutorial) for the options menu part
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
// only add the menu when the selection fragment is showing
if (fragments[SELECTION].isVisible()) {
if (menu.size() == 0) {
settings = menu.add(R.string.settings);
}
return true;
} else {
menu.clear();
settings = null;
}
return false;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
if (item.equals(settings)) {
showFragment(SETTINGS, true);
return true;
}
return false;
}
whats happening is this works most of the time but I found a test case I couldn't debug. When you logout, the menu item still shows and you have to click it to make it disappear.(it shouldn't appear at all). This wasn't a huge concern to me at the beginning but I found that when you logged in again after you clicked the menu item to make it disappear, the options menu doesn't appear at all.
I think I found the problem, I leave it up for others. From When and how often onPrepareOptionsMenu() method is called for ActionBar? ,I got that "On Android 3.0 and higher, you must call invalidateOptionsMenu() when you want to update the menu, because the menu is always open. The system will then call onPrepareOptionsMenu() so you can update the menu items."
When I logged out, even thought there were no actual menu items, the menu was still open. However when I clicked the menu when it was empty, it messed it up so that when I logged in, show wouldn't work. I don't understand that part yet. I was hoping someone can elaborate what happened during that part
I want to listen when user opens/closes the overflow menu (three dots) of ActionBar, someway like this:
void onOverflowMenu(boolean expanded) {
}
To handle open cases, I've tried onPrepareOptionsMenu(), but it's triggered when ActionBar is constructed or when invalidateOptionsMenu() is called. This is not what I want.
I was able to detect overflow menu is closed if user selects a menu item in onMenuItemSelected(). But I also want to detect it if user closes overflow menu by tapping outside of it, by pressing back key, and all other cases.
Is there a way to implement that?
To catch open action in the Activity:
#Override
public boolean onMenuOpened(int featureId, Menu menu) {
...
return super.onMenuOpened(featureId, menu);
}
To catch closed action, also if user touch outside of Menu view:
#Override
public void onPanelClosed(int featureId, Menu menu) {
...
}
IMHO the simplest way is to set ActionBar.OnMenuVisibilityListener
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.addOnMenuVisibilityListener(new ActionBar.OnMenuVisibilityListener() {
#Override
public void onMenuVisibilityChanged(boolean isVisible) {
if (isVisible) {
// menu expanded
} else {
// menu collapsed
}
}
});
}
How i can dinamically change action button icon of Action Bar when i swipe fragments in ViewPager. Depending on fragment button must change state (icon).
You can set the correct icon in onPrepareOptionsMenu, and then invalidate your action bar with invalidateOptionsMenu (or ActivityCompat.invalidateOptionsMenu if you are using the support library) when you want the icon to update.
For example:
#Override
public boolean onPrepareOptionsMenu (Menu menu) {
MenuItem item = menu.findItem(R.id.my_menu_id);
item.setIcon(getMenuItemIconResId());
}
#Override
public void onPageSelected(int position) {
invalidateOptionsMenu();
}
I solved this problem:
1) I implement OnPageChangeLister
2) Invoke setIcon() in onPageScrollStateChanged()
3) MenuItem defined like global variable (field of class)
It's clear that for showing/hiding the indeterminate progress you have to use this method:
itemMenu.setActionView(...);
So:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_refresh:
item.setActionView(R.layout.indeterminate_progress_action);
runAsyncTask();
...
}
}
What is not clear to me is: how to set the action view back to null. I don't want to keep a reference to a MenuItem, I don't think it is correct since I don't want to assume anything about the OptionsMenu lifecycle.
How should I set back the action view to null on onPostExecute?
I do it like this :
refresh = false; // the future state of your indeterminate progress
invalidateOptionsMenu(); // trigger the recreation of the menu and call onCreateOptionsMenu(Menu)
then in your onCreateOptionsMenu(Menu) method :
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
super.onCreateOptionsMenu(menu, inflater);
MenuItem refreshItem = menu.add(Menu.NONE, R.id.action_bar_refresh, 1, "Refresh");
refreshItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
if(refresh)
refreshItem.setActionView(R.layout.indeterminate_progress_action);
else
refreshItem.setIcon(R.drawable.ic_menu_refresh);
}
How about invalidateOptionsMenu()? Your onCreateOptionsMenu() would probably always set it to null, then.
I believe you could just call setActionView(null) on that MenuItem
Then refresh the ActionBar with invalidateOptionsMenu()
There is no need to manipulate specific menu items if you would prefer not to.
I use a different approach that leverages off the system's indeterminate progress bar functionality (as ported to ActionBarSherlock). I explain it here to offer more options to future readers to use whichever way works best for them.
My base fragment has a method I call to turn my loading UI on & off. Here is a trimmed down version:
private void setLoading(final boolean isLoading)
{
final SherlockFragmentActivity sherlockActivity = getSherlockActivity();
sherlockActivity.runOnUiThread(new Runnable()
{
public void run()
{
// show loading progress bar
sherlockActivity
.setSupportProgressBarIndeterminateVisibility(isLoading);
// hide the rest of the menu
setMenuVisibility(!isLoading);
}
});
}
For this to work, your activity must be configured to use the correct style - call this from your SherlockFragmentActivity.onCreate() method:
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
The final trick is that on pre-HoneyComb devices, this causes the progress bar to show immediately by default (instead of being hidden by default from HC & above).
you must set it to be invisible
you must also create a Sherlock Action Bar instance before this code will work
The onCreate() thus becomes:
protected void onCreate(Bundle arg0)
{
super.onCreate(arg0);
// allow window to show progress spinner in the action bar
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
getSupportActionBar();
setSupportProgressBarIndeterminateVisibility(false);
}
For more details on this you can check my answer to
Intermediate Progress doesn't work with ActionBarSherlock running on Gingerbread (here).
If you don't want to keep a reference to the menu item, then you can simply keep a reference to the Menu object instead. A reference to the Menu is guaranteed to remain valid until the next time onCreateOptionsMenu() is called as mentioned in the docs (http://developer.android.com/reference/android/app/Activity.html#onCreateOptionsMenu(android.view.Menu)).
Then call:
MenuItem menuItem = mMenu.findItem(R.id.favourite_payment);
menuItem.setActionView(null);
Or alternatively if using AppCompat:
MenuItem menuItem = mMenu.findItem(R.id.favourite_payment);
MenuItemCompat.setActionView(menuItem, null);
There is no need to call invalidateOptionsMenu().