How can I refresh the ActionBar when onPrepareOptionsMenu switched menu entries?
Within my apps I often enable/disable menu entries and do make them visible from onPrepareOptionsMenu.
Today I started to add the android:showAsAction menu attribute to some of my Android 2.x apps to show menu entries used most on the ActionBar.
The ActionBar does not reflect the enable/disable and visibility immediately. I need to click on the menu dropdown on the right to see this change happen.
Ok, I do understand that the menu fires onPrepareOptionsMenu. But what do I need to do to refresh the ActionBar? I think this change needs to be applied from within onOptionsItemSelected but I don't know what I should call.
Here's the menu:
<item
android:icon="@drawable/ic_menu_mapmode"
android:id="@+id/men_mapview"
android:showAsAction="ifRoom|withText"
android:title="@string/txt_mapview" />
<item
android:icon="@drawable/ic_menu_mapmode"
android:id="@+id/men_satelliteview"
android:showAsAction="ifRoom|withText"
android:title="@string/txt_satelliteview" />
Here's the onPrepareOptionsMenu:
@Override
public boolean onPrepareOptionsMenu(final Menu menu) {
MenuItem menuItemMapView = menu.findItem(R.id.men_mapview);
MenuItem menuItemSatelliteView = menu.findItem(R.id.men_satelliteview);
if (mapView.isSatellite()) {
menuItemMapView.setEnabled(true).setVisible(true);
menuItemmenuItemSatelliteView.setEnabled(false).setVisible(false);
} else {
menuItemMapView.setEnabled(false).setVisible(false);
menuItemmenuItemSatelliteView.setEnabled(true).setVisible(true);
}
return super.onPrepareOptionsMenu(menu);
}
Here's the onOptionsItemSelected
@Override
public boolean onOptionsItemSelected(final MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.men_mapview:
mapView.setSatellite(false);
mapView.setStreetView(true);
mapView.invalidate();开发者_运维知识库
invalidateOptionsMenu(); // This works on Android 3.x devices only
return true;
case R.id.men_satelliteview:
mapView.setSatellite(true);
mapView.setStreetView(false);
mapView.invalidate();
invalidateOptionsMenu(); // This works on Android 3.x devices only
return true;
}
return super.onOptionsItemSelected(menuItem);
}
EDIT: If I add invalidateOptionsMenu this works on Android 3.x apps but crashes on Android 2.x devices because of a missing method. What's the recommended way to do it right?
My method of choice is to create a helper class. For example:
class VersionHelper
{
static void refreshActionBarMenu(Activity activity)
{
activity.invalidateOptionsMenu();
}
}
Now in your code above, replace invalidateOptionsMenu();
with:
if (Build.VERSION.SDK_INT >= 11)
{
VersionHelper.refreshActionBarMenu(this);
}
Credit for this method goes to CommonsWare (search for HoneycombHelper, and check out his books - highly recommended)
Thanks to the accepted answer. I am using ActionBarActivity. in this class you can use
supportInvalidateOptionsMenu();
Use
ActivityCompat.invalidateOptionsMenu(Activity activity)
from the compatibility library.
See: https://stackoverflow.com/a/14748687/435855
save a reference to the menu and call:
this.menu.clear();
this.onCreateOptionsMenu(this.menu);
Based on "Klaasvaak" answer above. I am using its subMenus. This works for me :
// Declare and save the menu as global, so it can be called anywhere.
Menu absTopSubMenus;
public boolean onCreateOptionsMenu(Menu menu) {
absTopSubMenus = menu; // Used for re-drawing this menu anywhere in the codes.
// The remainder of your code below
}
Then, to re-draw this, just call :
// Redraw the top sub-menu
absTopSubMenus.clear();
onCreateOptionsMenu(absTopSubMenus);
You can now use supportInvalidateOptionsMenu() method from the ActionbarActivity with the support library. So you don't have to check for the version of the sdk. Goes until API 7 and above.
http://developer.android.com/reference/android/support/v7/app/ActionBarActivity.html
do to so, you have to import the v7 of the support library using this
http://developer.android.com/tools/support-library/setup.html
I am not sure you have seen it already, but if you use the actionbar extensively, and plan on supporting lower API's (>8), take a look at the actionBarSherlock library. It will make it so you do not have to section your actionBar code for lower and Higher API's, and then you can just run:
runOnUiThread(new Runnable(){
@Override
public void run(){
supportInvalidateOptionsMenu();
}
});
getActivity().invalidateOptionsMenu();
gets the job done.
Kudos to @Klaasvaak for showing us the way here. I use the following which works on both pre- and post- API Level 11:
private void invalidOptionsMenuHelper() {
if (Build.VERSION.SDK_INT >= 11) {
invalidateOptionsMenu();
} else if (mOptionsMenu != null) {
mOptionsMenu.clear();
onCreateOptionsMenu(mOptionsMenu);
}
}
Of course, you must save a reference to the menu (mOptionsMenu in this case) which I accomplish via:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
mOptionsMenu = menu;
//... create and manage the menu normally
}
Also make sure you are not calling
myAppCompatActivity.setToolbarTitle("some dynamic title");
shortly after you have refreshed your menu.
I had the issue that the drawables would not show up even if there was room for them to be displayed. Once I did an orientation change the drawables then appeared.. ?
In Summary:
MainActivity:
public class MainActivity extends AppCompatActivity {
private boolean showMenu = true;
public void setShowMenu(boolean show) {
showMenu = show;
supportInvalidateOptionsMenu();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.my_menu, menu);
menu.findItem(R.id.menu_share).setVisible(showMenu);
// menu.findItem(...
return true;
}
}
FragmentNoMenu:
public abstract class FragmentNoMenu extends Fragment {
protected MainActivity mainActivity;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mainActivity = (MainActivity) getActivity();
if (mainActivity != null) {
mainActivity.setShowMenu(false);
}
}
}
FragmentWithMenu:
public abstract class FragmentWithMenu extends Fragment {
protected MainActivity mainActivity;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mainActivity = (MainActivity) getActivity();
if (mainActivity != null) {
mainActivity.setShowMenu(true);
}
}
}
精彩评论