Android:通过更改片段更改菜单项的可见性
Posted
技术标签:
【中文标题】Android:通过更改片段更改菜单项的可见性【英文标题】:Android: Changing visibility on menu items with changing fragment 【发布时间】:2013-01-02 16:18:30 【问题描述】:当我更改活动中的片段时,我想更改片段活动 (abs) 的菜单项的可见性。片段是 SherlockListFragments。
我要显示/隐藏的菜单项是我在创建菜单时创建的微调器:
public boolean onCreateOptionsMenu(Menu menu)
// Inflate the menu; this adds items to the action bar if it is present.
MenuInflater inflater = getSupportMenuInflater();
IcsSpinner herbSortSpinner = new IcsSpinner(this, null, R.attr.actionDropDownStyle);
SpinnerAdapter herbSortSpinnerAdapter = ArrayAdapter.createFromResource(this, R.array.herb_sort_elements, android.R.layout.simple_spinner_dropdown_item);
herbSortSpinner.setAdapter(herbSortSpinnerAdapter);
herbSortSpinner.setOnItemSelectedListener(this);
herbSortSpinner.setId(HERB_SPINNER_ID);
menu.add(R.string.menu_sort).setActionView(herbSortSpinner).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
IcsSpinner noteSortSpinner = new IcsSpinner(this, null, R.attr.actionDropDownStyle);
SpinnerAdapter noteSortSpinnerAdapter = ArrayAdapter.createFromResource(this, R.array.note_sort_elements, android.R.layout.simple_spinner_dropdown_item);
noteSortSpinner.setAdapter(noteSortSpinnerAdapter);
noteSortSpinner.setOnItemSelectedListener(this);
noteSortSpinner.setId(NOTE_SPINNER_ID);
menu.add(R.string.menu_sort).setActionView(noteSortSpinner).setVisible(false).setEnabled(false).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
inflater.inflate(R.menu.activity_lexicon, menu);
menuHolder.setMenu(menu);
return true;
我切换片段的逻辑是:
public boolean onNavigationItemSelected(int position, long itemId)
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
switch(position)
case 0:
List<Herb> herbList = findHerbsByIntent(getHerbLocale());
HerbListFragment herbListFragment = new HerbListFragment();
herbListFragment.setListAdapter(new HerbListAdapter(this, getHerbLocale(), herbList));
fragmentTransaction.replace(R.id.fragment_container, herbListFragment, HERB_LIST_FRAGMENT_TAG);
//menuHolder.showHerbsSpinner();
break;
case 1:
SymptomListFragment symptomListFragment = new SymptomListFragment();
symptomListFragment.setListAdapter(new SymptomListAdapter(this, getDefaultSymptomLocale()));
fragmentTransaction.replace(R.id.fragment_container, symptomListFragment, SYMPTOM_LIST_FRAGMENT_TAG);
//menuHolder.showHerbsSpinner();
break;
case 2:
NoteRepository noteRepository = new NoteRepository(this);
List<Note> notes = noteRepository.getNoticables(ReferedType.HERB);
NoteListFragment noteListFragment = new NoteListFragment();
noteListFragment.setListAdapter(new NoteListAdapter(this, getHerbLocale(), notes));
fragmentTransaction.replace(R.id.fragment_container, noteListFragment, NOTE_LIST_FRAGMENT_TAG);
//menuHolder.showNotesSpinner();
break;
case 3:
FavoriteRepository favoriteRepository = new FavoriteRepository(this);
Set<Integer> favoriteHerbs = favoriteRepository.getFavorables(ReferedType.HERB);
List<Herb> favoriteHerbList = herbRepository.getHerbsByIds(favoriteHerbs, getHerbLocale());
FavoriteHerbListFragment favoriteHerbListFragment = new FavoriteHerbListFragment();
favoriteHerbListFragment.setListAdapter(new HerbListAdapter(this, getHerbLocale(), favoriteHerbList));
fragmentTransaction.replace(R.id.fragment_container, favoriteHerbListFragment, HERB_LIST_FRAGMENT_TAG);
//menuHolder.showHerbsSpinner();
break;
fragmentTransaction.commit();
return true;
我的第一个想法是将菜单对象保存在一个持有者类中,并在我切换片段时在那里操作它(在上面的每个 case 语句中)。
static class MenuHolder
private Menu mMenu;
void setMenu(Menu menu)
mMenu = menu;
void showNotesSpinner()
if (mMenu != null)
mMenu.findItem(HERB_SPINNER_ID).setVisible(false).setEnabled(false);
mMenu.findItem(NOTE_SPINNER_ID).setVisible(true).setEnabled(true);
void showHerbsSpinner()
if (mMenu != null)
mMenu.findItem(NOTE_SPINNER_ID).setVisible(false).setEnabled(false);
mMenu.findItem(HERB_SPINNER_ID).setVisible(true).setEnabled(true);
我的问题是没有给定 ID 的菜单项是活动本地常量。我在这里得到一个 NPE。有人知道我该如何解决吗?有没有更好的方法来改变切换片段时的菜单?
最好的问候 卡斯滕
【问题讨论】:
昨天帮助了自己。我已经清理了杂乱的代码(仅在 onCreate 中实例化片段一次)并将菜单项直接存储到持有人中。现在它就像一个魅力。 【参考方案1】:有没有更好的方法来改变切换片段时的菜单?
可能是的:)。
在您的片段onCreate
中,添加以下内容:
setHasOptionsMenu (true);
文档:
覆盖片段类中的onPrepareOptionMenu 方法。报告此片段希望通过接收对 onCreateOptionsMenu(Menu, MenuInflater) 和相关方法的调用来参与填充选项菜单。
准备要显示的屏幕标准选项菜单。每次显示菜单时,都会在显示菜单之前调用它。您可以使用此方法有效地启用/禁用项目或以其他方式动态修改内容。
然后,在此方法中,尝试通过 ID 查找您的菜单项,并使其可见/不可见、启用/禁用,如下所示:
@Override
public void onPrepareOptionsMenu(Menu menu)
menu.findItem(HERB_SPINNER_ID).setVisible(false).setEnabled(false);
Read More
【讨论】:
这个答案值得更多的支持。然而,在 PreferenceFragment 中,必要的 Override-declaration 将是: public void onPrepareOptionsMenu(Menu menu) /*..*/ 不过,你为我节省了很多工作。谢谢。 :) 也帮助了我,谢谢,mMenu 应该是菜单,它不应该返回任何东西,因为它是一个空。【参考方案2】:就我而言,我有 2 个片段具有不同的菜单项。
在我的 MainActivity 上:
FragmentA fragmentA = new FragmentA();
fragmentA.setTargetFragment(fragmentA, 0);
FragmentB fragmentB = new FragmentB();
fragmentB.setTargetFragment(fragmentB, 1);
而 FragmentA 和 FragmentB 有:
@Override
public void onHiddenChanged(boolean hidden)
super.onHiddenChanged(hidden);
if(hidden)
getTargetFragment().setMenuVisibility(false);
else
getTargetFragment().setMenuVisibility(true);
这将使片段 A 的菜单在 B 离开时可见。如果从 B 回到 A,则可以看到 A 的旧菜单。
参考:here
【讨论】:
以上是关于Android:通过更改片段更改菜单项的可见性的主要内容,如果未能解决你的问题,请参考以下文章
更改组件可见性时 Android Studio 空对象引用错误