Intereting Posts
Почему папка «data» не может отображаться так же, как в проводнике файлов DDMS? Android Контекст без активности? И другое программирование без активности? Android Studio 0.8.1 Manifest Merger $ {applicationId} недоступен Как я могу проверить, видно ли вид или нет в Android? MultiChoiceMode перед API 11 Каковы наилучшие методы показа справочной информации Spannable Text не работает в диалоговом фрагменте Создайте слой тепловой карты, используя карту google api v2 для Android. Перехват полученных SMS-сообщений в Delphi XE5 для Android Ошибка: (21, 0) Метод Gradle DSL не найден: Java.lang.NullPointerException: попытка вызвать метод интерфейса «java.util.Iterator java.lang.Iterable.iterator ()» при запуске уведомления Специальная схема URL-адреса Android отказывается работать / Как перейти в приложение Android после OAuth Используя {} после точки с запятой HttpUrlConnection не находит вызов NTLM на Android SetCurrentItem в ViewPager не прокручивается сразу в правильном положении

Применение stateListAnimator в элементе RecylerView вызовет мерцающий эффект при вызове notifyDataSetChanged

Я понимаю, что если я применил android:stateListAnimator в RecylerView , вызов adapter.notifyDataSetChanged вызовет нежелательный мерцающий эффект для некоторых RecylerView (не все элементы, как ни странно)

Вот мой элемент RecylerView

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" ... android:stateListAnimator="@anim/lift_up" android:background="@drawable/white" > ... </LinearLayout> 

@anim/lift_up определяется как

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="true" android:state_pressed="true"> <objectAnimator android:duration="@android:integer/config_shortAnimTime" android:propertyName="translationZ" android:valueTo="8dip" android:valueType="floatType" /> </item> <item> <objectAnimator android:duration="@android:integer/config_shortAnimTime" android:propertyName="translationZ" android:valueTo="4dip" android:valueType="floatType" /> </item> </selector> 

И @drawable/white определяется как

 <drawable name="white">#ffffffff</drawable> 

Когда я вызываю adapter.notifyDataSetChanged , следующий странный мерцающий эффект происходит в последних 5 элементах RecylerView. (На экране есть всего 10 видимых элементов)

Эта проблема возникает только в API 21 и выше, потому что только API 21 поддерживает android:stateListAnimator

Это ошибка, или я что-то пропустил?

Полный минимальный работоспособный код можно загрузить с https://github.com/yccheok/RecyclerViewTutorial/tree/4763879598864233a8e6544fe240c3fb34a15b73

Solutions Collecting From Web of "Применение stateListAnimator в элементе RecylerView вызовет мерцающий эффект при вызове notifyDataSetChanged"

Не все предметы, странно

Это по дизайну (я считаю).

Внутренне все перегруппированные ViewGroups (с которыми я столкнулся) поддерживают пул View. Его дорого создать «С нуля». Некоторые из этих затрат рассеиваются с помощью пула View, за счет использования ресурсов. Размер этого пула представляет этот компромисс. Здесь можно посмотреть базовую реализацию: ViewPool из DeckView .

RecyclerView делает то же самое с RecycledViewPool . Обратите внимание на максимальный размер по умолчанию:

 public static class RecycledViewPool { .... private static final int DEFAULT_MAX_SCRAP = 5; .... } 

Я считаю, что первые 5 просмотров в вашем случае не мерцают, потому что они происходят из пула – они не создаются при notifyDataSetChanged() . Это может быть причиной того, что StateListAnimator не использует. Для остальных 5 строк / элементов создаются новые представления.

Из исходного кода:

 View getViewForPosition(int position, boolean dryRun) { .... // 0) If there is a changed scrap, try to find from there .... // 1) Find from scrap by position .... // 2) Find from scrap via stable ids, if exists .... // fallback to recycler .... // getRecycledViewPool() returns an instance of RecycledViewPool holder = getRecycledViewPool().getRecycledView(type); .... // if holder is still 'null' after checking the pool, create a new one .... if (holder == null) { holder = mAdapter.createViewHolder(RecyclerView.this, type); } .... } 

Как вы можете сказать, переработка – это серьезный бизнес. Я не могу объяснить, почему параметры 0, 1, and 2 терпят неудачу – или говорят, даже если они это делают. Чтобы проверить мою гипотезу, вы можете изменить max размер пула и отметить любые различия (в # из мерцающих мер):

 mRecyclerView .getRecycledViewPool() .setMaxRecycledViews(RecyclerView.INVALID_TYPE, 10); 

Если вы проверяете документацию метода recyclerview notifyDataSetChanged в http://androidxref.com/6.0.0_r1/xref/frameworks/support/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java для метода notifyDatasetChanged, он упоминает После "

RecyclerView попытается синтезировать видимые события структурных изменений для адаптеров, которые сообщают, что они {@link #hasStableIds () стабильные идентификаторы}, когда этот метод используется. Это может помочь в целях сохранения анимации и визуального объекта, но отдельные представления элементов все равно нуждаются в отскоке и восстановлении.

Подобная идея также представлена ​​в https://www.youtube.com/watch?v=8MIfSxgsHIs, где вы бы сделали stableIds true, если вам нужно было делать анимации для просмотра списка, а также больше примеров в вышеупомянутых сериях байтов dev принимают стабильные Ids для сохранения анимации в элементах списка.