Добавить анимацию в ExpandableListView
Есть ли способ добавить анимацию при открытии расширяемого списка в Android?
Я хочу, чтобы, когда пользователь нажимает на расширяемый список, у него есть анимация/эффект, как будто я открываю скользящий ящик.
Он медленно перемещается, пока он не будет полностью открыт.
Ответы
Ответ 1
Я потратил много времени на поиск без везения. Существующие решения просто не достаточно гладки - если ваш макет является чем-то более сложным, чем всего две кнопки, он становится лагги.
Итак, я создал свой собственный ListAdapter
, который кэширует весь вид в Bitmap
, а затем выполняет анимацию в кэшированном представлении вместо самого представления. Он работает намного быстрее.
Вот он: https://github.com/dmitry-zaitsev/ExpandableAdapter
Хорошей новостью является то, что вам не нужно переписывать кучу кода - просто оберните мой ExpandableAdapter
вокруг вашего адаптера и укажите идентификатор представления, который будет действовать как кнопка переключения и идентификатор представления, который содержит содержимое второго уровня:
new ExpandableAdapter(context, yourAdapter, R.id.switch, R.id.holder);
И это все.
Ответ 2
У меня была такая же точная проблема. И я исправил его раз и навсегда. Я открыл его для github.
https://github.com/tjerkw/Android-SlideExpandableListView
В основном вы включаете эту зависимость проекта в свой проект Android. А затем оберните ListAdapter
в SlideExpandableListAdapter
. Затем оболочка добавит слайд-функции с анимацией к вашему ListView
.
Надеюсь, это поможет вам, я уже использую его в двух проектах.
Ответ 3
Я тоже пытался сделать эту работу. Я нашел одно решение, которое работает для childViews. Он не оживляет фактического расширения группы, хотя, но оживляет дочерние клетки, поскольку они заполняют пространство, расширение которого остается.
Изменить: есть ошибка при сбрасывании, которая заставит некоторые ячейки, которые не должны быть скрыты, станет скрытой. Вероятно, это связано с View-recycling в listView. Я буду обновлять, когда у меня есть решение.
Анимация с помощью layoutAnimation в setOnGroupClickListener
mResultList.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
if(mResultList.isGroupExpanded(groupPosition)){
mProgAdap.prepareToCollapseGroup(groupPosition);
setupLayoutAnimationClose(groupPosition);
mResultList.requestLayout();
}else{
boolean autoScrollToExpandedGroup = false;
mResultList.expandGroup(groupPosition,autoScrollToExpandedGroup);
setupLayoutAnimation();
//*/
}
//telling the listView we have handled the group click, and don't want the default actions.
return true;
}
private void setupLayoutAnimation() {
AnimationSet set = new AnimationSet(true);
Animation animation = new AlphaAnimation(0.0f, 1.0f);
animation.setDuration(50);
set.addAnimation(animation);
animation = new ScaleAnimation(1.0f, 1.0f, 0.0f, 1.0f, 0.5f, 1.0f);
animation.setDuration(50);
set.addAnimation(animation);
LayoutAnimationController controller = new LayoutAnimationController(set, 0.75f);
mResultList.setLayoutAnimationListener(null);
mResultList.setLayoutAnimation(controller);
}
private void setupLayoutAnimationClose(final int groupPosition) {
AnimationSet set = new AnimationSet(true);
Animation animation = new AlphaAnimation(1.0f, 0.0f);
animation.setDuration(50);
animation.setFillAfter(true);
animation.setFillEnabled(true);
set.addAnimation(animation);
animation = new ScaleAnimation(1.0f, 1.0f, 1.0f, 0.0f, 0.5f, 0.0f);
animation.setDuration(50);
animation.setFillAfter(true);
animation.setFillEnabled(true);
set.addAnimation(animation);
set.setFillAfter(true);
set.setFillEnabled(true);
LayoutAnimationController controller = new LayoutAnimationController(set, 0.75f);
controller.setOrder(LayoutAnimationController.ORDER_REVERSE);
mResultList.setLayoutAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
mResultList.collapseGroup(groupPosition);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
mResultList.setLayoutAnimation(controller);
}
});
Нам нужно больше настроек, чтобы анимация применима только к фактическим дочерним элементам расширенной/свернутой группы. Поскольку мы не можем перегрузить правильную часть в LayoutAnimationController, нам нужно создать специальный класс ViewGroup. Это та же техника, что и в "Может ли LayoutAnimationController анимировать только указанные виды" .
В ExpandableListViewAdapter теперь нам нужна некоторая обработка состояния, чтобы разрешить или игнорировать анимацию для элементов в списке.
@Override
public void onGroupExpanded(int groupPos){
super.onGroupExpanded(groupPos);
int childCount = getChildrenCount(groupPos);
Log.d("EXPLIST","setting children to be expanded:" + childCount);
for(int j=0; j < getGroupCount(); j++){
for(int k=0; k < getChildrenCount(j); k++){
GoalServiceCell cell = (GoalServiceCell)getChild(j,k);
cell.expandAnimState = GoalServiceCell.ExpandAnimState.SHOULD_NOT_ANIMATE;
}
}
for(int i=0; i < childCount; i++){
GoalServiceCell cell = (GoalServiceCell)getChild(groupPos,i);
cell.expandAnimState = GoalServiceCell.ExpandAnimState.SHOULD_START_EXPAND;
}
}
public void prepareToCollapseGroup(int groupPos){
int childCount = getChildrenCount(groupPos);
for(int j=0; j < getGroupCount(); j++){
for(int k=0; k < getChildrenCount(j); k++){
GoalServiceCell cell = (GoalServiceCell)getChild(j,k);
cell.expandAnimState = GoalServiceCell.ExpandAnimState.SHOULD_NOT_ANIMATE;
}
}
for(int i=0; i < childCount; i++){
GoalServiceCell cell = (GoalServiceCell)getChild(groupPos,i);
cell.expandAnimState = GoalServiceCell.ExpandAnimState.SHOULD_START_COLLAPSIN;
}
}
@Override
public void onGroupCollapsed(int groupPos){
super.onGroupCollapsed(groupPos);
int childCount = getChildrenCount(groupPos);
for(int i=0; i < childCount; i++){
GoalServiceCell cell = (GoalServiceCell)getChild(groupPos,i);
cell.expandAnimState = GoalServiceCell.ExpandAnimState.SHOULD_NOT_ANIMATE;
}
}
И в ViewHolder из детей.
void expandOrCollapse(GoalServiceCell cell,int position){
AnimationAverseRelativeLayout hack = (AnimationAverseRelativeLayout)master;
boolean shouldAnim = cell.expandAnimState == GoalServiceCell.ExpandAnimState.SHOULD_START_EXPAND ||
cell.expandAnimState == GoalServiceCell.ExpandAnimState.SHOULD_START_COLLAPSIN;
hack.setIfShouldAnimate(shouldAnim);
}
ГруппаViews также содержится в AnimationAverseRelativeLayout. Поскольку у меня установлено значение "shouldAnimate" равным false, мне не нужно прикасаться к ним.
Ответ 4
Итак, что я сделал, используйте обычный ListView
, а затем выполните анимацию в onListItemClick.
Анимация похожа на то, что я делаю по этой ссылке: Android animate выпадающее меню вверх/вверх надлежащим образом
Но только для части представления строки. Представление строки реализовано следующим образом в xml:
<somelayout>
<normal>
</normal>
<expanded>
</expanded>
</somelayout>
Норма используется без расширения. Когда активируется расширение, расширенный параметр становится видимым, а не ушел. Вам нужно сохранить контроль над тем, чтобы он снова исчезал при закрытии (помните, что это настроено на ваши конвертированные образы, которые перерабатываются).
Я могу уточнить, если это необходимо, просто достаточно много кода для ввода.
Ответ 5
Что я сделал в этой ситуации.
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(песни1, PropertyValuesHolder.ofInt( "дно", текущий списокHeight, текущий списокHeight * 2));
Что это будет делать, так это то, что высота listView будет удвоена, и она будет анимированной.
Если вы установите текущую высоту списка ZERO. это будет действовать как ящик.