Ответ 1
Если у вас есть устойчивые идентификаторы в вашем адаптере, вы можете получить довольно хорошие результаты (анимации), если вы создадите новый массив, содержащий отфильтрованные элементы, и вызовите
recyclerView.swapAdapter(newAdapter, false);
Используя swapAdapter, подсказки RecyclerView позволяют повторно использовать держатели. (vs в setAdapter, он должен перерабатывать все представления и воссоздавать, потому что он не знает, что новый адаптер имеет тот же ViewHolder, что и старый адаптер).
Лучшим подходом было бы найти, какие элементы удаляются и вызывать notifyItemRemoved(index)
. Не забудьте удалить элемент. Это позволит RecyclerView запускать прогностическую анимацию. Предполагая, что у вас есть адаптер, который внутренне использует ArrayList, реализация будет выглядеть так:
// adapter code
final List<ItemData> mItems = new ArrayList(); //contains your items
public void filterOut(String filter) {
final int size = mItems.size();
for(int i = size - 1; i>= 0; i--) {
if (mItems.get(i).test(filter) == false) {
mItems.remove(i);
notifyItemRemoved(i);
}
}
}
Он будет работать еще лучше, если вы можете выполнять вызовы notifyItemRemoved
и использовать notifyItemRangeRemoved
. Он выглядел бы так: (не тестировалось)
public void filterOut(String filter) {
final int size = mItems.size();
int batchCount = 0; // continuous # of items that are being removed
for(int i = size - 1; i>= 0; i--) {
if (mItems.get(i).test(filter) == false) {
mItems.remove(i);
batchCount ++;
} else if (batchCount != 0) { // dispatch batch
notifyItemRangeRemoved(i + 1, batchCount);
batchCount = 0;
}
}
// notify for remaining
if (batchCount != 0) { // dispatch remaining
notifyItemRangeRemoved(0, batchCount);
}
}
Вам нужно расширить этот код, чтобы добавить элементы, которые ранее были отфильтрованы, но теперь должны быть видимыми (например, пользователь удаляет запрос фильтра), но я думаю, что это должно дать основную идею.
Имейте в виду, что каждый из уведомлений о вызове элемента влияет на те, которые после него (вот почему я просматриваю список из конца, чтобы избежать его). Переход от конца также помогает ArrayList удалять производительность метода (меньше элементов для смены).
Например, если вы перемещали список с самого начала и удаляли первые два элемента. Вы должны либо позвонить
notifyItemRangeRemoved(0, 2); // 2 items starting from index 0
или если вы отправляете их по одному
notifyItemRemoved(0);
notifyItemRemoved(0);//because after the previous one is removed, this item is at position 0