【问题标题】:FragmentStatePageAdapter duplicates ActionBar menu itemsFragmentStatePagerAdapter 重复 ActionBar 菜单项
【发布时间】:2015-03-27 13:43:35
【问题描述】:

我对 FragmentStatePageAdapter(我用作 ViewPager 的适配器)和操作栏中的菜单项有疑问。

当我启动应用程序时,一切都很好。如果我将任务移到后台(例如,按 HOME 按钮)并开始做一些事情直到活动结束,那么当我回到我的应用程序(通过启动器或我创建的通知)时,一切都很好,除了有操作栏中的重复菜单项。

一个重要的细节是,唯一重复的项目是在我在 ViewPager 中使用的每个片段的 onCreateOptionsMenu() 中创建的那些。

如果我用 FragmentPageAdapter 替换FragmentStatePageAdapter,则项目不再重复,但片段不会显示在 ViewPager 中(永远不会调用适配器的 getItem() 函数,因此它不会返回任何片段)。

有什么想法吗?一种避免 FragmentStatePageAdapter 重复菜单项的方法?也许使用 FragmentPageAdapter 但进行修改以显示片段?对我的片段进行了修改?

这是我的应用程序中的一些代码 sn-ps...

如何在片段中创建菜单项:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    /* Create play button */
    final MenuItem mPlay = menu.add(R.string.play_all);

    mPlay.setIcon(R.drawable.ic_play_all);
    mPlay.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);

    mPlay.setOnMenuItemClickListener(new OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {
            final List<Song> songs = getSongs();

            if (songs.size() == 0) {
                /* Show message */
                Toast.makeText(mContext, R.string.no_song_list, Toast.LENGTH_LONG).show();
            } else {
                /* Play song list */
                try { PlayManager.getService().playList(songs); } catch (Exception e) {}
            }

            return false;
        }
    });

    /* Create menu */
    super.onCreateOptionsMenu(menu, inflater);
}

片段是如何在 ViewPager 适配器中实例化的

@Override
public Fragment getItem(int position) {
    final Class<?> cls = mTabs.get(position);

    /* No tab */
    if (cls == null)
        return null;

    /* Instantiate fragment */
    final Fragment fragment = Fragment.instantiate(mContext, cls.getName(), null);

    /* Add to list */
    mFragments.put(position, fragment);

    /* Return fragment */
    return fragment;
}

谢谢!

PS:我尝试将活动的 launchMode 更改为“singleTop”,并且我还尝试在 getItem() 中返回先前创建的片段(但这没用,因为当我返回应用程序时从未调用 getItem(),正如我之前所说)。

【问题讨论】:

  • 你好,米格尔!你找到解决办法了吗?
  • 是的。我刚刚在我使用的解决方案下方发布。这不是真正的修复,而是一种解决方法。

标签: android android-fragments android-viewpager


【解决方案1】:

在发布我的问题几天后,我找到了解决问题的方法。很抱歉这么晚才放在这里。

以下代码解决了我的问题:

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    outState.remove("android:support:fragments");
}

就像在我实例化和使用片段的活动中编写那段代码一样简单。

我希望这会有所帮助:)

【讨论】:

  • 太棒了! :) 另一个解决方案:在寻呼机的片段上调用 ​​setRetainInstance(true)。
  • 我也得试试那个:)
  • 经过一些实验,似乎 outState.remove 不适用于屏幕旋转,因为 FragmentStatePageAdapter 在状态恢复时使用此信息。 setRetainInstance(true) 也不适用于从后台启动应用程序。
  • @HighFlyer 在哪里将 setRetainInstance(true) 放在寻呼机中??
  • 是的。请检查我的问题stackoverflow.com/questions/34399646/…
【解决方案2】:

在 ViewPager 中的 Fragment 中扩展选项菜单之前,请检查 Fragment 实例是否可见以防止重复的菜单项:

// This should be in your Fragment implementation
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
    if(isVisible())
    {
        inflater.inflate(R.menu.menu_fragment, menu);
    }
    super.onCreateOptionsMenu(menu, inflater);
}

【讨论】:

  • 您的代码帮助我克服了重复问题,但它不会改变片段。
【解决方案3】:

我认为问题在于每次滑动时 FragmentStatePagerAdapter 都会创建一个新的 Fragment。因此,每个创建的 Fragment 都会调用 onCreateOptionsMenu()。

我认为有两种解决方案:

  1. 从片段中取出操作栏操作。您无需为 Fragment 内的菜单项设置 onclick,而是从 Activity 向当前 Fragment 发送消息。

  2. 使用 Menu.findItem() 查看另一个 Fragment 是否已经添加了您想要的 MenuItem,如果是,则将当前 Fragment 附加到它(在 onPrepareOptionsMenu() 中)。

【讨论】:

  • 不是这个原因。我第一次启动该应用程序时,当我滑动时,它运行良好。当我滑动时,由我移动的片段创建的项目被删除,而我移动到的片段中的项目被添加。仅当活动在后台关闭并重新启动时才会出现此问题。
【解决方案4】:

我找到了一些解决方案,试试它可能有效

在您的重复菜单片段中 在onCreateOptionsMenu(Menu menu, MenuInflater inflater) 中的inflate 菜单文件之前添加menu.clear()

@Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        menu.clear();
        inflater.inflate(R.menu.main,menu);
    }

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2012-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-24
  • 1970-01-01
相关资源
最近更新 更多