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


212

我正在尝试从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;
}

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


Answers:


127

正如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框架经常调用它,例如,在显示“活动”时以及每次显示菜单时。因此,如果您的菜单不经常更改,这可能不是很有效。
Mr-IDE

1
invalidateOptionsMenu()也会调用onCreateOptionsMenu(),因此您可以将更新逻辑放入onCreateOptionsMenu()
Mr-IDE

如果您将其编辑为与问题相关,则将其标记为可接受的答案
Garbit

@Garbit更新为使用原始问题中的代码!
托德·迪兰德

375

我建议在活动中保留对您在onCreateOptionsMenu中收到的Menu对象的引用,然后使用该引用来检索需要更改的MenuItem(在需要时)。例如,您可以按照以下方式进行操作:

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对这类问题有一个更优雅的解决方案。似乎最简单的答案通常是最好的-谢谢。
史蒂芬·沃尔夫

12

您可以这样做,创建一个全局“菜单”对象,然后在onCreateOptionMenu中分配它

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对象获取必需的项目

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

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()进行操作-可以通过任何方法,随时随地进行操作)。
杰克

尽管此方法确实有效,但不推荐使用此方法,因为管理菜单的Menu对象将不知道标题何时更改,因此无法执行标题更改时可能需要执行的任务,例如布局和换行符。
Charles Harley

3

您最好使用重写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");
   }

是一个例子


确实,使用预期的方法。:)如果您决定保留对菜单的本地引用,您将需要担心上下文泄漏,我想。或者可能不是。但是肯定不是这种方法。
威廉·T·马拉德

3

我使用此代码来整理我的底部导航项

BottomNavigationView navigation = this.findViewById(R.id.my_bottom_navigation);
Menu menu = navigation.getMenu();
menu.findItem(R.id.nav_wall_see).setTitle("Hello");

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*/);
}

这对我有用。


0

在我看来,您想在本地方法中更改菜单的内容,并且无论何时发生事件或在活动UI线程中,都可以随时调用此方法。

当您覆盖此方法并在此方法中使用它时,为什么不在onPrepareOptionsMenu的全局变量中使用Menu的实例。确保在发生事件(例如单击按钮)时,或者在活动UI线程,处理程序或异步任务后执行时调用此方法。

您应该事先知道要更改的该菜单项的索引。清除菜单后,您需要添加菜单XML并更新项目的名称或图标。


0

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

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

选项菜单标题文字


3
问题是动态的,不是静态的!
EngineSense

仍然出现在Google搜索上,对我有所帮助,感谢您的发帖
bruchowski 16'5

0

我需要更改片段的菜单图标。对于片段,我对Charles的回答做了一些改动:

    private Menu top_menu;

    //...
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

       setHasOptionsMenu(true);
       //...
       rootview = inflater.inflate(R.layout.first_content,null);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.fragment_menu, menu);
        this.top_menu = menu;
    }


    // my procedure
    private void updateIconMenu() {
         if(top_menu!= null) {
             MenuItem nav_undo = top_menu.findItem(R.id.action_undo);
             nav_undo.setIcon( R.drawable.back);
         }
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.