Просмотр утилизации в ListView с AnimationDrawable
Таким образом, у меня есть этот ListView с пользовательским адаптером, который позволяет мне "выбирать" элемент при щелчке элемента. Теперь у каждой строки списка есть ImageView, Drawable которого я заменяю на "выбранное" изображение, когда соответствующий элемент выбран. Работает нормально на моем устройстве Lollipop.
Я создаю Drawables в конструкторе адаптера списка
public DoubleRowSelectableArrayAdapter(Context context, int resource2, List<Recording> recordings) {
super(context, resource2, recordings);
idle = ContextCompat.getDrawable(context,R.drawable.idleicon);
animation = (AnimationDrawable) ContextCompat.getDrawable(context, R.drawable.animation);
}
Теперь, как вы можете видеть, "выбранный" элемент - это AnimationDrawable, который должен воспроизводиться всякий раз, когда выбирается представление (кстати, это режим одиночного выбора).
Представления обновляются в методе getView
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
convertView = layoutInflater.inflate(resource, null);
}
if (position == selection) {
Log.d("getView", "selection = position");
convertView.setSelected(true);
convertView.setPressed(true);
//get the imageview from the current row
final ImageView pic = ((ImageView) convertView.findViewById(R.id.iconview));
pic.setImageDrawable(animation);
}
else{
Log.d("getView","else");
convertView.setSelected(false);
convertView.setPressed(false);
//set idle icon
((ImageView) convertView.findViewById(R.id.iconview)).setImageDrawable(idle);
}
Я бы предположил, что AnimationDrawable имеет "глобальное" состояние для всех элементов списка. Поэтому запуск анимации один раз в конструкторе должен позволять анимации воспроизводиться постоянно для каждого элемента списка.
Мне удалось запустить анимацию для каждого элемента, например, запустив ее в конструкторе или в методе getView с помощью вызова post(). Однако я пропустил эту часть кода, потому что хочу сосредоточиться на немного другой вещи.
Вот проблема: Когда я выбираю другой элемент списка во время воспроизведения анимации (oneshot=false), анимация вновь выбранного элемента будет воспроизводиться, если она находится НИЖЕ, как позиция старого элемента, НО НЕ воспроизводится, если она находится НАШЕ место старой позиции в список. Итак, я выбираю первый пункт. Анимация играет. Выбран второй элемент, воспроизводится анимация. Третий выбран, анимация воспроизводится...10-й элемент выбран, анимация воспроизводится. В другом направлении это не работает. Если у меня воспроизводится анимация 10-го элемента и я выбираю один из элементов с позициями 1-9, анимация не будет воспроизводиться вообще. Я должен был бы ждать окончания бегущей анимации, прежде чем сможет играть новая.
Это поведение меняется, если я получаю Drawable из ресурсов каждый раз, когда вызывается getView - тогда он работает абсолютно нормально. Так в getView
AnimationDrawable d = (AnimationDrawable) getContext().getResources().getDrawable(R.drawable.animation);
pic.setImageDrawable(d);
d.start(); //or by post() call, etc. -- however working.
Мое дикое предположение, что это как-то связано с переработкой View в списке. Что я должен сделать, чтобы сохранить (дорогой?) Экземпляр drawable из ресурсов в каждом вызове getView?
Вопросы: почему это так? Как правильно настроить анимацию? Разумно ли получать анимацию из ресурсов для каждого нового запуска анимации (вероятно, нет)? Как это сделать правильно?
1 ответ
Это почему? Всякий раз, когда воспроизводится анимация, за сценой генерируется поток, и значения применяются к целевому объекту. Этот поток синхронизирован, поэтому только один процесс может войти одновременно. Следовательно, вы должны создать отдельный объект анимации для каждого вида.
Как правильно настроить анимацию? Что я должен сделать, чтобы сохранить (дорогой?) Экземпляр drawable из ресурсов в каждом вызове getView? Разумно ли получать анимацию из ресурсов для каждого нового запуска анимации (вероятно, нет)? Как это сделать правильно? Вы делаете это правильно, вы должны создавать animationDrawable в каждом вызове getview(). Если вы хотите избавиться от создания drawable более одного раза (дорогая задача) для представления, установите animationDrawable в качестве тега и извлекайте его при каждом вызове getView и повторно инициализируйте, если оно равно нулю.
Я надеюсь, что вы получили свой ответ, если не дайте мне знать.