Ответ 1
Окончательное обновление
Прошло довольно много времени с тех пор, как я написал этот ответ. С тех пор многое изменилось. Самое большое изменение - введение RecyclerView
, что упрощает анимацию списка или сетки. Я настоятельно рекомендую переключиться на RecyclerView
, если можно. Для тех, кто не может, я увижу, что я могу сделать для исправления ошибок для моей библиотеки.
Оригинальный ответ
Мне действительно не нравится популярная реализация анимированного ExpandableListView, который просто использует ListView с анимацией расширения, потому что в моем случае использования у каждой из моих групп было много детей, поэтому было невозможно использовать обычный ListView поскольку представления детей не будут переработаны, а использование памяти будет огромным с низкой производительностью. Вместо этого я пошел с гораздо более сложным, но более масштабируемым и гибким подходом.
Я расширил класс ExpandableListView и переопределил функции onCollapse и onExpand. Я также создал подкласс BaseExpandableListAdapter под названием AnimatedExpandableListAdapter. Внутри адаптера я переопределил функцию getChildView и сделал функцию final так, что функция не может быть снова переопределена. Вместо этого я предоставил другую функцию, называемую getRealChildView для подклассов, чтобы переопределить, чтобы обеспечить реальный дочерний вид. Затем я добавил в класс флаг анимации и сделал getChildView возвращением фиктивного представления, если был установлен флаг анимации, и реальный вид, если флаг не был установлен. Теперь со сценой я делаю следующее для onExpand:
- Установите флаг анимации в адаптере и сообщите адаптеру, какая группа расширяется.
- Вызов
notifyDataSetChanged()
(заставляет адаптер вызыватьgetChildView()
для всех просмотров на экране). - Адаптер (в режиме анимации) затем создаст фиктивный вид для расширяющейся группы с начальной высотой 0. Адаптер затем получит реальные дочерние представления и передаст эти представления в фиктивный вид.
- В представлении фиктивного типа начнутся рисовать реальные дочерние представления внутри собственной
onDraw()
функции. - Адаптер начнет цикл анимации, который расширит фиктивный вид до нужного размера. Он также установит прослушиватель анимации, чтобы он мог очистить флаг анимации после завершения анимации и также будет вызывать
notifyDataSetChanged()
.
Наконец, со всем этим я смог не только получить желаемый эффект анимации, но и желаемую производительность, так как этот метод будет работать с группой с более чем 100 детьми.
Для коллапсирующей анимации нужно выполнить немного больше работы, чтобы все это было настроено и запущено. В частности, когда вы переопределяете onCollapse, вы не хотите вызывать родительскую функцию, так как она сбрасывает группу сразу, не оставляя вам никакой возможности воспроизвести анимацию. Вместо этого вы хотите вызвать super.onCollapse в конце анимации коллапса.
UPDATE:
Я провел некоторое время в эти выходные, чтобы переписать мою реализацию этого AnimatedExpandableListView, и я выпускаю источник с примером использования здесь: https://github.com/idunnololz/AnimatedExpandableListView/