Перерисовать одну строку в списке

Можно ли перерисовать одну строку в ListView? у меня есть ListView с рядами, которые LinearLayouts. Я слушаю изменение предпочтений, и иногда мне нужно изменить только один View внутри LinearLayout одного ряда. Есть ли способ сделать это перерисовать эту строку без вызова listview.notifyDatasetChanged()?

Я попытался вызвать view.invalidate() для представления (внутри LinearLayout) но это не перерисовывает строку.

4 ответа

Решение

Как недавно объяснил Romain Guy во время сеанса ввода-вывода Google, самый эффективный способ обновить только одно представление в виде списка - это что-то вроде следующего (этот обновляет все View данные):

ListView list = getListView();
int start = list.getFirstVisiblePosition();
for(int i=start, j=list.getLastVisiblePosition();i<=j;i++)
    if(target==list.getItemAtPosition(i)){
        View view = list.getChildAt(i-start);
        list.getAdapter().getView(i, view, list);
        break;
    }

Если предположить, target это один элемент адаптера.

Этот код получить ListView, затем просмотрите отображаемые в данный момент виды, сравните target элемент, который вы ищете, с каждым отображаемым элементом представления, и если ваша цель находится среди них, получите включающий вид и выполните адаптер getView() на этом экране, чтобы обновить дисплей.

Как примечание стороны invalidate() не работает, как некоторые ожидают, и не будет обновлять вид, как getView() делает, notifyDataSetChanged() перестроит весь список и в итоге вызовет getview() для каждого отображаемого элемента и invalidateViews() также повлияет на кучу.

И последнее, можно также получить дополнительную производительность, если ему нужно только изменить дочерний элемент представления строки, а не всю строку, как getView делает. В этом случае следующий код может заменить list.getAdapter().getView(i, view, list); (пример для изменения TextView текст):

((TextView)view.findViewById(R.id.myid)).setText("some new text");

В коде мы верим.

view.invalidate() не работал для меня Но это работает как шарм:

Предположим, вы обновляете позициюposition"в ряд. if избегайте странных перерисовок, таких как танцы текста, когда вы обновляете строку, которой нет на экране.

            if (position >= listView.getFirstVisiblePosition()
                && position <= listView.getLastVisiblePosition()) {

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            listView.invalidateViews();
                        }
                    });
            }

Romain Guy ответил на этот вопрос в видео "Google IO 2010, мир ListView" в то время, когда был задан этот вопрос: http://www.youtube.com/watch?feature=player_detailpage&v=wDBM6wVEO70

Так что, по словам Ромена Гая, это должно сработать, и я думаю, мы можем ему доверять.

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

setAnimationCacheEnabled(false);
setScrollingCacheEnabled(false);
setChildrenDrawingCacheEnabled(false);
setChildrenDrawnWithCacheEnabled(false);

Поместите тег в строку, которую вы хотите обновить. Если вы хотите перерисовать конкретный вид или строку, выполните

ListView lv = (ListView)findViewById(....)

а потом

View v = lv.findViewWithTag(tagobject);

а затем вы делаете все, что вы хотите с видом.

Другие вопросы по тегам