Itoun
Itoun

Reputation: 3227

expand/collapse Animation Android half view

I would like to expand/collapse an ImageView but start from 50% picture to expand at 100%, collapse to 50% not under.

I already took a look at some popular questions and answers on SO but I didn't find how to manage only half. I also want to modify on the height of view, not the width.

What I tried :

public static void expand(final View v) {
    v.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    final int targtetHeight = v.getMeasuredHeight();

    v.getLayoutParams().height = 0;
    v.setVisibility(View.VISIBLE);
    Animation a = new Animation()
    {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            v.getLayoutParams().height = interpolatedTime == 1
                    ? ViewGroup.LayoutParams.WRAP_CONTENT
                    : (int)(targtetHeight * interpolatedTime);
            v.requestLayout();
        }

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

    a.setDuration((int)(targtetHeight / v.getContext().getResources().getDisplayMetrics().density));
    v.startAnimation(a);
}

public static void collapse(final View v) {
    final int initialHeight = v.getMeasuredHeight();

    Animation a = new Animation() {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            if (interpolatedTime == 1) {
                v.setVisibility(View.VISIBLE);
            } else {
                v.getLayoutParams().height = initialHeight - (int) (initialHeight * interpolatedTime);
                v.requestLayout();
            }
        }

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

    a.setDuration((int) (initialHeight / v.getContext().getResources().getDisplayMetrics().density));
    v.startAnimation(a);
}

as I said it's not what I want because it make disappeared totally and it change the width.

I also tried this snippet but there is no animation :

mImageDrawable = (ClipDrawable) pic.getDrawable();
mImageDrawable.setLevel(5000);//use set level to expand or collapse manually but no animation.

clip:

    <?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="vertical"
    android:drawable="@drawable/test_pic"
    android:gravity="top" />

Upvotes: 3

Views: 5097

Answers (1)

ashakirov
ashakirov

Reputation: 12360

Use Transition API which is available in support package (androidx). Just call TransitionManager.beginDelayedTransition then change height of view. TransitionManager will handle this changes and it will provide transition which will change imageView with animation.

enter image description here

scaleType of ImageView here is centerCrop thats why image scales when collapse and expand. Unfortunetly there is no "fill width and crop bottom" scaleType, so if you need it I think it can be done throught scaleType = matrix .

import androidx.appcompat.app.AppCompatActivity;
import androidx.transition.TransitionManager;

public class MainActivity extends AppCompatActivity {

  private ImageView image;
  private ViewGroup parent;
  boolean collapse = true;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    image = findViewById(R.id.image);
    parent = findViewById(R.id.parent);

    findViewById(R.id.btn).setOnClickListener(view -> {
        collapse = !collapse;
        collapse();
    });
  }

  private void collapse() {
    TransitionManager.beginDelayedTransition(parent);
    //change layout params
    int height = image.getHeight();
    LayoutParams layoutParams = image.getLayoutParams();
    layoutParams.height = !collapse ? height / 2 : height * 2;
    image.requestLayout();
  }
}

Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<Button
    android:id="@+id/btn"
    android:text="start"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

<ImageView
    android:id="@+id/image"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    android:scaleType="centerCrop"
    android:src="@drawable/qwe" />

<TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="random text"
    android:layout_margin="8dp"/>
</LinearLayout>

UPDATE:

There is beginDelayedTransition(ViewGroup, Transtion) method. beginDelayedTransition(ViewGroup) by default use AutoTransition as transition. So if you need handle start/end of transition you can do it like this:

    AutoTransition transition = new AutoTransition();
    transition.addListener(new TransitionListenerAdapter(){
        @Override
        public void onTransitionStart(@NonNull Transition transition) {
            //TODO
        }
        @Override
        public void onTransitionEnd(@NonNull Transition transition) {
            //TODO 
        }
    });
    TransitionManager.beginDelayedTransition(parent, transition);

Upvotes: 6

Related Questions