如何动态创建菜单项?

Posted

技术标签:

【中文标题】如何动态创建菜单项?【英文标题】:How can I dynamically create menu items? 【发布时间】:2013-03-12 21:16:14 【问题描述】:

我正在构建一个 android 应用程序,我正在尝试构建一个用户管理系统,用户可以在其中登录、注销等。如果用户已注销,我想显示一个登录菜单项,如果用户退出,我想显示一个注销按钮用户已登录。如何动态执行此操作?

这是现在的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:id="@+id/add" android:title="Add" android:icon="@drawable/ic_menu_add"/>
  <item android:id="@+id/list" android:title="List" android:icon="@drawable/ic_menu_list"/>
  <item android:id="@+id/refresh" android:title="Refresh" android:icon="@drawable/ic_menu_refresh"/>
  <item android:id="@+id/login" android:title="Login" android:icon="@drawable/ic_menu_login"/>
</menu>

这是我现在的 Java:

@Override
public boolean onCreateOptionsMenu(Menu menu) 
    new MenuInflater(this).inflate(R.menu.activity_main, menu);
    return(super.onCreateOptionsMenu(menu));


@Override
public boolean onOptionsItemSelected(MenuItem item) 

    System.out.println(item.getItemId()==R.id.add);
    if (item.getItemId()==R.id.add)
    
        //Cannot add spot unless we have obtained the users current location. 
        if((currentLat != 0) && (currentLng != 0))
        

            System.out.println("loggedin? : "  + auth.isLoggedIn());
            if(!auth.isLoggedIn())
            
                Toast.makeText(MainActivity.this, "You must be logged in to add a new spot",
                        Toast.LENGTH_LONG).show();
            
            else
            


                Intent addIntent = new Intent(MainActivity.this, AddSpot.class);
                Bundle b = new Bundle();
                b.putDouble("currentLat", currentLat);
                b.putDouble("currentLng", currentLng);
                addIntent.putExtras(b);
                startActivity(addIntent);
                return(true);
            
        
       
    else if(item.getItemId()==R.id.list)
    
        //Pointless showing them a blank screen if nothing is retrieved from the server
        if(list != null)
        
            Intent listIntent = new Intent(MainActivity.this, ListLocations.class);
            listIntent.putExtra("list", list);
            startActivity(listIntent);
            return(true);
        
    

    if(item.getItemId()==R.id.refresh)
    
        finish();
        startActivity(getIntent());
        return(true);       
    

    if(item.getItemId()==R.id.login)
    
        Intent loginIntent = new Intent(MainActivity.this, LoginActivity.class);
        startActivity(loginIntent);
        return(true);   
    

    return(super.onOptionsItemSelected(item));

【问题讨论】:

【参考方案1】:

您可以调用invalidateOptionsMenu()(注意:需要使用actionBarSherlock之类的兼容库才能访问,以防需要支持低API版本),然后根据状态更新菜单项。

您可以在此处隐藏登录操作项并显示注销操作项。

您也可以尝试更新图标本身,但我从未尝试过。

【讨论】:

不错的额外触摸。有必要将 LOGIN 替换为 LOGOUT 图标,例如问过的@johnathan-au,因为这会导致再次调用 onPrepareOptionsMenu()【参考方案2】:

如何向 Android Activity 动态添加菜单项

public class yourActivity extends Activity 
    ...
    private static final int MENU_ADD = Menu.FIRST;
    private static final int MENU_LIST = MENU.FIRST + 1;
    private static final int MENU_REFRESH = MENU.FIRST + 2;
    private static final int MENU_LOGIN = MENU.FIRST + 3;

    /**
     * Use if your menu is static (i.e. unchanging)
     */
    /*
    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        super.onCreateOptionsMenu(menu);
        menu.add(0, MENU_ADD, Menu.NONE, R.string.your-add-text).setIcon(R.drawable.your-add-icon);
        menu.add(0, MENU_LIST, Menu.NONE, R.string.your-list-text).setIcon(R.drawable.your-list-icon);
        menu.add(0, MENU_REFRESH, Menu.NONE, R.string.your-refresh-text).setIcon(R.drawable.your-refresh-icon);
        menu.add(0, MENU_LOGIN, Menu.NONE, R.string.your-login-text).setIcon(R.drawable.your-login-icon);
        return true;
    
    */

    /**
     * Gets called every time the user presses the menu button.
     * Use if your menu is dynamic.
     */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) 
        menu.clear();
        if(enableAdd)
            menu.add(0, MENU_ADD, Menu.NONE, R.string.your-add-text).setIcon(R.drawable.your-add-icon);
        if(enableList)
            menu.add(0, MENU_LIST, Menu.NONE, R.string.your-list-text).setIcon(R.drawable.your-list-icon);
        if(enableRefresh)
            menu.add(0, MENU_REFRESH, Menu.NONE, R.string.your-refresh-text).setIcon(R.drawable.your-refresh-icon);
        if(enableLogin)
            menu.add(0, MENU_LOGIN, Menu.NONE, R.string.your-login-text).setIcon(R.drawable.your-login-icon);
        return super.onPrepareOptionsMenu(menu);
    

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
        super.onOptionsItemSelected(item);

        switch (item.getItemId()) 
        case MENU_ADD: doAddStuff(); break;
        case MENU_LIST: doListStuff(); break;
        case MENU_REFRESH: doRefreshStuff(); break;
        case MENU_LOGIN: doLoginStuff(); break;
        
        return false;
    

