如何更改 Android 上选项菜单上的 MenuItem?

发布于 2024-10-03 01:00:41 字数 1242 浏览 0 评论 0原文

我的 Activity 上有一个带有 MenuItem“Start”的选项菜单。当选择此 MenuItem 时,我想更改菜单,使其包含 MenuItem “Stop”。最后,当选择“停止”时,我想改回“开始”。

这是我的代码中无法正常工作的部分。我在 mymenu.xml 中列出了“Start”和“Stop”,我应该在创建菜单时删除“stop”:

public class MyActivity extends Activity {
    private boolean isStarted = false;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        menu.removeItem(R.id.stop);
        inflater.inflate(R.menu.mymenu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.start:
            isStarted = true;
            return true;
        case R.id.stop:
            isStarted = false;
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        if(isStarted) {
            menu.removeItem(R.id.start);
            menu.add(R.id.stop);
        } else {
            menu.removeItem(R.id.stop);
            menu.add(R.id.start);
        }
        return true;
    }
}

I have an Options Menu on my Activity with an MenuItem "Start". When this MenuItem is selected I would like to alter the Menu so it contains a MenuItem "Stop". And finally when "Stop" is selected, I would like to alter back to "Start".

Here is parts of my code that isn't working. I have both "Start" and "Stop" listed in mymenu.xml I should probably remove "stop" when the menu is created:

public class MyActivity extends Activity {
    private boolean isStarted = false;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        menu.removeItem(R.id.stop);
        inflater.inflate(R.menu.mymenu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.start:
            isStarted = true;
            return true;
        case R.id.stop:
            isStarted = false;
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        if(isStarted) {
            menu.removeItem(R.id.start);
            menu.add(R.id.stop);
        } else {
            menu.removeItem(R.id.stop);
            menu.add(R.id.start);
        }
        return true;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

涙—继续流 2024-10-10 01:00:41

对于此类操作,我通常选择不更改菜单项,而只是隐藏不需要的菜单项:

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    menu.findItem(R.id.start).setVisible(!isStarted);
    menu.findItem(R.id.stop).setVisible(isStarted);
    return true;
}

For this type of operation I usually choose not to alter the menu items, but just hide the ones you don't need:

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    menu.findItem(R.id.start).setVisible(!isStarted);
    menu.findItem(R.id.stop).setVisible(isStarted);
    return true;
}
绝不放开 2024-10-10 01:00:41

Flygenring 答案是正确的,但 menu.findItem() 很滞后,并且在 onPrepareOptionsMenu(Menu menu) 中调用它会产生糟糕的用户体验。最好在创建菜单时获取一次 MenuItem 对象,然后每次菜单出现在屏幕上时调用 setVisible :

    MenuItem mDynamicMenuItem;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        // Get dynamic menu item
        mDynamicMenuItem = menu.findItem(R.id.menu_item);
        return true;
    }

    // Prepare the Screen's standard options menu to be displayed. This is called right 
    // before the menu is shown, every time it is shown. You can use this method to
    // efficiently enable/disable items or otherwise dynamically modify the contents.
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);
        // Here is just a good place to update item
        mDynamicMenuItem.setVisible(isVisible);
        return true;
    }

Flygenring answer is correct, but menu.findItem() is laggy and calling it within onPrepareOptionsMenu(Menu menu) produces bad user experience. It's better to get MenuItem object once while creating menu, and then just call setVisible each time menu occures on screen:

    MenuItem mDynamicMenuItem;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        // Get dynamic menu item
        mDynamicMenuItem = menu.findItem(R.id.menu_item);
        return true;
    }

    // Prepare the Screen's standard options menu to be displayed. This is called right 
    // before the menu is shown, every time it is shown. You can use this method to
    // efficiently enable/disable items or otherwise dynamically modify the contents.
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);
        // Here is just a good place to update item
        mDynamicMenuItem.setVisible(isVisible);
        return true;
    }
成熟稳重的好男人 2024-10-10 01:00:41

完成更改后,您可能需要调用 super.onPrepareOptionsMenu。来自 文档

