Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

View Animations in Android Collapse/Expand Views in LinearLayout

I added Images view dynamically to my Linear layout,

I want to achieve

enter image description here

Here is sample code what I have done

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>

when I click expand button at the first time is not showing the animation from the second time it's working.

enable Visible the item after click on collapse button.

What to do next : When I selected any View item it has to show select animation then collapse animation, after collapse it has to appear as top View like I mention in Image above. Currently I am hard code the count of the views and wrote static animations for each view with static heights of animations i.e (expandOrCollapse(view, height_of_view))

I search a while for this, but no luck.

I follow the Vie expand/collapse and smooth expand / collapse but they can't help me expand all views in Linear layout.

Can we do this List views are recycler view or something ?

for time saving I have added my sample to git hub you can try it Animation Sample Github

Suggest me, please.

like image 581
Kathi Avatar asked Oct 28 '16 09:10

Kathi


2 Answers

I have made separate class for it. Check if it works for you:

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;
    }
}

While working with this. For expand

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);
    }

For collapse:

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 added to prevent view blinking.

like image 148
Jimit Patel Avatar answered Oct 21 '22 12:10

Jimit Patel


Try to not hide your target view (now you set visibility GONE for all views after collapsed animation end) and do this:

targetView.bringToFront();
targetView.invalidate();
targetView.getParent().requestLayout();
like image 31
Roman_D Avatar answered Oct 21 '22 13:10

Roman_D