Как я могу обновить ActionBar, когда onPrepareOptionsMenu переключил пункты меню?
В моих приложениях я часто включаю / отключаю пункты меню и делаю их видимыми из onPrepareOptionsMenu.
Сегодня я начал добавлять атрибут меню android:showAsAction в некоторые из моих приложений для Android 2.x, чтобы отображать элементы меню, наиболее часто используемые в ActionBar.
Панель действий не отражает включение / отключение и видимость сразу. Мне нужно нажать на выпадающее меню справа, чтобы увидеть это изменение.
Хорошо, я понимаю, что меню запускается по меню "RepareOptionsMenu". Но что мне нужно сделать, чтобы обновить ActionBar? Я думаю, что это изменение должно быть применено изнутри onOptionsItemSelected, но я не знаю, что мне следует называть.
Вот меню:
<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" />
Вот меню onPrepareOptions:
@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);
}
Вот 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);
}
РЕДАКТИРОВАТЬ: Если я добавлю invalidateOptionsMenu, это работает на приложениях Android 3.x, но происходит сбой на устройствах Android 2.x из-за отсутствия метода. Какой рекомендуемый способ сделать это правильно?
10 ответов
Мой метод выбора - создать вспомогательный класс. Например:
class VersionHelper
{
static void refreshActionBarMenu(Activity activity)
{
activity.invalidateOptionsMenu();
}
}
Теперь в вашем коде выше, замените invalidateOptionsMenu();
с:
if (Build.VERSION.SDK_INT >= 11)
{
VersionHelper.refreshActionBarMenu(this);
}
Кредит на этот метод идет на CommonsWare (поиск HoneycombHelper и проверить его книги - настоятельно рекомендуется)
Спасибо за принятый ответ. Я использую ActionBarActivity. в этом классе вы можете использовать
supportInvalidateOptionsMenu();
Использование
ActivityCompat.invalidateOptionsMenu(Activity activity)
Сохранить ссылку в меню и вызвать:
this.menu.clear();
this.onCreateOptionsMenu(this.menu);
Теперь вы можете использовать метод supportInvalidateOptionsMenu() из ActionbarActivity с библиотекой поддержки. Так что вам не нужно проверять версию SDK. Идет до API 7 и выше.
http://developer.android.com/reference/android/support/v7/app/ActionBarActivity.html
сделать так, вы должны импортировать v7 библиотеки поддержки, используя эту
http://developer.android.com/tools/support-library/setup.html
На основании "Клаасваак" ответ выше. Я использую его подменю. Это работает для меня:
// 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
}
Затем, чтобы перерисовать это, просто позвоните:
// Redraw the top sub-menu
absTopSubMenus.clear();
onCreateOptionsMenu(absTopSubMenus);
Я не уверен, что вы уже видели это, но если вы широко используете панель действий и планируете поддерживать более низкие API (>8), взгляните на библиотеку actionBarSherlock. Это сделает так, что вам не придется разделять код actionBar на более низкие и более высокие API, а затем вы можете просто запустить:
runOnUiThread(new Runnable(){
@Override
public void run(){
supportInvalidateOptionsMenu();
}
});
. GetActivity() invalidateOptionsMenu();
выполняет свою работу
Престижность @Klaasvaak для того, чтобы показать нам путь здесь. Я использую следующее, которое работает как до, так и после API уровня 11:
private void invalidOptionsMenuHelper() {
if (Build.VERSION.SDK_INT >= 11) {
invalidateOptionsMenu();
} else if (mOptionsMenu != null) {
mOptionsMenu.clear();
onCreateOptionsMenu(mOptionsMenu);
}
}
Конечно, вы должны сохранить ссылку на меню (в данном случае mOptionsMenu), которую я выполняю через:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
mOptionsMenu = menu;
//... create and manage the menu normally
}
Также убедитесь, что вы не звоните
myAppCompatActivity.setToolbarTitle("some dynamic title");
вскоре после того, как вы обновили свое меню.
У меня была проблема, что ничьи не отображались, даже если бы было место для их отображения. После того, как я изменил ориентацию, появились чертежи..?
В итоге:
Основная деятельность:
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);
}
}
}