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().
Related
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.
I have an ActionBarSherlock with one menu item in my bar. When I'm call
View item = findViewById(R.id.my_item);in activity's button onClick all works fine as expected.
But when I try to do this in onCreate or onResume or even in onPostResume it is always null. I also tryed do this in onCreateOptionsMenu(Menu menu) after inflating my menu from resource, but without any succes.
Therefore I can't understand when actionbar items created and how to catch this moment?
As it has been said here and here, getActionView returns the view that we sets in setActionView. Therefore, the only one way to customize action bar menu item described here
actually it is possible to get the view of the action item, even if it's not customized.
however, do note that sometimes action items get to be inside the overflow menu so you might get a null instead.
so, how can you do it?
here's a sample code:
public boolean onCreateOptionsMenu(final Menu menu) {
getSupportMenuInflater().inflate(R.menu.main, menu);
new Handler().post(new Runnable() {
#Override
public void run() {
final View syncItemView = findViewById(R.id.action_search);
...
this was tested when using actionBarSherlock library, on android 4.1.2 and android 2.3.5 .
another alternative is to use a more extensive way , used on the showcaseView library, here .
first of all get a menu reference as below:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.custom_menu, menu);
customMenu = menu;
return super.onCreateOptionsMenu(menu);
}
after that you can get the item you need as below
customMenu.getItem(0);
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)
In some methods of my Activity I want to check the title of menu or know if it is checked or not. How can I get Activity's menu. I need something like this.getMenu()
Be wary of invalidateOptionsMenu(). It recreates the entire menu. This has a lot of overhead and will reset embedded components like the SearchView. It took me quite a while to track down why my SearchView would "randomly" close.
I ended up capturing the menu as posted by Dark and then call onPrepareOptionsMenu(Menu) as necessary. This met my requirement without an nasty side effects. Gotcha: Make sure to do a null check in case you call onPrepareOptionsMenu() before the menu is created. I did this as below:
private Menu mOptionsMenu;
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
mOptionsMenu = menu
...
}
private void updateOptionsMenu() {
if (mOptionsMenu != null) {
onPrepareOptionsMenu(mOptionsMenu);
}
}
Call invalidateOptionsMenu() instead of passing menu object around.
you could do it by passing the Menu object to your Activity class
public class MainActivity extends Activity
{
...
...
private Menu _menu = null;
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
_menu = menu;
return true;
}
private Menu getMenu()
{
//use it like this
return _menu;
}
}
There several callback methods that provide menu as a parameter.
You might wanna manipulate it there.
For example:
onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
onCreateOptionsMenu(Menu menu)
onCreatePanelMenu(int featureId, Menu menu)
There several more, best you take a look in activity documentation and look for your desired method:
http://developer.android.com/reference/android/app/Activity.html
As far as I could understand what you want here is which may help you:
1. Refer this tutorial over option menu.
2. Every time user presses menu button you can check it's title thru getTitle().
3. Or if you want to know the last menu item checked or selected when user has not pressed the menu button then you need to store the preferences when user presses.
Android now has the Toolbar widget which was a Menu you can set/get. Set the Toolbar in your Activity with some variation of setSupportActionBar(Toolbar) for stuff like onCreateOptionsMenu from a Fragment for example. Thread revived!
I have an Activity that extends ActionBarActivity taken from the ActionBarCompat code sample and I'm trying to show/hide menu items (actions) at runtime.
I've tried using setVisible() on the MenuItem and works for ICS, but in pre-ICS it only change visibility of menu items (menu button press) whereas the ActionBar doesn't get notified of menu changes.
Any solution? Thanks in advance!
I created multiple alternatives of the action bar items under /res/menu/. I keep a member to indicate which one I am using right now. to replace the menu, I call:
protected void setMenuResource(int newMenuResourceId)
{
_menuResource = newMenuResourceId;
invalidateOptionsMenu();
}
And I override onCreateOptionsMenu() to:
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
if (_menuResource != 0)
{
getSupportMenuInflater().inflate(_menuResource, menu);
return true;
}
return super.onCreateOptionsMenu(menu);
}
Now, if I want to change the action Items, I call:
setMenuResource(R.menu.actionbar_menu_X);
This is how i solved it:
In ActionBarHelperBase.java of actionbarcompat project
...
private View addActionItemCompatFromMenuItem(final MenuItem item) {
final int itemId = item.getItemId();
....
The creator of this class copy properties of object, but didn't copy the id of item, so it is impossible to find it later with fiven id.
So i added it in that method:
...
actionButton.setId(itemId);
...
and in the same class i just use:
#Override
public void hideMenuItemById(int id, boolean show){
getActionBarCompat().findViewById(id).setVisibility(show? View.VISIBLE: View.GONE);
}
Hope it helps You.
You have to call supportInvalidateOptionsMenu() which is the relevant method for an ActionBarActivity:
http://developer.android.com/reference/android/support/v7/app/ActionBarActivity.html#supportInvalidateOptionsMenu()