在移动动画时变换ImageView(保持比例)

Tai*_*Dao 2 animation android view android-animation android-imageview

我正在制作一个动画,一个视图移动并同时将其转换为另一种形式.

这是动画描述:

动画预期

我不知道怎么做.对我有什么解决方案?
任何建议表示赞赏.

================================================== ===============
更新

我用AnimationSet尝试了TranslateAnimation + ScaleAnimation,但我的ImageView缩放得非常难看.

这是使用centerCrop的开始图像:
在此输入图像描述

这是Translate + ScaleAnimation的结果:
在此输入图像描述

但这是我想要的结果(centerCrop上面有相同的src):
在此输入图像描述

如何转换+移动但保持像这样的图像比例?我不希望我的图像比例发生变化.

感谢帮助.

Vik*_*ram 8

以下是您对此答案的期望:

在此输入图像描述

另请注意,此处提供的代码是出于测试目的而编写的,因此未进行优化.

我已经使用Animator(可用于api> = 11)来达到你所描述的效果,因为我没有找到TranslateAnimation并且ScaleAnimation在结果方面足够"好".

这里发生了三件事:

  • 宽度在变化
  • 身高正在变化
  • imageview的'x'值正在发生变化

您需要提供这3个参数的最终值:finalWidth,finalHeight和final Xplacement.

我们将利用valueAnimator获得的动画值,宽度和高度上的每个更新,然后使用这些值来更新LayoutParamsImageView.

animate按钮(在gif上面)调用下面的方法:

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();
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中用于活动的布局没什么特别的:

<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>
Run Code Online (Sandbox Code Playgroud)

编辑:重置ImageView's位置,大小和比例:

将起始值和最终值声明为类变量:

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();
}
Run Code Online (Sandbox Code Playgroud)

动画回来:

// `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();
}
Run Code Online (Sandbox Code Playgroud)

  • @Dolphin嗨,欢迎你.要将`ImageView`重置为其原始状态,请再次运行相同的3个动画师 - 此时_but_,将起始值与最终值交换.我已经编辑了我的答案以合并`back`动画.我没有测试编辑过的代码,所以可能会有一些问题.如果它没有按预期工作,请给我留言,我会回复你. (2认同)
  • 谢谢,我也想到并尝试了这个想法.这是工作.只需要为"X"和"Y"保留ObjectAnimator.再次感谢你:) (2认同)