操作栏(ActionBar)项重复出现。

23

我的应用程序中有一个操作栏(Action Bar)。我使用menu.xml添加操作项。我使用action bar-compat作为我的支持库。我观察到一个奇怪的问题,我的操作项会被复制。

我发现这个问题是随机出现的,当我离开我的设备一段时间或者在其他应用程序中工作时。请查看下面的屏幕截图和我的代码:

private LoginWebActivity mContext;
private final String TAG = "LoginFragment";

// for metrics
private String mPageNameSignIn = "signin";

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    mView = inflater.inflate(R.layout.webview, container, false);

    return mView;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    mContext = (LoginWebActivity) getActivity();
    initFragment();

}

@Override
public void onResume() {

    super.onResume();
}

/**
 * Initialises the views and variables of the fragment.
 */
@SuppressLint({ "JavascriptInterface", "SetJavaScriptEnabled" })
protected void initFragment() {


    mWebView = (WebView) mView.findViewById(R.id.webView);
    Bundle b = mContext.getIntent().getExtras();
    if (b != null) {
        mUrl = b.getString(Constants.EXTRA_WEB_LOGIN_URL);
    }
    super.initFragment();

    setHasOptionsMenu(true);
}

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Navigate
    switch (item.getItemId()) {
    case R.id.menu_item_signup:
        mContext.onSignUpClick();
        break;
    case android.R.id.home:
        if (!goBack())
            getActivity().finish();
    default:
        break;
    }
    return super.onOptionsItemSelected(item);
}

我的 XML:

<?xml version="1.0" encoding="utf-8"?>
<item
    android:id="@+id/menu_item_signup"
    allergy:showAsAction="ifRoom"
    android:title="@string/sign_up">
</item>

在此输入图片描述


你是从fragment中添加菜单选项的,对吗?你创建了多个fragments吗? - Szymon
我有一个活动,基本上当用户点击登录按钮时会显示一个Web视图。我基本上正在用另一个片段替换现有的片段。 - Ganesh
2
那么每个片段是否可以添加一个操作栏选项呢?您能将该选项移动到活动中吗? - Szymon
这是解决我的问题的方法:https://dev59.com/WWDVa4cB1Zd3GeqPifuc#16582895 - CaptainNemo
5个回答

68
您需要在添加项目之前清空菜单对象。我曾遇到过同样的问题,这是我找到的最佳解决方案。

您需要在添加项目之前清空菜单对象。我曾遇到过同样的问题,这是我找到的最佳解决方案。

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

另外,当我改用App Compact时,我必须确保在一个地方引用菜单,而不是在Activity及其子片段中引用。 - User3
1
@Renan 这也清除了我的常规活动菜单。请帮忙。 - Roon13

26

虽然来晚了,但对于任何像我一样通过谷歌找到这里的人,这才是真正的问题。

您没有发布创建片段的Activity代码,但我猜测它看起来像这样:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_layout);
        Fragment fragment = ...
        getSupportFragmentManager()
            .beginTransaction()
            .add(R.id.fragment_container, fragment)
            .commit();
    }
这样做的问题在于,当活动经历其生命周期时(正如你所说,“当我离开设备空闲或与其他应用程序一起工作时”),系统会为您保存和恢复片段的状态。但是使用此代码,您还将向Activity添加一个新片段,因此您最终会在Activity中运行多个片段,每个片段都向菜单添加一个项目。
尽管发布的解决方法将解决重复菜单条目的问题,但它会留下这些额外的片段实例,显然这不是您想要的。
正确的修复方法是进行简单的空值检查:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_layout);

        if (savedInstanceState == null) {
            Fragment fragment = ...
            getSupportFragmentManager()
                .beginTransaction()
                .add(R.id.fragment_container, fragment)
                .commit();
        }
    }

由于系统将使用非空 Bundle 对象作为 savedInstanceState 参数指示正在重新创建活动,因此您可以检查该对象来确定是否应该创建并添加新的 Fragment。

希望这可以帮到您。


谢谢dominicoder,我也认为这是最好的解决方案。 - Dezo

4
我使用了Renan Bandeira的优秀解决方案,但出现了一些错误,所以我对其进行了一些修改,并且也适用于我的情况。现在分享我的经验:也许这可以再次有所帮助,所有功劳都归功于他的卓越解决方案。
@Override
    public void onCreateOptionsMenu(Menu menu ) {
       menu.clear();
       MenuInflater inflater = getMenuInflater();    
       inflater.inflate(R.menu."your current activity name ", menu);
    return true;
}

4
为什么在无返回值方法中要使用"return true"? - Robust

2
我遇到了与@Szymon所述完全相同的问题:“我从片段添加菜单选项,我创建多个片段?”因此,我的解决方案如下所示。
onCreate:
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    menu.clear();
    inflater.inflate(R.menu.menu, menu);
    menu.findItem(R.id.action_one).setVisible(true);
    menu.findItem(R.id.action_two).setVisible(false);
    super.onCreateOptionsMenu(menu, inflater);
}

onPrepare:

@Override
public void onPrepareOptionsMenu(Menu menu) {
    if (isAdded()
            && !isDetached()
            && isVisible()
            && !isRemoving()
            )
    {
        // show the menu
        if (menu.findItem(R.id.action_one).isVisible())
            menu.findItem(R.id.action_one).setVisible(true);
        // hide the menu
        if (menu.findItem(R.id.action_two).isVisible())
            menu.findItem(R.id.action_two).setVisible(false);
    }
}

0
你应该使用以下方法,这样就不会再看到重复项了(请注意它只有一个菜单对象作为参数)。
  @Override
    public boolean onCreateOptionsMenu( Menu menu )
    {
        getMenuInflater().inflate( R.menu.main_activity_menu, menu );
        return true;
    }

Santiago请注意他在Fragment中调用了onCreateOptionsMenu,而不是在Activity中。 - Dezo

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