Android: Позиция обратного вызова контекстного меню отключена на единицу, когда ListView содержит заголовок

#android #listview #adapter

#Android #listview #адаптер

Вопрос:

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

Когда пользователь долго нажимает строку, позиция в onCreateContextMenu обратном вызове, похоже, отключена на единицу. Когда пользователь долго нажимает на заголовок, сообщаемая позиция равна 0 (я бы не ожидал обратного вызова), когда пользователь долго нажимает на первую строку, сообщаемая позиция равна 1 вместо 0 и так далее.

Тот же код работает, как ожидалось, без заголовка.

Я знаю, что внутренне Android просто создает новый адаптер вокруг моего, когда я устанавливаю заголовок, но я бы предположил, что они обрабатывают настройку позиции перед вызовом обратных вызовов.

Это то, что я вижу ожидаемое поведение? Возможно, я делаю что-то не так?

Вот как я извлекаю позицию:

 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
    int position = info.position;

    // this is my workaround, but I'm afraid it's going to bite me in
    // the ass if/when GOOG fixes this
    if( this.hasHeader() amp;amp; position > 0 ) position--;
  

Ответ №1:

Я знаю, что внутренне Android просто создает новый адаптер вокруг моего, когда я устанавливаю заголовок, но я бы предположил, что они обрабатывают настройку позиции перед вызовом обратных вызовов.

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

Проще говоря, содержимое контекстного меню вообще не включает Adapter , только AdapterView . Следовательно, у переноса нет возможности Adapter либо использовать события меню, либо корректировать значения позиций.

Я подозреваю, что вам просто нужно будет вычесть 1 и игнорировать строку заголовка самостоятельно.

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

1. Спасибо. Таким образом, AdapterView передается положение представлений , но адаптер фактически передает значения индекса фактических элементов списка, независимо от того, установлен заголовок или нет? Я думаю, что понимаю, о чем вы говорите, но это развеет мои сомнения, если вы знаете какую-либо документацию, которая объясняет, как настройка заголовка влияет на позицию в объектах AdapterContextMenuInfo. Мой поиск ничего конкретно об этом не дал.

2. @psychotik: «Итак, AdapterView обходит позиции представлений, но адаптер фактически обходит значения индексов фактических элементов списка, независимо от того, установлен заголовок или нет?» — AdapterView думает position , что будет выполняться от 0 до того, что Adapter возвращает для getCount() минуса 1 . Точка. Совершенно не обращая внимания на то, что это значит. ListView заменяет Adapter другим (перенос) Adapter . Перенос Adapter знает, что позиция 0 является заголовком и getCount() должна увеличиваться на 1 .

3. @psychotik: «если вы знаете какую-либо документацию, которая объясняет, как настройка заголовка влияет на позицию в объектах AdapterContextMenuInfo» — я сомневаюсь, что есть что-либо, кроме исходного кода. Вы можете изучить AdapterView , ListView и Adapter класс переноса (некоторый внутренний класс ListView IIRC, хотя прошло некоторое время с тех пор, как я изучал это поведение).