Элемент меню#getTag()

#android

#Android

Вопрос:

В подклассах View существует getTag() метод, который возвращает значение android:tag атрибута из .xml. Я хотел бы то же самое для MenuItem … можно ли просто привести его к View ? Потому что элементы item также допускают атрибут тега в .xml…

Обновление: Моя цель при этом — установить тег в формате .xml, т.Е. "notranslate" и запросить его во время выполнения (мы локализуем вручную во время выполнения, не спрашивайте …)

Комментарии:

1. MenuItem — это интерфейс, а не представление. какова ваша цель? я уверен, что есть другой способ добиться этого.

2. Обновил вопрос в соответствии с моей целью. Хотя MenuItem — это интерфейс, я бы надеялся, что объекты, присутствующие во время выполнения, являются скрытыми представлениями..

3. ну, я думаю, это могло бы быть возможно путем создания вашего собственного интерфейса MenuItem, но это звучит как много усилий для выполнения чего-то, что, безусловно, может быть сделано более стандартным способом .. рассматривали ли вы возможность использования одного int (getGroupId()) или одного char (getAlphabeticShortcut()) или обоих?

Ответ №1:

Всегда можно выполнить приведение, однако приведение any Interface не может быть проверено во время компиляции, только во время выполнения. Обычно по этой причине многие не рекомендуют использовать интерфейс, который вы не можете контролировать. Наличие правильного кода проверки ошибок — лучший способ гарантировать, что такое приведение не приведет к нарушению вашего кода.

Для приведения на самом деле не имеет значения, является ли MenuItem это Interface или a View , но объект, на который он ссылается, должен быть одним из подклассов View , если не самим View a. Если вы собираетесь применить его, try приведите и catch a ClassCastException на всякий случай, поскольку это ошибка, которая будет выдана во время выполнения.

Другой вариант заключается в том, что, поскольку MenuItem — это просто интерфейс, вы можете легко просто создать View подкласс, который использует MenuItem , позволяющий вам выполнять приведение. Если вы используете пользовательский, ContextMenu как это делают многие лаунчеры, то, скорее всего, ваш ответ почти завершен.

Надеюсь, это поможет, FuzzicalLogic

Ответ №2:

MenuItem — это интерфейс. Любой класс может реализовать этот интерфейс, и поэтому не всегда будет безопасно приводить MenuItem к представлению. Вы можете использовать оператор «instanceOf», чтобы проверить, действительно ли объект, реализующий интерфейс MenuItem, является представлением или нет.

Я понимаю, что вы хотите определить флаг в XML-определении меню, а затем во время выполнения запросить этот флаг, чтобы принять программное решение.

В документации по ресурсам меню записано, какие атрибуты могут быть установлены в XML. Вы можете рассмотреть возможность использования (злоупотребления) одного из этих параметров, такого как «android:alphabeticShortcut» для кодирования флага и использовать метод MenuItem::getAlphabeticShortcut() для получения значения. Для этого не требуется приведение — он просто использует существующие поля в XML-конструкции / классе MenuItem для ваших собственных целей.

Возможно, менее сложный способ сделать это — сохранить простую таблицу в отдельном файле ресурсов, в которой перечислены идентификаторы пунктов меню и специальное поведение, связанное с этим идентификатором, например, переводить или не переводить.

В качестве альтернативы создайте простой класс, в котором таблица с этой конфигурационной информацией жестко закодирована, используя логический идентификатор ресурса «@[ ][package:] id / имя_ресурса» в качестве ключей к таблице. Хотя это не сохраняет все это в одном месте (в XML), это делает это таким образом, чтобы не кодировать информацию в неиспользуемых атрибутах или полагаться на неизменяемые идентификаторы. «Таблица» может быть реализована как статический метод со встроенным оператором switch, позволяющим использовать такой код, как «if (TranslationTable.Следует перевести(MenuItem.getItemId())) { выполнить перевод }»

Ответ №3:

У меня была похожая проблема в том, что я хотел связать некоторые произвольные данные с каждым пунктом меню, чтобы я мог обрабатывать пункты меню общим способом без необходимости использовать жестко запрограммированные проверки для идентификаторов отдельных элементов в коде.

То, что я сделал, было для определенного пункта меню (например, @ id / foo) Существовал массив типов, который был определен с использованием того же имени, что и идентификатор элемента меню. Вы могли бы сделать это и с другими типами ресурсов.

Итак, чтобы выполнить ассоциацию, вы получаете имя элемента ресурса (foo в моем примере), а затем используете это для поиска идентификатора другого ресурса другого типа (@array / foo в моем примере).

В моем обработчике для меню у меня был такой код:

 Resources resources = getResources();
String name = resources.getResourceEntryName(item.getItemId());
int id = resources.getIdentifier(name, "array", "com.example");

if(id != 0)
{
    TypedArray data = resources.obtainTypedArray(id);

    // Use the typed array to get associated data
}
  

Редактировать:

На самом деле это даже проще, чем это. В идентификаторах пунктов меню нет ничего особенного, кроме того, что вам не нужны несколько пунктов меню с одинаковым идентификатором. Идентификатор не обязательно должен иметь вид @ id/foo. На самом деле это может также ссылаться на другие ресурсы. Итак, в моем примере выше, вместо того, чтобы указывать в меню идентификатор @ id / foo и использовать диспетчер ресурсов для поиска по нему @array / foo, я изменил, чтобы элемент меню действительно имел идентификатор @array / foo .

Теперь в моем onOptionsItemSelected у меня есть это:

 Resources resources = getResources();

if("array".equals(resources.getResourceTypeName(item.getItemId())))
{
    TypedArray data = resources.obtainTypedArray(item.getItemId());

    // Use the typed array
}