Android的 - 缩放动画使用AnimatorSet [英] Android - Zoom animation using AnimatorSet

查看:1615
本文介绍了Android的 - 缩放动画使用AnimatorSet的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

官方放大视图教程使用了 AnimatorSet 放大到一个查看。它创造了向下运动的错觉作为视图扩展。后来, AnimatorSet 只是重播向后打造的缩小的错觉。

The official Zooming a View tutorial uses an AnimatorSet to zoom into a View. It creates the illusion of downward movement as the view expands. Later, the AnimatorSet is simply replayed backwards to create the illusion of zoom-out.

我需要实现是这样做的完全相反。我要开始与扩大观点和收缩到一个较小的视图向上运动:

What I need to implement is the exact reverse of this. I need to start with an expanded view and shrink it into a smaller view with an upward movement:

它似乎并不认为我可以使用反转code的例子。这个例子假设你先放大视图,并展开,然后收缩它放回原来的缩略图图标。

It doesn't seem that I can use the reversal code in the example. That example assumes that you first zoom into the view and expand it, and then shrink it back into the original thumbnail icon.

下面是我到目前为止已经试过。我的XML布局

Here's what I've tried so far. My XML layout is

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#1999da">             

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:orientation="horizontal"
        android:layout_gravity="center"
        android:gravity="center">

        <!-- The final shrunk image -->

        <ImageView
            android:id="@+id/thumb_button_1"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:layout_marginRight="1dp"
            android:visibility="invisible"/>

    </LinearLayout>

</LinearLayout>

<!-- The initial expanded image that needs to be shrunk -->

<ImageView
    android:id="@+id/expanded_image"
    android:layout_width="wrap_content"
    android:layout_height="125dp"
    android:layout_gravity="center"
    android:src="@drawable/title_logo_expanded"
    android:scaleType="centerCrop"/>

</FrameLayout>

和这里是执行缩小操作的方法。我基本上是试图扭转教程的步骤:

And here is the method that performs the zoom-out operation. I've basically tried to reverse the procedure in the tutorial:

private void zoomImageFromThumbReverse(final View expandedImageView, int imageResId, final int duration) {
    // If there's an animation in progress, cancel it immediately and proceed with this one.      

    if (mCurrentAnimator != null) {
        mCurrentAnimator.cancel();
    }

    // Load the low-resolution "zoomed-out" image.
    final ImageView thumbView = (ImageView) findViewById(R.id.thumb_button_1);
    thumbView.setImageResource(imageResId);

    // Calculate the starting and ending bounds for the zoomed-in image. This step
    // involves lots of math. Yay, math.
    final Rect startBounds = new Rect();
    final Rect finalBounds = new Rect();
    final Point globalOffset = new Point();

    // The start bounds are the global visible rectangle of the container view (i.e. the FrameLayout), and the
    // final bounds are the global visible rectangle of the thumbnail. Also
    // set the container view's offset as the origin for the bounds, since that's
    // the origin for the positioning animation properties (X, Y).
    findViewById(R.id.container).getGlobalVisibleRect(startBounds, globalOffset);
    thumbView.getGlobalVisibleRect(finalBounds);
    startBounds.offset(-globalOffset.x, -globalOffset.y);
    finalBounds.offset(-globalOffset.x, -globalOffset.y);

    // Adjust the start bounds to be the same aspect ratio as the final bounds using the
    // "center crop" technique. This prevents undesirable stretching during the animation.
    // Also calculate the start scaling factor (the end scaling factor is always 1.0).
    float startScale;
    if ((float) finalBounds.width() / finalBounds.height()
            > (float) startBounds.width() / startBounds.height()) {
        // Extend start bounds horizontally
        startScale = (float) startBounds.height() / finalBounds.height();
        float startWidth = startScale * finalBounds.width();
        float deltaWidth = (startWidth - startBounds.width()) / 2;
        startBounds.left -= deltaWidth;
        startBounds.right += deltaWidth;
    } else {
        // Extend start bounds vertically
        startScale = (float) startBounds.width() / finalBounds.width();
        float startHeight = startScale * finalBounds.height();
        float deltaHeight = (startHeight - startBounds.height()) / 2;
        startBounds.top -= deltaHeight;
        startBounds.bottom += deltaHeight;
    }

    // Hide the expanded-image and show the zoomed-out, thumbnail view. When the animation begins,
    // it will position the zoomed-in view in the place of the thumbnail.
    expandedImageView.setAlpha(0f);
    thumbView.setVisibility(View.VISIBLE);

    // Set the pivot point for SCALE_X and SCALE_Y transformations to the top-left corner of
    // the zoomed-in view (the default is the center of the view).
    thumbView.setPivotX(0f);
    thumbView.setPivotY(0f);

    // Construct and run the parallel animation of the four translation and scale properties
    // (X, Y, SCALE_X, and SCALE_Y).
    AnimatorSet set = new AnimatorSet();
    set
            .play(ObjectAnimator.ofFloat(thumbView, View.X, startBounds.left,
                    finalBounds.left))
            .with(ObjectAnimator.ofFloat(thumbView, View.Y, startBounds.top,
                    finalBounds.top))
            .with(ObjectAnimator.ofFloat(thumbView, View.SCALE_X, startScale, 1f))
            .with(ObjectAnimator.ofFloat(thumbView, View.SCALE_Y, startScale, 1f));
    //set.setDuration(mShortAnimationDuration);
    set.setDuration(duration);
    set.setInterpolator(new DecelerateInterpolator());
    set.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            mCurrentAnimator = null;
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            mCurrentAnimator = null;
        }
    });
    set.start();
    mCurrentAnimator = set;

    // Upon clicking the zoomed-out image, it should zoom back down to the original bounds
    // and show the thumbnail instead of the expanded image.
    final float startScaleFinal = startScale;
    thumbView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (mCurrentAnimator != null) {
                mCurrentAnimator.cancel();
            }

            // Animate the four positioning/sizing properties in parallel, back to their
            // original values.
            AnimatorSet set = new AnimatorSet();
            set
                    .play(ObjectAnimator.ofFloat(thumbView, View.X, startBounds.left))
                    .with(ObjectAnimator.ofFloat(thumbView, View.Y, startBounds.top))
                    .with(ObjectAnimator
                            .ofFloat(thumbView, View.SCALE_X, startScaleFinal))
                    .with(ObjectAnimator
                            .ofFloat(thumbView, View.SCALE_Y, startScaleFinal));
            //set.setDuration(mShortAnimationDuration);
            set.setDuration(duration);
            set.setInterpolator(new DecelerateInterpolator());
            set.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    expandedImageView.setAlpha(1f);
                    thumbView.setVisibility(View.GONE);
                    mCurrentAnimator = null;
                }

                @Override
                public void onAnimationCancel(Animator animation) {
                    expandedImageView.setAlpha(1f);
                    thumbView.setVisibility(View.GONE);
                    mCurrentAnimator = null;
                }
            });
            set.start();
            mCurrentAnimator = set;
        }
    });
}

