Перерисовать одну строку в списке
Можно ли перерисовать одну строку в ListView
? У меня есть ListView
со строками LinearLayout
s. Я слушаю изменение предпочтений, и иногда мне нужно изменить только один View
внутри LinearLayout
одной строки. Есть ли способ перерисовать эту строку без вызова listview.notifyDatasetChanged()
?
Я попытался вызвать view.invalidate() в представлении (внутри LinearLayout
), но он не перерисовывает строку.
Ответы
Ответ 1
Поскольку 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");
В коде, которому мы доверяем.
Ответ 2
view.invalidate()
не работал у меня. Но это работает как шарм:
предположите, что вы обновляете позицию "position
" в строке.
if
избегать странных перерисовывающих вещей, таких как текстовые танцы, когда вы
обновление строки, которая не находится на экране.
if (position >= listView.getFirstVisiblePosition()
&& position <= listView.getLastVisiblePosition()) {
runOnUiThread(new Runnable() {
@Override
public void run() {
listView.invalidateViews();
}
});
}
Ответ 3
Ромен Гай ответил на этот вопрос в "Google IO 2010 Мир ListView"
Видео в то время, когда задавался этот вопрос: http://www.youtube.com/watch?feature=player_detailpage&v=wDBM6wVEO70#t=3149s
Итак, согласно Роменину Гаю, это должно сработать, и я думаю, мы можем ему доверять.
Причина, по которой ваше представление не перерисовывается, немного таинственно.
Возможно, попробуйте отключить все параметры кеша, доступные в ListView
setAnimationCacheEnabled(false);
setScrollingCacheEnabled(false);
setChildrenDrawingCacheEnabled(false);
setChildrenDrawnWithCacheEnabled(false);
Ответ 4
Поместите некоторый тег в строку, которую вы хотите обновить.
Если вы хотите перерисовать этот конкретный вид или строку, выполните
ListView lv = (ListView)findViewById(....)
а затем
View v = lv.findViewWithTag(tagobject);
а затем вы делаете все, что хотите, с видом.