Android: 更改片段时更改菜单项的可见性

9
我希望在活动的片段改变时改变片段活动(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中只实例化片段一次),并直接将菜单项存储到持有者中。现在它运行得非常好。 - modebm
2个回答

21

切换片段时更改菜单有更好的方法吗?

也许有 :)

文档说明 :

报告此片段希望通过调用onCreateOptionsMenu(Menu, MenuInflater)和相关方法来参与填充选项菜单。

准备屏幕的标准选项菜单以显示。这是在每次显示菜单之前调用的。您可以使用此方法有效地启用/禁用项目或以其他方式动态修改内容。

然后,在该方法中,通过ID查找您的菜单项,并使它们可见/不可见、启用/禁用,就像这样:

@Override
public void onPrepareOptionsMenu(Menu menu) {    
    menu.findItem(HERB_SPINNER_ID).setVisible(false).setEnabled(false);
}

阅读更多


3
这个回答应该得到更多的赞。但是,在PreferenceFragment中,必须使用以下Override声明来准备选项菜单:public void onPrepareOptionsMenu(Menu menu){ /../ }不过,你帮我节省了很多工作。谢谢 :) - Daniel Gilbert
1
也帮助了我,谢谢,并且mMenu应该改为menu,而且它不应该返回任何东西,因为它是一个void。 - fizgig

0
在我的情况下,我有两个片段具有不同的菜单项。
在我的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);
    }
}

这将使得当B离开时,来自Fragment A的菜单可见。如果从B返回A,则旧菜单可以显示。

参考:这里


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接