我在调用此方法的onCreate()如下:

final View expandedImageView = findViewById(R.id.expanded_image);
new Handler().postDelayed(new Runnable(){
        public void run() {
            zoomImageFromThumbReverse(expandedImageView, R.drawable.title_logo_min, 1000);
        }}, 1000);

嗯,就是这样,乡亲们。这是行不通的。我很茫然,为什么。 DEMO例子完美的作品,所以为什么不这项工作?采取甘德,并告诉我,如果我疯了。

Well, that's it, folks. It isn't working. I am at a loss as to why. The demo example works perfectly, so why doesn't this work ? Take a gander and tell me if I'm crazy.

任何人都可以找出错误?或点我在正确的方向?所有帮助将大大AP preciated。

Can anyone identify the error ? Or point me in the right direction ? All help will be greatly appreciated.

推荐答案

这是解决方案,我已经最终使用:

This is the solution I have ultimately used:

private void applyAnimation(final View startView, final View finishView, long duration) {
    float scalingFactor = ((float)finishView.getHeight())/((float)startView.getHeight());

    ScaleAnimation scaleAnimation =  new ScaleAnimation(1f, scalingFactor,
                                                        1f, scalingFactor,
                                                        Animation.RELATIVE_TO_SELF, 0.5f,
                                                        Animation.RELATIVE_TO_SELF, 0.5f);

    scaleAnimation.setDuration(duration);
    scaleAnimation.setInterpolator(new AccelerateDecelerateInterpolator());

    Display display = getWindowManager().getDefaultDisplay();

    int H;

    if(Build.VERSION.SDK_INT >= 13){
        Point size = new Point();
        display.getSize(size);
        H = size.y;
    }
    else{
        H = display.getHeight();
    }

    float h = ((float)finishView.getHeight());

    float verticalDisplacement = (-(H/2)+(3*h/4));

    TranslateAnimation translateAnimation = new TranslateAnimation(Animation.ABSOLUTE, 0,
                                                                   Animation.ABSOLUTE, 0,
                                                                   Animation.ABSOLUTE, 0,
                                                                   Animation.ABSOLUTE, verticalDisplacement);

    translateAnimation.setDuration(duration);
    translateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());

    AnimationSet animationSet = new AnimationSet(false);
    animationSet.addAnimation(scaleAnimation);
    animationSet.addAnimation(translateAnimation);
    animationSet.setFillAfter(false);

    startView.startAnimation(animationSet);
}

这里的关键因素是 toYDelta TranslateAnimation 参数的值:

toYDelta = (-(H/2)+(3*h/4));

理解为什么这个工程是最主要的。其余的主要是简单的。

Understanding why this works is the main thing. The rest is mostly simple.

这篇关于Android的 - 缩放动画使用AnimatorSet的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