如果用户已登录,以下具体示例会添加一个 MENU_LOGOUT 选项。

    private static final int MENU_LOGOUT = MENU.FIRST + 4;

    public boolean onPrepareOptionsMenu(Menu menu) 
        ...
        if(auth.isLoggedIn()) 
            menu.add(0, MENU_LOGOUT, Menu.NONE, R.string.your-logout-text).setIcon(R.drawable.your-logout-icon);
        
        ...
    

    public boolean onOptionsItemSelected(MenuItem item) 
        ...
        case MENU_LOGOUT:
            if(auth.isLoggedIn()) 
                doLogout();
             else 
                Toast.makeText(this, "You must have somehow been logged out between the time the menu button was pressed and now.", Toast.DURATION_LONG).show();
            
            break;
        ...
    

仅此而已。

【讨论】:

您好,谢谢。如果用户登录,您能否提供一个显示注销的示例?我将使用哪种方法添加此逻辑?另外,我不明白变量 MENU_ADD...等 完成。请参阅上面的更新答案。 menuId 值是必需的,以便您在处理 onOptionsItemSelected() 中的菜单活动时知道用户按下了哪个菜单项。 好的,很好。还有几个问题。 onPrepareOptionsMenu 方法,我是否必须重新创建所有其他项目,或者您添加的逻辑是否足够? MENU_LOGOUT 变量,不是 +3 而不是 +4,因为它会在 MENU_LOGIN 变得可见时替换它? 您必须为每个项目重新创建 if() 逻辑。在 onPrepareOptionsMenu() 中,您必须放置逻辑来决定是否应显示菜单项。作为一种好的做法,您还应该在 onOptionsItemSelected() 中重新创建相同的逻辑。这是为了以防万一在用户第一次按下菜单按钮和他最终按下特定菜单项按钮之间的潜在较长时间间隔内发生变化(即,他在选择一个项目之前离开菜单显示的时间)。不要忘记投票(三角形)并接受(检查)正确答案。 项目 id 值(即 MENU_LOGOUT)不必是连续的。它们可以是任何数字。您可以拥有任意数量的。只是不要重复任何值。在任何时候只显示您需要的那些。因此,可以为每个可能的菜单标签设置一个,即使有些很少显示。【参考方案3】:

在我的情况下,菜单项在 ArrayList 中, - 试试这个希望它会帮助你 :)

public void onClick(View v)

    PopupMenu menu = new PopupMenu(DialogCheckBox.this, v);
    for (String s : limits)  // "limits" its an arraylist  
        menu.getMenu().add(s);
    
    menu.show();

【讨论】:

谢谢,这太棒了。正是我要找的东西 能否请您解释一下,我如何在其项目上应用点击监听器【参考方案4】:

创建菜单项的简单方法:

Dynamic_PopUpMenu.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                PopupMenu menu = new PopupMenu(DialogCheckBox.this, v);
                menu.getMenu().add("AGIL"); // menus items 
                menu.getMenu().add("AGILANBU"); // menus items
                menu.getMenu().add("AGILarasan");
                menu.getMenu().add("Arasan");
                menu.show();
            
        );

试试这个:)

【讨论】:

【参考方案5】:

很简单

创建菜单

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

    for (int i = 0; i < list.size(); i++) 
        menu.add(0, i, 0, "Menu Name").setShortcut('5', 'c');
    

    return true;

从点击的菜单中获取详细信息

@Override
public boolean onOptionsItemSelected(MenuItem item) 

    int id = item.getItemId(); //to get the selected menu id
    String name = item.getTitle(); //to get the selected menu name

    return super.onOptionsItemSelected(item);

【讨论】:

【参考方案6】:
private void getPopup(final TextView textView, ArrayList<String> arrayList) 
        final PopupMenu popupMenu = new PopupMenu(sContext, textView);
        for (int i = 0; i < arrayList.size(); i++) 
            popupMenu.getMenu().add(arrayList.get(i));
        
        popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() 
            @Override
            public boolean onMenuItemClick(MenuItem item) 
                textView.setText(item.getTitle());
                return false;
            
        );
        popupMenu.show();
    

【讨论】:

如果您的数据来自 APIs 并且您在 Popup 中显示数据,那么此代码可以帮助您。这也用于动态弹出窗口。

以上是关于如何动态创建菜单项?的主要内容,如果未能解决你的问题,请参考以下文章

无法销毁 Delphi 中动态创建的菜单项

无法销毁 Delphi 中动态创建的菜单项

怎么使用CSS3创建动态菜单

如何动态更改网页所选菜单项的颜色?

Delphi动态创建菜单

动态活动菜单项 Django