Добавить анимацию в 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. это будет действовать как ящик.