2

I'm making an animation that a View moving and transform it self to another form at the same time.

Here is animation description:

animation expected

I don't know how to do it. Any solution for me?
Any advice is appreciated.

=================================================================
UPDATE

I've tried TranslateAnimation + ScaleAnimation with AnimationSet but my ImageView scaled very urgly.

Here is start image, using centerCrop:
enter image description here

Here is result of Translate + ScaleAnimation:
enter image description here

But this is result that I want (centerCrop with same src above):
enter image description here

How to transform + moving but keep image ratio like that ? I don't want my image ratio changed.

Thanks for help.

Tai Dao
  • 3,407
  • 7
  • 31
  • 54

3 Answers3

8

Here's what you can expect from this answer:

enter image description here

Also note that the code provided here was written for test purposes, and thus isn't optimized.

I have used Animator (available for api >= 11) to achieve the effect you have described as I don't find TranslateAnimation and ScaleAnimation 'good' enough in terms of outcome.

There are 3 things happening here:

  • width is changing
  • height is changing
  • 'x' value for the imageview is changing

You will need to provide the final values for these 3 parameters: finalWidth, finalHeight and final X placement.

We will use valueAnimator to get animated values for the width and height on every update, and then use these values to update the LayoutParams of ImageView.

The animate button (in the gif above) calls the following method:

public void animate() {
    // This is to get the screen dimensions
    final Point p = new Point();
    getWindowManager().getDefaultDisplay().getSize(p);

    // First, define the starting values

    final int startingWidth = mImageView.getWidth();
    final int startingHeight = mImageView.getHeight();
    final int startingXValue = mImageView.getX():

    // Next, define the final values

    // For this example, the final width will be half of screen-width
    final int finalWidth = p.x / 2;

    // Just an arbitrary final value for height. You will have to decide
    // what the final height should be
    final int finalHeight = p.y - ivv.getTop() - 300; 

    // final `X` placement of the imageview
    int finalXValue = p.x / 2 - finalWidth / 2;

    // ValueAnimator to generate changes in width
    final ValueAnimator vaW = ValueAnimator.ofInt(startingWidth, finalWidth);

    vaW.addUpdateListener(new AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            // Get animated width value update
            int newWidth = (int) vaW.getAnimatedValue();

            // Get and update LayoutParams from imageview
            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) 
                                                mImageView.getLayoutParams();
            lp.width = newWidth;
            mImageView.setLayoutParams(lp);
        }
    });

    // ValueAnimator to generate changes in height      
    final ValueAnimator vaH = ValueAnimator.ofInt(startingHeight, finalHeight);

    vaW.addUpdateListener(new AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            // Get animated height value update
            int newHeight = (int) vaH.getAnimatedValue();

            // Get and update LayoutParams from imageview
            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) 
                                                mImageView.getLayoutParams();
            lp.height = newHeight;
            mImageView.setLayoutParams(lp);
        }
    });

    // Used to provide translate animation
    ObjectAnimator oa = ObjectAnimator.ofFloat(
                                    mImageView, "X", startingXValue, 
                                              finalXValue);
    // To play these 3 animators together
    AnimatorSet as = new AnimatorSet();     
    as.playTogether(vaW, vaH, oa);
    as.setDuration(5000);

    as.start();
}

The layout used for the activity in this example is nothing special:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@android:color/holo_blue_dark" >

    <Button
        android:id="@+id/bAnimate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="animate"
        android:layout_gravity="center_horizontal" />

    <ImageView
        android:id="@+id/ivToAnimate"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:text="animate"
        android:layout_gravity="right"
        android:src="@drawable/index"
        android:scaleType="centerCrop" />

</LinearLayout>

Edit: To reset ImageView's position, size & scale:

Declare starting and final values as class variables:

int startingWidth, startingHeight, startingXValue, 
                   finalWidth, finalHeight, finalXValue; 

// this method will only be called ONCE. 
// Use appropriate values to initialize starting and final values
public void initialize() {
    final Point p = new Point();
    getWindowManager().getDefaultDisplay().getSize(p);

    startingWidth = mImageView.getWidth();
    startingHeight = mImageView.getHeight();
    startingXValue = mImageView.getX():

    finalWidth = p.x / 2;
    finalHeight = p.y - ivv.getTop() - 300; 
    finalXValue = p.x / 2 - finalWidth / 2;
}

