如何在Android中动态更改菜单项文本

233

我正在尝试在onOptionsItemSelected(MenuItem item)方法之外更改菜单项的标题。

我已经做了以下操作;

public boolean onOptionsItemSelected(MenuItem item) {
  try {
    switch(item.getItemId()) {
      case R.id.bedSwitch:
        if(item.getTitle().equals("Set to 'In bed'")) {
          item.setTitle("Set to 'Out of bed'");
          inBed = false;
        } else {
          item.setTitle("Set to 'In bed'");
          inBed = true;
        }
        break;
    }
  } catch(Exception e) {
    Log.i("Sleep Recorder", e.toString());
  }
  return true;
}

但是我希望能够在这个方法之外修改特定菜单项的标题。


https://dev59.com/U2w05IYBdhLWcg3wuUKY#32072318 应该被接受为答案。 - Akhil Dad
13个回答

386

我建议在Activity中保留对你在onCreateOptionsMenu中接收到的菜单对象的引用,然后在需要更改菜单项时使用它来检索。例如,你可以按以下方式进行操作:

public class YourActivity extends Activity {

  private Menu menu;
  private String inBedMenuTitle = "Set to 'In bed'";
  private String outOfBedMenuTitle = "Set to 'Out of bed'";
  private boolean inBed = false;

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

    // Create your menu...

    this.menu = menu;
    return true;
  }

  private void updateMenuTitles() {
    MenuItem bedMenuItem = menu.findItem(R.id.bedSwitch);
    if (inBed) {
      bedMenuItem.setTitle(outOfBedMenuTitle);
    } else {
      bedMenuItem.setTitle(inBedMenuTitle);
    }
  }

}

或者,你可以重写onPrepareOptionsMenu方法,在每次显示菜单时更新菜单项。


1
我总是期望Android能够有更优雅的解决方案来解决这些问题。看起来最简单的答案往往是最好的 - 谢谢。 - Steven

150

正如JxDarkAngel建议的那样,您可以在Activity的任何地方调用此函数:

invalidateOptionsMenu();

然后覆盖:

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
  MenuItem item = menu.findItem(R.id.bedSwitch);
    if (item.getTitle().equals("Set to 'In bed'")) {
        item.setTitle("Set to 'Out of bed'");
        inBed = false;
    } else {
        item.setTitle("Set to 'In bed'");
        inBed = true;
    }
  return super.onPrepareOptionsMenu(menu);
}

这是一个更好的选择。我使用了来自https://stackoverflow.com/a/17496503/568197的答案。


最佳方案。因为这个重写了Android方法,而不是重新发明轮子。 - Azlan Jamal
请注意 onPrepareOptionsMenu() 在 Android 框架中被频繁调用,例如在显示 Activity 时和每次显示菜单时。因此,如果您的菜单不经常更改,则可能不太高效。 - Mr-IDE
1
invalidateOptionsMenu() 也会调用 onCreateOptionsMenu(),因此您可以将更新逻辑放在 onCreateOptionsMenu() 中。 - Mr-IDE
@Garbit已更新,使用了您在原始问题中的代码! - Todd DeLand
1
接受 - 永恒的因果等待着 :) - Garbit

13

你可以创建一个全局的“Menu”对象,然后在onCreateOptionsMenu中进行赋值。

public class ExampleActivity extends AppCompatActivity
    Menu menu;

然后在这里分配

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu, menu);
    this.menu = menu;
    return true;
}

然后稍后使用已分配的菜单对象来获取所需项目

menu.findItem(R.id.bedSwitch).setTitle("Your Text");

这是我最初想到的解决方案,它起作用了,谢谢。 - jokermt235

5
创建一个setOptionsTitle()方法,并在您的类中设置一个字段。例如:
String bedStatus = "Set to 'Out of Bed'";

...

public void setOptionsTitle(String status)
{
    bedStatus = status;

}

现在当菜单被填充时,将标题更改为您的状态:

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

        menu.add(bedStatus);


        // Return true so that the menu gets displayed.
        return true;
    }

