Типы меню
Позвольте мне изложить различие между контекстными меню и всплывающими меню (взято из здесь):
-
PopupMenu - это модальное меню, привязанное к представлению
-
Контекстное меню [я говорю конкретно о плавающих контекстных меню] предлагает действия, которые влияют на конкретный элемент или контекстный фрейм в пользовательском интерфейсе. Вы можете предоставить контекстное меню для любого вида, но чаще всего они используются для элементов в ListView, GridView или других коллекциях представлений, в которых пользователь может выполнять прямые действия над каждым элементом.
В качестве руководства, документы различают их использование: - PopupMenu: "Предоставление меню стиля переполнения для действий, относящихся к определенному контенту (например, заголовкам электронной почты Gmail..." - ContextualMenu: "Для действий, влияющих на выбранный контент..."
Я после визуального просмотра и взаимодействия PopupMenu.
Моя настройка (и цель)
У меня есть ListView, где у каждого элемента есть кнопка справа.
--------------------
| Item 1 [ ]|
--------------------
--------------------
| Item ... [ ]|
--------------------
--------------------
| Item n [ ]|
--------------------
сохраняя onItemClick
для каждого ListItem, я бы хотел использовать кнопку для запуска PopupMenu
.
Действия в PopupMenu
перечислены в my_menu.xml
, поэтому единственное различие между каждым экземпляром меню - это элемент, на который он был нажат.
Что я пробовал
Я попытался переопределить getView()
в моем ListAdapter
, чтобы добавить OnClickListener
для каждой кнопки, как этот пост. Результат был непоследовательным; не все клики регистрировались (возможно, из-за переработки - я еще не пробовал это исправление), но в целом подход казался сжатым, учитывая легкость определения контекста меню для просмотра списка.
Я также попытался добавить контекстное меню, которое было мертвым легко, за исключением того, что оно срабатывало только при длительном нажатии элемента списка.
Способ getView()
- путь или есть что-то проще?
В моем списке, у меня есть кнопка мини-переполнения для каждого элемента, похожая на каждый трек в плейлисте для Play Music. Они отображают PopupMenu для каждого элемента там, когда вы нажимаете кнопку переполнения. Длительное нажатие ничего не делает.
Я бы хотел, но не уверен, как это сделать? На странице меню только описано, как включить всплывающее меню для отдельных просмотров.
registerForContextMenu(ListView lv)
- единственное, что я видел, что я могу применить ко всему ListView, но похоже, что он работает только с длинными нажатиями всего списка. Есть ли способ связать это событие с кликом определенного вида в элементе списка (при сохранении элемента списка для остальной части элемента списка)?
Я попытался установить OnClickListener
в getView()
, как описано здесь, но он чувствует себя squisty для PopupMenu, и не все клики регистрировались каждый раз (это было последовательно противоречиво).
Обновление - с возвратом getView() снова
Когда я создаю StacksCursorAdapter, я передаю экземпляр StackViewFragment, который хранится как поле (поэтому его можно назначить представлениям в качестве прослушивателя кликов).
ViewHolder
- класс с public final ImageView miniOverflow
StacksCursorAdapter (расширяет SimpleCursorAdapter):
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = super.getView(position, convertView, parent);
ViewHolder holder = (ViewHolder) row.getTag();
if (holder == null) {
holder = new ViewHolder(row);
row.setTag(holder);
}
holder.miniOverflow.setTag(R.id.tag_stack_position, position);
holder.miniOverflow.setOnClickListener(listener);
return row;
}
StackViewFragment (расширяет ListFragment, реализует View.OnClickListener):
@Override
public void onClick(View v) {
Log.d(TAG, "mini overflow clicked");
Log.d(TAG, "position:::::" + v.getTag(R.id.tag_stack_position));
PopupMenu popup = new PopupMenu(getActivity(), v);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.menu_stackview_listitem, popup.getMenu());
popup.show();
}
stack_list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<!-- a single row item for a Stacks listview -->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="48dp"
android:descendantFocusability="blocksDescendants"
>
...
<other views>
...
<ImageView
android:id="@+id/moreoverflow_btn"
android:focusable="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:alpha="0.4"
android:scaleType="fitCenter"
android:src="@drawable/ic_menu_moreoverflow_black"
android:layout_alignParentRight="true"
/>
</RelativeLayout>
Проблема на этом перекрестке заключается в том, что я должен щелкнуть несколько раз, чтобы получить щелчок, чтобы зарегистрироваться (на кнопке). Это без прокрутки, поэтому оно не связано с переходом на просмотр.
Заключение (решение eskimoapps.com отмечено как правильно)
Таким образом, не было никаких проблем с несколькими кликами, за исключением того, что моя целевая точка касания не была в том месте, которое я ожидал, - ресурс изображения, который я использовал для мини-переполнения, взвешен вправо (так что три точки находятся рядом с правый край касательной цели), означающий, что я просто пропустил его половину времени (facepalm).
Переопределение getView()
, как я показал выше, кажется, работает нормально, и на самом деле getView()
можно изменить еще дальше, установив OnClickListener только в случае необходимости (но определенно, обновление тега должно выполняться для каждого а не только вновь созданные):
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = super.getView(position, convertView, parent);
ViewHolder holder = (ViewHolder) row.getTag();
if (holder == null) {
holder = new ViewHolder(row);
row.setTag(holder);
holder.miniOverflow.setOnClickListener(listener);
}
holder.miniOverflow.setTag(R.id.tag_stack_position, position);
return row;
}