// Call this method whenever you need to animate forward
// `animate()` method // refer above for comments
public void animate() {
    final ValueAnimator vaW = ValueAnimator.ofInt(startingWidth, finalWidth);

    vaW.addUpdateListener(new AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int newWidth = (int) vaW.getAnimatedValue();
            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) 
                                                mImageView.getLayoutParams();
            lp.width = newWidth;
            mImageView.setLayoutParams(lp);
        }
    });

    final ValueAnimator vaH = ValueAnimator.ofInt(startingHeight, finalHeight);

    vaW.addUpdateListener(new AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int newHeight = (int) vaH.getAnimatedValue();
            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) 
                                                mImageView.getLayoutParams();
            lp.height = newHeight;
            mImageView.setLayoutParams(lp);
        }
    });

    ObjectAnimator oa = ObjectAnimator.ofFloat(
                                    mImageView, "X", startingXValue, 
                                              finalXValue);
    AnimatorSet as = new AnimatorSet();     
    as.playTogether(vaW, vaH, oa);
    as.setDuration(5000);
    as.start();
}

Animate back:

// `animateBack()` method // similar execution to `animate()`
// Notice how the starting and final values have been switched
public void animateBack() {

    final ValueAnimator vaW = ValueAnimator.ofInt(finalWidth, startingWidth);

    vaW.addUpdateListener(new AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int newWidth = (int) vaW.getAnimatedValue();
            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) 
                                                mImageView.getLayoutParams();
            lp.width = newWidth;
            mImageView.setLayoutParams(lp);
        }
    });

    final ValueAnimator vaH = ValueAnimator.ofInt(finalHeight, startingHeight);

    vaW.addUpdateListener(new AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int newHeight = (int) vaH.getAnimatedValue();
            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) 
                                                mImageView.getLayoutParams();
            lp.height = newHeight;
            mImageView.setLayoutParams(lp);
        }
    });

    ObjectAnimator oa = ObjectAnimator.ofFloat(
                                    mImageView, "X", finalXValue, startingXValue);
    AnimatorSet as = new AnimatorSet();     
    as.playTogether(vaW, vaH, oa);
    as.setDuration(5000);
    as.start();
}
Vikram
  • 51,313
  • 11
  • 93
  • 122
  • thanks, it worked. One more thing, the position of ImageView changed after animation finish. I want to set ImageView position back to start. I've tried to set position back using setLayoutParams but no used. How to set ImageView to start position ? – Tai Dao Aug 13 '14 at 08:57
  • 2
    @Dolphin Hi, you are welcome. To reset the `ImageView` to its original state, run the same 3 animators again - _but_ this time, swap the start values with final values. I have edited my answer to incorporate the `back` animation. I have not tested the edited code, so it may have some problem. Please leave me a comment if it does not work as intended and I will get back to you. – Vikram Aug 13 '14 at 09:47
  • 2
    thanks, I also think & and tried that idea. That's work. Just need reserve ObjectAnimator for "X" and "Y". Thanks you one more time :) – Tai Dao Aug 13 '14 at 09:53
1

first link is to create a set of animtions. second link - Animation for Translate. third link - Animation for Scaling. create the translate and scaling animation add them to the Animationset

AnimationSet

TranslateAnimation

ScaleAnimation

Itzik Samara
  • 2,278
  • 1
  • 14
  • 18
  • thanks for quick reply, but I want both of move and scale at same time :) – Tai Dao Aug 06 '14 at 13:01
  • check out this answer : http://stackoverflow.com/questions/8418501/android-animation-moving-and-rotating-at-same-time its show that it happened at the same time. – Itzik Samara Aug 06 '14 at 13:04
-1

To keep the same ratio in the ImageView, try to use these attributes:

<ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scaleType="centerInside"
        android:src="@drawable/your_image" />
Simon Marquis
  • 7,248
  • 1
  • 28
  • 43