Android – доступ к представлению в ListView после вызова Adapter.notifyDataSetChanged и ListView.setSelection

У меня есть:

ArrayList<SubwordInfo> subwordInfoList - мои данные - список SubwordInfo объектов.

ListView lvSubwords - ListView для отображения моих данных

SubwordListAdapter subwordListAdapter - мой собственный адаптер между subwordInfoList и lvSubwords (на базе BaseAdapter).

В какой-то момент я хочу сделать простую вещь:

  1. Обновить элемент данных в subwordInfoList.
  2. Обновите внешний вид соответствующего дочернего представления в lvSubwords.
  3. Позиционируйте lvSubwords на этом дочернем виде.
  4. Запустите анимацию в этом дочернем представлении.

Шаги 1-3 работают нормально. Но шаг 4 - проблема, потому что я не могу правильно получить доступ к дочернему представлению. Я получаю неправильное дочернее представление или ноль.

Там код:

SubwordInfo si;
...
si=subwordInfoList.get(subwordNo);

<updating si>

subwordListAdapter.notifyDataSetChanged();  //Notify for update - successfull
lvSubwords.setSelection(subwordNo);         //Positionize - successfull

И после этого я пытаюсь получить доступ к дочернему представлению, соответствующему si.

Я пытался сделать это:

View view = lvSubwords.getChildAt(subwordNo-lvSubwords.getFirstVisiblePosition());
if (view!=null)
    view.startAnimation(animHighlight);

Иногда это работает, иногда нет (view==NULL). Иногда взгляд — это неправильный взгляд.

Также я попытался использовать теги просмотра:

View view = lvSubwords.findViewWithTag(si);
if (view!=null)
    view.startAnimation(animHighlight);

Теги назначаются перед в getView адаптера:

@Override
public View getView(int arg0, View arg1, ViewGroup arg2) 
{
    View view = arg1;
    if (view == null) 
      view = lInflater.inflate(R.layout.subword_element, arg2, false);

    SubwordInfo si = getSubwordInfo(arg0);

    ...

    view.setTag(si);//Assigning tags

    return view;        
}

Это работает, только если lvSubwords.getFirstVisiblePosition() было равно 0 ДО вызова subwordListAdapter.notifyDataSetChanged() и lvSubwords.setSelection. В противном случае представление равно нулю.

Кроме того, я обнаружил, что lvSubwords.getFirstVisiblePosition() возвращает одно и то же значение до и после вызова lvSubwords.setSelection.

Итак, мне кажется, что после вызова subwordListAdapter.notifyDataSetChanged() и lvSubwords.setSelection дочерних представлений ListView и сам ListView не обновляется сразу. И они обновятся через некоторое время. Как я могу поймать этот момент и получить желаемое дочернее представление для анимации?


person user3082655    schedule 06.01.2015    source источник


Ответы (1)


Прошло немного времени с тех пор, как я это сделал, но я считаю, что у вас это немного задом наперед. SetSelection должен выравнивать любую позицию адаптера, указанную в верхней части ListView. Это означает, что вы должны быть в порядке, просто всегда захватывая дочерний элемент с индексом 0.

Также да setSelection не происходит сразу. Это выстрелит и не закончится до некоторого времени. Я столкнулся с подобной проблемой совсем недавно, и единственное решение, которое я смог придумать, это postDelay исполняемый файл с действиями, которые вы хотите выполнить.

lvSubwords.setSelection(subwordNo);
lvSubwords.postDelayed(new Runnable() {
    @Override
    public void run() {
        //Get View and start animation
    }
}, 66);

Возможно, вам придется поиграть с тем, как долго вам придется ждать.

person Jay Soyer    schedule 06.01.2015
comment
Спасибо, это работает. И с 66мс тоже работает :) Но мне все же кажется немного неточно. Потому что я угадываю момент - когда я могу получить доступ к представлению. Неужели нет возможности узнать этот момент поточнее? Если бы это был не сенсорный режим, то это было бы событие onSetSelection, но в сенсорном режиме выбора нет, и это событие не срабатывает. Android кажется мне немного неуклюжим... - person user3082655; 09.01.2015
comment
Я поигрался с задержкой и обнаружил, что она работает даже с нулевой задержкой. Итак, я думаю - независимо от того, насколько велика задержка, это сообщение будет обработано ПОСЛЕ ожидающих сообщений представления, включая сообщения для обновления состояния представления, поэтому при любой задержке состояние ListView обязательно будет обновлено, и я могу получить доступ прямо Посмотреть. Если я правильно понимаю... - person user3082655; 09.01.2015