派生类应始终调用
直到基类
实施。

You probably need to call super.onPrepareOptionsMenu after you are finished making your changes. From the docs:

Deriving classes should always call
through to the base class
implementation.

倾`听者〃 2024-10-10 01:00:41

我得到了解决方案。调用 removeItem() 时,您基本上是在删除 MenuItem,从而也删除了引用。使用此代码有效。

private boolean isStarted = false;

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case 1:
        isStarted = true;
        return true;
    case 0:
        isStarted = false;
        return true;
    default:
        return super.onOptionsItemSelected(item);
    }
}

@Override
public boolean onPrepareOptionsMenu(Menu menu) {

    if(isStarted) {
        menu.removeItem(1);
        menu.add(0, 0, 0, "Stop");
    } else {
        menu.removeItem(0);
        menu.add(0, 1, 0, "Start");
    }

    return super.onPrepareOptionsMenu(menu);
}

您必须再次创建 MenuItem。这也是 false 标签的原因。实际上,当您通过代码创建 Menu 时,您不需要 MenuInflater,因此也不需要任何菜单 XML 文件。

I got the solution. You are basically deleting the MenuItem when calling removeItem() thus also deleting the reference. Using this code works.

private boolean isStarted = false;

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case 1:
        isStarted = true;
        return true;
    case 0:
        isStarted = false;
        return true;
    default:
        return super.onOptionsItemSelected(item);
    }
}

@Override
public boolean onPrepareOptionsMenu(Menu menu) {

    if(isStarted) {
        menu.removeItem(1);
        menu.add(0, 0, 0, "Stop");
    } else {
        menu.removeItem(0);
        menu.add(0, 1, 0, "Start");
    }

    return super.onPrepareOptionsMenu(menu);
}

You have to create the MenuItem again. Thats also the reason for the false label. Actually you don't need the MenuInflater as you create the Menu via code so also no need for any menu XML file.

寄风 2024-10-10 01:00:41

感谢这篇文章中的信息,因为它解决了我的菜单中的错误标签问题。我确实必须稍微修改它,并得到运行良好的最终代码,如下所示,希望它能为其他人节省一些时间和挫败感。它的解决方案略有不同,但我所做的主要更改是将 .setVisible 设置为 True 或 False,除此之外 i.shadrins 解决方案最适合我的需求。

    @Override
public boolean onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);

    if(loggedIn) 
    {
        logIn.setVisible(false);
        logOut.setVisible(true);
    } 
    else 
    {
        logIn.setVisible(true);
        logOut.setVisible(false);
    }
    return true;
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    logIn = menu.findItem(R.id.loggedOut);
    logOut = menu.findItem(R.id.loggedIn);
    return true;
}

thanks for the info in this post as it solved my problem of the false labels in my menu. I did have to modify it slightly and have the final code that works well as follows in the hope it saves someone else some time and frustration. Its a slightly different solution but the main change I made was the .setVisible to either True or False, apart from that i.shadrins solution was the best fit for my needs.

    @Override
public boolean onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);

    if(loggedIn) 
    {
        logIn.setVisible(false);
        logOut.setVisible(true);
    } 
    else 
    {
        logIn.setVisible(true);
        logOut.setVisible(false);
    }
    return true;
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    logIn = menu.findItem(R.id.loggedOut);
    logOut = menu.findItem(R.id.loggedIn);
    return true;
}
冰雪梦之恋 2024-10-10 01:00:41

在Android 3.0及更高版本上,您应该调用invalidateOptionsMenu()来请求系统调用onPrepareOptionsMenu()。然后您可以修改该方法中的选项菜单。您可以在此处查看 Android 文档的在运行时更改菜单项部分 https://developer.android.com/guide/topics/ui/menus#options-menu 了解更多详细信息。

On Android 3.0 and higher, you should call invalidateOptionsMenu() to request that the system calls onPrepareOptionsMenu(). You can then modify the options menu in the method. You can check the Changing menu items at runtime section of the Android documentation here https://developer.android.com/guide/topics/ui/menus#options-menu for more details.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文