【问题标题】:Transform a ImageView while moving animation (keep ratio)移动动画时变换 ImageView(保持比例)
【发布时间】:2014-08-06 12:52:30
【问题描述】:

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

这里是动画说明:

我不知道该怎么做。有什么解决办法吗?
任何建议表示赞赏。

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

我用 AnimationSet 尝试过 TranslateAnimation + ScaleAnimation,但我的 ImageView 缩放非常紧急。

这是开始图片,使用 centerCrop:

这是 Translate + ScaleAnimation 的结果:

但这是我想要的结果(centerCrop 与上面相同的 src):

如何变换+移动但保持这样的图像比例?我不想改变我的图像比例。

感谢您的帮助。

【问题讨论】:

    标签: android animation view android-imageview android-animation


    【解决方案1】:

    你可以从这个答案中得到什么:

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

    我使用Animator(api >= 11 可用)来实现您描述的效果,因为我没有找到TranslateAnimationScaleAnimation 'good' 在结果方面足够。

    这里发生了 3 件事:

    • 宽度在变化
    • 高度在变化
    • imageview 的“x”值正在改变

    您需要为这 3 个参数提供最终值:finalWidth、finalHeight 和 final Xplacement。

    我们将在每次更新时使用valueAnimator 获取宽度和高度的动画值,然后使用这些值更新ImageViewLayoutParams

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

    本示例中用于 Activity 的布局没有什么特别之处:

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

    编辑:重置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();
    }
    

    动画返回:

    // `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();
    }
    

    【讨论】:

    • 谢谢,它成功了。还有一件事,ImageView 的位置在动画完成后发生了变化。我想将 ImageView 位置重新设置为开始。我尝试使用 setLayoutParams 设置位置,但没有使用。如何将 ImageView 设置为起始位置?
    • @Dolphin 嗨,不客气。要将ImageView 重置为其原始状态,请再次运行相同的 3 个动画师 - 这一次,将起始值与最终值交换。我已经编辑了我的答案以包含 back 动画。我没有测试编辑的代码,所以它可能有一些问题。如果它没有按预期工作,请给我留言,我会回复您。
    • 谢谢,我也想和尝试过这个想法。那是工作。只需要为“X”和“Y”保留 ObjectAnimator。再次感谢您:)
    【解决方案2】:

    第一个链接是创建一组动画。 第二个链接 - 翻译动画。 第三个链接 - 缩放动画。 创建平移和缩放动画将它们添加到动画集​​

    AnimationSet

    TranslateAnimation

    ScaleAnimation

    【讨论】:

    【解决方案3】:

    要在 ImageView 中保持相同的比例,请尝试使用以下属性:

    <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:scaleType="centerInside"
            android:src="@drawable/your_image" />
    

    【讨论】:

      猜你喜欢
      • 2020-09-24
      • 2013-10-16
      • 2018-03-20
      • 2021-11-25
      • 1970-01-01
      • 2015-09-04
      • 2015-05-06
      • 2012-07-08
      • 1970-01-01
      相关资源
      最近更新 更多