Как установить тег в MenuItem?
Я создаю всплывающее меню в android, и мне нужно сохранить некоторые идентификаторы в каждом элементе меню. Идентификаторы являются String, поэтому было бы неплохо, если бы я мог установить массив String в MenuItem.
Проблема в том, что MenuItem не имеет метода setTag.
Как еще я могу прикрепить к нему некоторые данные?
EDIT: Geobits упоминается о getActionView();
К сожалению, он возвращает null.
Однако можно ли сделать следующее?
View view = new View(getActivity());
view.setTag(tag);
menuItem.setActionView(view);
Ответы
Ответ 1
Каждый 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);
}
Ответ 2
Хакерный способ установки тегов при использовании пользовательских представлений. Идея довольно проста, после создания фактического представления мы пытаемся найти ее по ее тексту и значку
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;
}
}