Android: Expand/collapse animation

后端 未结 30 2176
说谎
说谎 2020-11-22 05:01

Let\'s say I have a vertical linearLayout with :

[v1]
[v2]

By default v1 has visibily = GONE. I would like to show v1 with an expand animat

相关标签:
30条回答
  • 2020-11-22 05:36

    An alternative is to use a scale animation with the following scaling factors for expanding:

    ScaleAnimation anim = new ScaleAnimation(1, 1, 0, 1);
    

    and for collapsing:

    ScaleAnimation anim = new ScaleAnimation(1, 1, 1, 0);
    
    0 讨论(0)
  • 2020-11-22 05:36

    You can use a ViewPropertyAnimator with a slight twist. To collapse, scale the view to a height of 1 pixel, then hide it. To expand, show it, then expand it to its height.

    private void collapse(final View view) {
        view.setPivotY(0);
        view.animate().scaleY(1/view.getHeight()).setDuration(1000).withEndAction(new Runnable() {
            @Override public void run() {
                view.setVisibility(GONE);
            }
        });
    }
    
    private void expand(View view, int height) {
        float scaleFactor = height / view.getHeight();
    
        view.setVisibility(VISIBLE);
        view.setPivotY(0);
        view.animate().scaleY(scaleFactor).setDuration(1000);
    }
    

    The pivot tells the view where to scale from, default is in the middle. The duration is optional (default = 1000). You can also set the interpolator to use, like .setInterpolator(new AccelerateDecelerateInterpolator())

    0 讨论(0)
  • 2020-11-22 05:41

    This was my solution, my ImageView grows from 100% to 200% and return to his original size, using two animation files inside res/anim/ folder

    anim_grow.xml

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:interpolator="@android:anim/accelerate_interpolator">
     <scale
      android:fromXScale="1.0"
      android:toXScale="2.0"
      android:fromYScale="1.0"
      android:toYScale="2.0"
      android:duration="3000"
      android:pivotX="50%"
      android:pivotY="50%"
      android:startOffset="2000" />
    </set>
    

    anim_shrink.xml

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:interpolator="@android:anim/accelerate_interpolator">
     <scale
      android:fromXScale="2.0"
      android:toXScale="1.0"
      android:fromYScale="2.0"
      android:toYScale="1.0"
      android:duration="3000"
      android:pivotX="50%"
      android:pivotY="50%"
      android:startOffset="2000" />
    </set>
    

    Send an ImageView to my method setAnimationGrowShrink()

    ImageView img1 = (ImageView)findViewById(R.id.image1);
    setAnimationGrowShrink(img1);
    

    setAnimationGrowShrink() method:

    private void setAnimationGrowShrink(final ImageView imgV){
        final Animation animationEnlarge = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.anim_grow);
        final Animation animationShrink = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.anim_shrink);
    
        imgV.startAnimation(animationEnlarge);
    
        animationEnlarge.setAnimationListener(new AnimationListener() {         
            @Override
            public void onAnimationStart(Animation animation) {}
    
            @Override
            public void onAnimationRepeat(Animation animation) {}
    
            @Override
            public void onAnimationEnd(Animation animation) {
                imgV.startAnimation(animationShrink);
            }
        });
    
        animationShrink.setAnimationListener(new AnimationListener() {          
            @Override
            public void onAnimationStart(Animation animation) {}
    
            @Override
            public void onAnimationRepeat(Animation animation) {}
    
            @Override
            public void onAnimationEnd(Animation animation) {
                imgV.startAnimation(animationEnlarge);
            }
        });
    
    }
    
    0 讨论(0)
  • 2020-11-22 05:43

    I stumbled over the same problem today and I guess the real solution to this question is this

    <LinearLayout android:id="@+id/container"
    android:animateLayoutChanges="true"
    ...
     />
    

    You will have to set this property for all topmost layouts, which are involved in the shift. If you now set the visibility of one layout to GONE, the other will take the space as the disappearing one is releasing it. There will be a default animation which is some kind of "fading out", but I think you can change this - but the last one I have not tested, for now.

    0 讨论(0)
  • 2020-11-22 05:44

    This is a snippet that I used to resize the width of a view (LinearLayout) with animation.

    The code is supposed to do expand or shrink according the target size. If you want a fill_parent width, you will have to pass the parent .getMeasuredWidth as target width while setting the flag to true.

    Hope it helps some of you.

    public class WidthResizeAnimation extends Animation {
    int targetWidth;
    int originaltWidth;
    View view;
    boolean expand;
    int newWidth = 0;
    boolean fillParent;
    
    public WidthResizeAnimation(View view, int targetWidth, boolean fillParent) {
        this.view = view;
        this.originaltWidth = this.view.getMeasuredWidth();
        this.targetWidth = targetWidth;
        newWidth = originaltWidth;
        if (originaltWidth > targetWidth) {
            expand = false;
        } else {
            expand = true;
        }
        this.fillParent = fillParent;
    }
    
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        if (expand && newWidth < targetWidth) {
            newWidth = (int) (newWidth + (targetWidth - newWidth) * interpolatedTime);
        }
    
        if (!expand && newWidth > targetWidth) {
            newWidth = (int) (newWidth - (newWidth - targetWidth) * interpolatedTime);
        }
        if (fillParent && interpolatedTime == 1.0) {
            view.getLayoutParams().width = -1;
    
        } else {
            view.getLayoutParams().width = newWidth;
        }
        view.requestLayout();
    }
    
    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
    }
    
    @Override
    public boolean willChangeBounds() {
        return true;
    }
    

    }

    0 讨论(0)
  • 2020-11-22 05:44

    This is really simple with droidQuery. For starts, consider this layout:

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical" >
        <LinearLayout
            android:id="@+id/v1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" 
                android:text="View 1" />
        </LinearLayout>
        <LinearLayout
            android:id="@+id/v2"
            android:layout_width="wrap_content"
            android:layout_height="0dp" >
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" 
                android:text="View 2" />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" 
                android:text="View 3" />
        </LinearLayout>
    </LinearLayout>
    

    We can animate the height to the desired value - say 100dp - using the following code:

    //convert 100dp to pixel value
    int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());
    

    Then use droidQuery to animate. The simplest way is with this:

    $.animate("{ height: " + height + "}", new AnimationOptions());
    

    To make the animation more appealing, consider adding an easing:

    $.animate("{ height: " + height + "}", new AnimationOptions().easing($.Easing.BOUNCE));
    

    You can also change the duration on AnimationOptions using the duration() method, or handle what happens when the animation ends. For a complex example, try:

    $.animate("{ height: " + height + "}", new AnimationOptions().easing($.Easing.BOUNCE)
                                                                 .duration(1000)
                                                                 .complete(new Function() {
                                                                     @Override
                                                                     public void invoke($ d, Object... args) {
                                                                         $.toast(context, "finished", Toast.LENGTH_SHORT);
                                                                     }
                                                                 }));
    
    0 讨论(0)
提交回复
热议问题