Перерисовать одну строку в списке
Можно ли перерисовать одну строку в ListView
? у меня есть ListView
с рядами, которые LinearLayout
s. Я слушаю изменение предпочтений, и иногда мне нужно изменить только один 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);
а затем вы делаете все, что вы хотите с видом.