Просмотр анимаций в Android Collapse/Expand Views в LinearLayout

Я добавил динамически изображения в мой линейный макет,

Я хочу достичь

введите описание изображения здесь

Вот пример кода, что я сделал

MainActivity

 package ksp.com.animationssample;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {

    private Button btn_expand;
    private Button btn_collapse;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_expand = (Button) findViewById(R.id.btn_expand);
        btn_collapse = (Button) findViewById(R.id.btn_collapse);
        LinearLayout.LayoutParams vp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        final LinearLayout layout = (LinearLayout) findViewById(R.id.imageLayout);


        for (int i = 0; i < 3; i++) {
            final ImageView image = new ImageView(MainActivity.this);
            image.setLayoutParams(vp);
            if (i == 0)
                image.setImageDrawable(getResources().getDrawable(R.drawable.item_image1));
            else image.setImageDrawable(getResources().getDrawable(R.drawable.item_image2));
            if (i == 2)
                image.setVisibility(View.VISIBLE);
            else
                image.setVisibility(View.GONE);
            layout.addView(image);
        }


        btn_expand.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                expandOrCollapse(layout.getChildAt(2), true, layout.getChildAt(0).getHeight() + layout.getChildAt(1).getHeight());
                expandOrCollapse(layout.getChildAt(1), true, layout.getChildAt(0).getHeight());
                expandOrCollapse(layout.getChildAt(0), true, 0);


            }
        });
        btn_collapse.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                expandOrCollapse(layout.getChildAt(0), false, 0);
                expandOrCollapse(layout.getChildAt(1), false, layout.getChildAt(0).getHeight());
                expandOrCollapse(layout.getChildAt(2), false, layout.getChildAt(0).getHeight() + layout.getChildAt(1).getHeight());
            }
        });


    }


    public void expandOrCollapse(final View v, boolean is_expand, final int animheight) {
        TranslateAnimation anim = null;
        if (is_expand) {
            anim = new TranslateAnimation(0.0f, 0.0f, -animheight, 0.0f);
            v.setVisibility(View.VISIBLE);
            Animation.AnimationListener expandedlistener = new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                }

                @Override
                public void onAnimationEnd(Animation animation) {


                }
            };

            anim.setAnimationListener(expandedlistener);
        } else {
            anim = new TranslateAnimation(0.0f, 0.0f, 0.0f, -animheight);
            Animation.AnimationListener collapselistener = new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    v.setVisibility(View.GONE);
                }
            };

            anim.setAnimationListener(collapselistener);
        }

        anim.setDuration(1500);
        anim.setInterpolator(new AccelerateInterpolator(0.5f));
        v.startAnimation(anim);
    }
}

activity_mainn.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    android:background="@android:color/holo_blue_dark"
    tools:context="ksp.com.animationssample.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:id="@+id/btn_expand"
        android:text="Expand"
        />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn_collapse"
        android:text="Collopse"/>
<ScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:scrollbars="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:id="@+id/imageLayout"
        android:gravity="center"

        android:orientation="vertical"
        android:layout_height="wrap_content">
    </LinearLayout>
    <!--android:animateLayoutChanges="true"-->
</ScrollView>


</RelativeLayout>

когда я нажимаю кнопку expand, в первый раз не отображает анимацию во второй раз, когда она работает.

enable Видимый элемент после нажатия кнопки свернуть.

Что делать дальше: Когда я выбрал какой-либо элемент View, он должен показать анимацию выбора, а затем свернуть анимацию, после ее сглаживания она должна появиться как верхний вид, как я упоминал в изображении выше. В настоящее время я являюсь жестким кодом подсчета просмотров и пишет статические анимации для каждого представления со статическими высотами анимаций i.e(expandOrCollapse(view, height_of_view))

Я искал какое-то время для этого, но не повезло.

Я следую Vie expand/collapse и плавное расширение/свернуть, но они не могут мне помочь развернуть все виды в линейном макете.

Можем ли мы сделать этот просмотр списка, это просмотр ресайклеров или что-то еще?

для экономии времени Я добавил свой пример в концентратор git, вы можете попробовать его Пример анимации Github

Предложите мне, пожалуйста.

Ответ 1

Я сделал для него отдельный класс. Проверьте, работает ли он для вас:

public class DropDownAnim extends Animation {
    private final int sourceHeight;
    private final int targetHeight;
    private final View view;
    private final boolean down;

    public DropDownAnim(View view, int sourceHeight, int targetHeight, boolean down) {
        this.view = view;
        this.sourceHeight = sourceHeight;
        this.targetHeight = targetHeight;
        this.down = down;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        int newHeight;
        if (down) {
            newHeight = sourceHeight + (int) (targetHeight * interpolatedTime);
        } else {
            newHeight = sourceHeight + targetHeight - (int) (targetHeight * interpolatedTime);//(int) (targetHeight * (1 - interpolatedTime));
        }
        view.getLayoutParams().height = newHeight;
        view.requestLayout();
        view.setVisibility(down ? View.VISIBLE : View.GONE);
    }

    @Override
    public void initialize(int width, int height, int parentWidth,
            int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
    }

    @Override
    public boolean willChangeBounds() {
        return true;
    }
}

Во время работы с этим. Для расширения

public void expand(final View v) {
        final int sourceHeight = v.getLayoutParams().height;
        final int targetHeight = getResources().getDimensionPixelSize(R.dimen.notification_height);//v.getMeasuredHeight();
        DropDownAnim a = new DropDownAnim(v,targetHeight,true);
        a.setDuration((int) (targetHeight / v.getContext().getResources().getDisplayMetrics().density));
        a.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                // Your code on end of animation
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        v.setVisibility(View.INVISIBLE);
        v.startAnimation(a);
    }

Для коллапса:

public void collapse(final View v) {
        final int sourceHeight = v.getLayoutParams().height;
        final int targetHeight = v.getMeasuredHeight();
        DropDownAnim a = new DropDownAnim(v, targetHeight, false);
        a.setDuration((int) (targetHeight / v.getContext().getResources().getDisplayMetrics().density));
        a.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                // Your code on end of animation
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        v.startAnimation(a);
    }

Update:
sourceHeight, чтобы предотвратить мигание отображения.

Ответ 2

Попытайтесь не скрывать свое целевое представление (теперь вы установите видимость GONE для всех представлений после окончания завершенной анимации) и выполните следующее:

targetView.bringToFront();
targetView.invalidate();
targetView.getParent().requestLayout();