Обнаружение, какой выбранный пункт (в ListView) породил ContextMenu (Android)

У меня есть ListView, который позволит пользователю длинному нажатию объект для получения контекстного меню. Проблема, которую я имею, находится в определении который ListItem они долго нажатый. Я попытался делать это:

myListView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
  @Override public void onCreateContextMenu(ContextMenu menu, final View v, ContextMenuInfo menuInfo) {
   menu.add("Make Toast")
    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
     @Override public boolean onMenuItemClick(MenuItem item) {
      String toastText = "You clicked position " + ((ListView)v).getSelectedItemPosition();
      Toast.makeText(DisplayScheduleActivity.this, toastText, Toast.LENGTH_SHORT).show();
      return true;
     }
    });
  } 
 });

но это просто зависает, пока ANR не открывается. Я подозреваю, что после меню создается ListItem больше не выбирается.

Похоже, что Вы могли контролировать для щелчков, или длинные щелчки тогда записывают нажатый объект там:

 mArrivalsList.setOnItemLongClickListener(new OnItemLongClickListener() {
  @Override public boolean onItemLongClick(AdapterView parent, View v, int position, long id) {
   // record position/id/whatever here
   return false;
  }
 });

но это чувствует абсолютно kludgey мне. У кого-либо есть какие-либо лучшие решения для этого?

56
задан Mark B 23 February 2010 в 20:44
поделиться

4 ответа

Я делаю именно это. В моем методе onCreateContextMenu (...) я привел ContextMenu.ContextMenuInfo к AdapterView.AdapterContextMenuInfo . Оттуда вы можете получить targetView, который снова передадите виджету. Полный код доступен в HomeActivity.java , ищите метод onCreateContextMenu (...) .

@Override
public void onCreateContextMenu(ContextMenu contextMenu,
                                View v,
                                ContextMenu.ContextMenuInfo menuInfo) {
    AdapterView.AdapterContextMenuInfo info =
            (AdapterView.AdapterContextMenuInfo) menuInfo;
    selectedWord = ((TextView) info.targetView).getText().toString();
    selectedWordId = info.id;

    contextMenu.setHeaderTitle(selectedWord);
    contextMenu.add(0, CONTEXT_MENU_EDIT_ITEM, 0, R.string.edit);
    contextMenu.add(0, CONTEXT_MENU_DELETE_ITEM, 1, R.string.delete);
}

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

75
ответ дан 26 November 2019 в 17:07
поделиться

Прежде всего, мне интересно, не слишком ли вы усложняете ситуацию, используя View.setOnCreateContextMenuListener () . Все станет намного проще, если вы используете Activity.registerForContextMenu () , потому что тогда вы можете просто использовать Activity.onCreateContextMenu () и Activity.onContextItemSelected () , чтобы обрабатывать все события вашего меню. По сути, это означает, что вам не нужно определять все эти анонимные внутренние классы для обработки каждого события; вам просто нужно переопределить несколько методов Activity для обработки этих событий контекстного меню.

Во-вторых, определенно есть более простые способы получить текущий выбранный элемент. Все, что вам нужно сделать, это сохранить ссылку либо на ListView , либо на адаптер , используемый для его заполнения. Вы можете использовать ContextMenuInfo как AdapterContextMenuInfo, чтобы получить позицию элемента; а затем вы можете использовать ListView.getItemAtPosition () или Adapter.getItem () , чтобы получить объект , специально связанный с тем, что было щелкнуто. Например, предположим, что я использую Activity.onCreateContextMenu () , я мог бы сделать это:

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);

    // Get the info on which item was selected
    AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;

    // Get the Adapter behind your ListView (this assumes you're using
    // a ListActivity; if you're not, you'll have to store the Adapter yourself
    // in some way that can be accessed here.)
    Adapter adapter = getListAdapter();

    // Retrieve the item that was clicked on
    Object item = adapter.getItem(info.position);
}

@Override
public boolean onContextItemSelected(MenuItem item) {
    // Here's how you can get the correct item in onContextItemSelected()
    AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
    Object item = getListAdapter().getItem(info.position);
}
67
ответ дан 26 November 2019 в 17:07
поделиться

Мы успешно использовали:

@Override
public boolean onContextItemSelected
(
MenuItem item
)
    {
    if (!AdapterView.AdapterContextMenuInfo.class.isInstance (item.getMenuInfo ()))
        return false;

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

    Object o = getListView ().getItemAtPosition (cmi.position);

    return true;
    }
2
ответ дан 26 November 2019 в 17:07
поделиться

Разве аргумент view не является фактическим видом выбранной строки, или я не понял вопроса?

ListView lv;
private OnItemLongClickListener onLongClick = new OnItemLongClickListener() {
    public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
            int arg2, long arg3) {
        lv.showContextMenuForChild(arg1);
        lv.showContextMenu();
        return false;
    }
};
2
ответ дан 26 November 2019 в 17:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: