13

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

问题是 MenuItem 没有 setTag 方法。

我还能如何附加一些数据呢?

编辑:Geobits 提到 getActionView();

不幸的是它返回null。

但是,是否可以节省执行以下操作?

 View view = new View(getActivity());
 view.setTag(tag);
 menuItem.setActionView(view);
4

2 回答 2

15

每个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);
}
于 2013-03-10T19:40:29.020 回答
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;
    }
}
于 2018-02-07T08:50:15.800 回答