如何为菜单项设置标签?

14

我正在为Android构建一个弹出菜单,并且需要在每个菜单项中存储一些ID。 这些ID是字符串,因此如果我可以将字符串数组设置为MenuItem,那就太好了。

问题是MenuItem没有setTag方法。

还有其他方法可以将数据附加到它上面吗?

编辑: Geobits提到了getActionView();

不幸的是,它返回null。

但是,执行以下操作是否安全?

 View view = new View(getActivity());
 view.setTag(tag);
 menuItem.setActionView(view);
2个回答

16
每个MenuItem都有一个关联的View,称为ActionView。如果您正在使用自定义的ActionView,则可以使用MenuItem.getActionView()获取它,并在其上设置/检索标记。
例如,要设置标记:
public void setMenuItemTag(MenuItem item, Object tag)
{
    View actionView = item.getActionView();
    actionView.setTag(tag);
}

编辑

如果您没有使用自定义的ActionView,您可以使用HashMap来存储标签。将MenuItem用作键。

public void setMenuItemTag(MenuItem item, Object tag)
{
    myMap.put(item, tag);
}

// returns null if tag has not been set(or was set to null)
public Object getMenuItemTag(MenuItem item, Object tag)
{
    return myMap.get(item);
}

5
getActionView 返回 null。 - Arturs Vancans
啊,那么你可以设置一个 HashMap<MenuItem, Object> 来存储它们。 - Geobits
使用 HashMap 是否更好,还是像我在帖子中添加的那样做? - Arturs Vancans
我从未尝试过你编辑的方式,但我认为那会改变你的菜单项的外观/行为。使用哈希映射是可以的,而且足够简单。 - Geobits
好的。很好的回答。我会等一会儿,也许其他人会补充些什么。 - Arturs Vancans
1
在onCreateContextMenu中创建MenuItem时,您必须设置MenuItem.setActionView(yourView),然后才能调用MenuItem.getActionView(),否则它将为null。 - Vincy

0
一种在不使用自定义视图时设置标签的巧妙方法。 这个想法很简单,就是在实际视图创建后,我们尝试通过它的文本和图标找到它。
private void addButtonToMenu(Toolbar toolbar, Menu menu, String title, Drawable icon, String testId) {
    MenuItem menuItem = menu.add(title);
    if (icon != null){
        menuItem.setIcon(icon);
    }
    setTestId(toolbar, title, icon, testId);
}

private void setTestId(Toolbar toolbar, String title, Drawable icon, String testId) {
    UiUtils.runOnPreDrawOnce(toolbar, () -> {
        ActionMenuView buttonsLayout = ViewUtils.findChildByClass(toolbar, ActionMenuView.class);
        List<TextView> buttons = ViewUtils.findChildrenByClass(buttonsLayout, TextView.class);
        for (TextView view : buttons) {
            if (!TextUtils.isEmpty(title) && title.equals(view.getText())) {
                view.setTag(testId);
            } else if (icon != null && ArraryUtils.containes(view.getCompoundDrawables(), icon)) {
                view.setTag(testId);
            }
        }
    });
}

// Helper functions

public class UiUtils {

    public static void runOnPreDrawOnce(final View view, final Runnable task) {
        view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                view.getViewTreeObserver().removeOnPreDrawListener(this);
                task.run();
                return true;
            }
        });
    }
}

public class ArrayUtils {
    public static boolean contains(Object[] array, Object item) {
        if (isNullOrEmpty(array)) return false;
        for (Object o : array) {
            if (o == item) return true;
        }
        return false;
    }

    private static boolean isNullOrEmpty(Object[] array) {
        return array == null || array.length == 0;
    }
}

public class ViewUtils {
    @Nullable
    public static <T> T findChildByClass(ViewGroup root, Class clazz) {
        for (int i = 0; i < root.getChildCount(); i++) {
            View view = root.getChildAt(i);
            if (clazz.isAssignableFrom(view.getClass())) {
                return (T) view;
            }

            if (view instanceof ViewGroup) {
                view = findChildByClass((ViewGroup) view, clazz);
                if (view != null && clazz.isAssignableFrom(view.getClass())) {
                    return (T) view;
                }
            }
        }
        return null;
    }

    public static <T> List<T> findChildrenByClass(ViewGroup root, Class clazz) {
        List<T> ret = new ArrayList<>();
        for (int i = 0; i < root.getChildCount(); i++) {
            View view = root.getChildAt(i);
            if (clazz.isAssignableFrom(view.getClass())) {
                ret.add((T) view);
            }
        }
        return ret;
    }
}

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