Анимация высоты контейнера LinearLayout с ValueAnimator

У меня есть LinearLayout, который я использую в качестве контейнера для некоторых кнопок и текстового представления, которые я хотел бы оживить по высоте, чтобы создать впечатление, что макет сползает, когда пользователь нажимает кнопку "показать".

Я установил LinearLayout в layout_height = "0dp" и visibility = "gone" в моем xml. Затем я хочу настроить его на видимость и любую высоту, необходимую для обертывания содержимого. На данный момент у меня возникают проблемы даже с анимацией вообще, неважно, насколько высока содержимое упаковки.

Здесь мой метод анимации:

private void toggle(final LinearLayout v) {
    v.setVisibility(View.VISIBLE);
    ValueAnimator va = ValueAnimator.ofInt(0, 300);
    va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        public void onAnimationUpdate(ValueAnimator animation) {
            Integer value = (Integer) animation.getAnimatedValue();
            v.getLayoutParams().height = value.intValue();
            v.invalidate();

        }
    });

    va.start();
}

Возможно, проблема заключается в том, как я устанавливаю высоту LinearLayout? Или я не понимаю функцию ValueAnimator? Я просмотрел сообщение в блоге Чет Хаазе, но они не содержат конкретных примеров анимации высоты. Я также не смог найти и хорошие примеры того, как работать с анимацией высоты, используя API от 3.0+. Хотелось бы помочь в этом, спасибо!

Ответы

Ответ 1

Глядя на это сообщение в блоге: http://tech.chitgoks.com/2011/10/29/android-animation-to-expand-collapse-view-its-children/ Я обнаружил, что не должен использовать view.invalidate(), чтобы перерисовать макет. Я должен использовать view.requestLayout().

Таким образом, код становится примерно таким:

ValueAnimator va = ValueAnimator.ofInt(0, height);
    va.setDuration(700);
    va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        public void onAnimationUpdate(ValueAnimator animation) {
            Integer value = (Integer) animation.getAnimatedValue();
            v.getLayoutParams().height = value.intValue();
            v.requestLayout();
        }
    });

Я просто хотел добавить примечание о том, как получить высоту LinearLayout, а также сделать динамику анимации. Чтобы получить высоту, сначала нужно нарисовать все виды. Мы должны прислушиваться к событию, которое говорит нам, что рисунок сделан. Это можно сделать из метода onResume(), подобного этому (обратите внимание, что в моем xml я объявил контейнер wrap_content для высоты, и он также виден, так как я хочу скрыть его с самого начала, я делаю это, измеряя его)

@Override
    public void onResume() {
        super.onResume();
        final ViewTreeObserver vto = filterContainer.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                height = filterContainer.getHeight();
                filterContainer.setVisibility(View.GONE);
                filterContainer.getLayoutParams().height = 0;
                filterContainer.requestLayout();
                ViewTreeObserver obs = filterContainer.getViewTreeObserver();
                obs.removeGlobalOnLayoutListener(this);
            }
        });
    }