Определение вида, выбранного в ContextMenu (Android)

В Android onContextItemSelected имеет один аргумент MenuItem и поэтому неясно, как идентифицировать выбранное представление. MenuItem.getMenuInfo предоставляет доступ к Contextmenu.ContextMenuInfo , но, хотя оба известных подкласса обеспечивают доступ к целевому представлению, на интерфейсе не появляется аксессор.

Один из вариантов заключается в том, чтобы сохранить View представленное в onCreateContextMenu в переменной частного класса, которая полагается на onCreateContextMenu не будет снова вызвана в активности перед onContextItemSelected . Другим является использование идентификатора представления для аргумента itemId для ContextMenu.add . Если мы это сделаем, нам нужно будет определить вариант, выбранный из контекстного меню, используя его (возможно, интернационализированное) название.

Каков наилучший метод идентификации View выбранного в onContextSelected ?

Не существует такой концепции, как «определение выбранного вида» для любого меню или контекстных меню в Android. Следовательно, на ваш вопрос довольно сложно ответить. Итак, я сделаю некоторые догадки.

Если, выбрав «Выбранный вид», вы имеете в виду, какой выбор меню был выбран, то есть getItemId() в MenuItem который передается onOptionsItemSelected() или onContextItemSelected() .

Если «идентифицировать вид выбранный» означает, какая строка в ListView была одной длинной, чтобы вызвать контекстное меню, getMenuInfo() (вызываемый в MenuItem ) в AdapterView.AdapterContextMenuInfo , затем используйте либо id либо Значения position в зависимости от вашего адаптера. См. Здесь пример проекта, который использует эту технику.

Если, «идентифицировав View selected», вы имеете в виду, что у вас есть несколько контекстных меню не ListView в действии, я бы не использовал эту технику пользовательского интерфейса.

Весь смысл контекстного меню заключается в том, что он связан с отдельным основным представлением, и это явно ограничение по дизайну в Android, что ассоциация теряется в обратном вызове 'onContextItemSelected'. Включение длинного касания в любом представлении достаточного размера представляется вполне разумным в качестве альтернативы щелчку правой кнопки мыши.

Как и другие должности, рекомендуется в некоторых контекстах:

 AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo(); 

Является подходящим, и targetView является полезной контрольной точкой.

Другой способ заключается в подклассе представления и переопределении 'getContextMenuInfo' для предоставления ссылки на представление. Например, простой TextView:

 Пакет ...;

 Открытый класс TextViewWithContext расширяет TextView {
     TextViewContextMenuInfo _contextMenuInfo = null;

     Public TextViewWithContext (контекст контекста) {
         супер (контекст);
         _contextMenuInfo = новый TextViewContextMenuInfo (this);
     }

     Public TextViewWithContext (контекст контекста, AttributeSet attrs) {
         Супер (контекст, attrs);
         _contextMenuInfo = новый TextViewContextMenuInfo (this);
     }   

     Protected ContextMenuInfo getContextMenuInfo () {
         Return _contextMenuInfo;
     }

     Public boolean isContextView (ContextMenuInfo menuInfo) {
         Return menuInfo == (ContextMenuInfo) _contextMenuInfo;
     }

     Защищенный класс TextViewContextMenuInfo реализует ContextMenuInfo {
         Protected TextView _textView = null;

         Защищенный TextViewContextMenuInfo (TextView textView) {
             _textView = textView;
         }
     }
 }

 ...
     @Override
     Public boolean onContextItemSelected (элемент MenuItem) {   

         ContextMenuInfo menuInfo = item.getMenuInfo ();

         If (textViewWithContext.isContextView (menuInfo) {
             ...
         }
     }

Наконец, было бы более полезно, если базовому классу View был назначен объект ContextInfo с обратной ссылкой на представление, а не null, как в настоящее время.

Class TestActivity расширяет действие {

 // create temp item here private ImageView tmpImageView = null; 

 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo){ super.onCreateContextMenu(menu, v, menuInfo); // initialize temp item mCurrentStatusImage = (ImageView) v.findViewById(R.id.rule_status); } public boolean onContextItemSelected(MenuItem item) { switch (item.getItemId()) { case ENABLE_ID: // use temp item tmpImageView.setImageResource(android.R.drawable.presence_online); return super.onContextItemSelected(item); case DISABLE_ID: // use temp item tmpImageView.setImageResource(android.R.drawable.presence_invisible); return super.onContextItemSelected(item); default: return super.onContextItemSelected(item); } 

Я установил аналогичную проблему, установив идентификатор groupID для MenuItem, на основе которого отправлен элемент, например:

  textview.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() { @Override public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) { menu.setHeaderTitle("Context Menu"); menu.add(R.id.whateverviewclicked, RENAME_MENU_ITEM, 0, "Rename"); menu.add(R.id.whateverviewclicked, DELETE_MENU_ITEM, 1, "Delete"); } }); 

Это позволит вам получить идентификатор groupID в onContextItemSelected:

 public boolean onContextItemSelected(MenuItem aItem) { int selectedViewID = aItem.getGroupId(); int selectedItem = aItem.getItemId(); }; 

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

Если вы прикрепляете ContextMenus к нескольким представлениям, которые НЕ находятся в ListView (то есть нет адаптера, лежащего в основе представлений), и вы хотите определить, какой вид View был долго нажат для доступа к ContextMenu, может быть реализован следующий «хак». (Было бы лучше, если бы Android предоставил слушателю, который мог бы быть связан с каждым элементом).

«Хак» состоит в том, что создается частный элемент просмотра mLastViewTouched в классе, а затем добавляется следующий onTouchListener ко всем представлениям, которые могут генерировать ContextMenu:

  private View.OnTouchListener onTouchListener = new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { mLastViewTouched = view; // Store a handle on the last view touched. This will be used to identify the view on which the Context Menu was launched return false; // We return false since this indicates that the touch was not handled and so it is passed down the stack to be handled appropriately } }; 

Поэтому всякий раз, когда вид затрагивается, mLastViewTouched обновляется. Теперь в onContextItemSelected вы получите доступ к представлению, инициировавшему ContextMenu.

При создании своего меню в OnCreateContextMenuListener или public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) вы можете установить пользовательский MenuItem.OnMenuItemClickListener для каждого элемента:

  addPhotosBtn.setOnCreateContextMenuListener((menu, v, menuInfo) -> { getMenuInflater().inflate(R.menu.upload_image_menu, menu); int itemCount = menu.size(); for(int i = 0; i < itemCount; i++) { menu.getItem(i).setOnMenuItemClickListener(addPhotosBtnMenuItemClickListener); } }); 

Поскольку в это время у вас есть доступ к представлению, для которого вы создаете контекстное меню, вы можете плотно связать слушателя с этим представлением.