我需要在活动渲染后设置它。因此不能在这两个方法内部设置。 - Garbit
在您的活动被渲染后的任何时候调用setOptionsTitle。我猜我不理解你的需求,因为“我需要在活动被呈现之后设置它”对我来说意味着在调用setContent(R.layout.id)之后,您可能需要更改选项菜单显示的内容(您可以使用setOptionsTitle() - 从任何方法、任何地方、任何时间)。 - Jack
虽然这种方法确实可行,但不建议使用,因为管理菜单的菜单对象不知道标题何时更改,因此无法执行可能需要在标题更改时执行的任务,例如布局和换行。 - Charles Harley

3
我使用这段代码来自定义我的底部导航项。
BottomNavigationView navigation = this.findViewById(R.id.my_bottom_navigation);
Menu menu = navigation.getMenu();
menu.findItem(R.id.nav_wall_see).setTitle("Hello");

3

建议使用override onPrepareOptionsMenu方法

menu.Clear ();
   if (TabActual == TabSelec.Anuncio)
   {
       menu.Add(10, 11, 0, "Crear anuncio");
       menu.Add(10, 12, 1, "Modificar anuncio");
       menu.Add(10, 13, 2, "Eliminar anuncio");
       menu.Add(10, 14, 3, "Actualizar");
   }
   if (TabActual == TabSelec.Fotos)
   {
       menu.Add(20, 21, 0, "Subir foto");
       menu.Add(20, 22, 1, "Actualizar");
   }
   if (TabActual == TabSelec.Comentarios)
   {
       menu.Add(30, 31, 0, "Actualizar");
   }

Here an example


确实,使用预期的方法。 :) 如果您决定保留对菜单的本地引用,则需要担心上下文泄漏,我认为是这样的。或者也许不需要。但是肯定不会出现这种情况。 - William T. Mallard

2
声明你的菜单字段。
private Menu menu;

以下是onCreateOptionsMenu()方法:
public boolean onCreateOptionsMenu(Menu menu) {
this.menu = menu;
    try {
        getMenuInflater().inflate(R.menu.menu_main,menu);
    } catch (Exception e) {
        e.printStackTrace();
        Log.i(TAG, "onCreateOptionsMenu: error: "+e.getMessage());
    }
    return super.onCreateOptionsMenu(menu);
}

下面是您的名称设置活动。可以通过按钮点击或条件代码来实现。
public void setMenuName(){
menu.findItem(R.id.menuItemId).setTitle(/*Set your desired menu title here*/);
}

这对我很有帮助。

1
您可以使用以下代码更改菜单项文本:-
 fun showPopup(v: View) {
        popup = PopupMenu(context, v)
        val inflater = popup?.menuInflater
        popup?.setOnMenuItemClickListener(this)
        inflater?.inflate(R.menu.menu_main, popup?.menu)
        val menu: Menu = popup!!.menu
        val item = menu.findItem(R.id.name)
        if (item.title.equals("Name")) {
            item.title = "Safal Bhatia"
        }
}

1
您可以像这样做,不需要专门变量:
Toolbar toolbar = findViewById(R.id.toolbar);
Menu menu = toolbar.getMenu();
MenuItem menuItem = menu.findItem(R.id.some_action);
menuItem.setTitle("New title");

或者稍微简化一下:
MenuItem menuItem = ((Toolbar)findViewById(R.id.toolbar)).getMenu().findItem(R.id.some_action);
menuItem.setTitle("New title");

只有在菜单创建后才能正常工作。


如果您使用标准工具栏作为默认主题,则它可以正常工作,但如果您使用自定义工具栏,则无法正常工作。 - jokermt235
1
是的,菜单来自于:“Menu menu = toolbar.getMenu();”。否则需要添加您自定义的菜单... - IQ.feature

0

对于需要静态设置标题的人。 这可以在AndroidManifest.xml中完成

<activity
    android:name=".ActivityName"
    android:label="Title Text" >
</activity>

Options Menu Title Text


3
问题是动态的,而不是静态的! - EngineSense
仍然出现在谷歌搜索中并帮助了我,感谢您的发布。 - bruchowski

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