Android---缩放View

来源:互联网 发布:达芬奇调色软件下载 编辑:程序博客网 时间:2024/06/14 22:51

本文译自:http://developer.android.com/training/animation/zoom.html

本文向你介绍如何制作触碰缩放动画,对于像相册这样的应用程序,让图片在缩略图和全屏显示之间具有动画行为,会具有更好的用户体验。

创建View

给要缩放的内容创建大小两个版本的布局文件。下例中给可点击的图片缩略图创建了一个ImageButton布局和一个用于显示大图片的ImageView布局:

<FrameLayoutxmlns: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="wrap_content"
        android:orientation="vertical"
        android:padding="16dp">

        <ImageButton
            android:id="@+id/thumb_button_1"
            android:layout_width="100dp"
            android:layout_height="75dp"
            android:layout_marginRight="1dp"
            android:src="@drawable/thumb1"
            android:scaleType="centerCrop"
            android:contentDescription="@string/description_image_1" />

    </LinearLayout>

    <!-- Thisinitially-hidden ImageView will hold the expanded/zoomed version of
         the images above. Withouttransformations applied, it takes up the entire
         screen. To achieve the"zoom" animation, this view's bounds are animated
         from the bounds of thethumbnail button above, to its final laid-out
         bounds.
         -->

    <ImageView
        android:id="@+id/expanded_image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="invisible"
        android:contentDescription="@string/description_zoom_touch_close" />

</FrameLayout>

建立缩放动画

应用上述布局之后,就要建立触发缩放动画的事件处理器。下例给ImageButton控件添加了一个View.OnClickListener事件处理器,以便在用户点击图片按钮时,执行缩放动画。

publicclassZoomActivityextendsFragmentActivity{
   
// Hold a reference to thecurrent animator,
    // so that it can becanceled mid-way.
    private AnimatormCurrentAnimator;

    // The system"short" animation time duration, in milliseconds. This
    // duration is ideal forsubtle animations or animations that occur
    // very frequently.
    private intmShortAnimationDuration;

    @Override
    protected void onCreate(BundlesavedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_zoom);

        // Hook upclicks on the thumbnail views.

        final View thumb1View = findViewById(R.id.thumb_button_1);
        thumb1View.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               zoomImageFromThumb(thumb1View, R.drawable.image1);
            }
        });

        // Retrieveand cache the system's default "short" animation time.
        mShortAnimationDuration = getResources().getInteger(
                android.R.integer.config_shortAnimTime);
    }
    ...
}

缩放View

现在,你需要在恰当的时机,使用动画把普通尺寸的View转换成要缩放的尺寸。通常,需。要把普通尺寸的View转换成较大尺寸的View。下面的方法说明了如何实现一个缩放动画,它把一个图片的缩略图转换成一个较大图片View,具体步骤如下:

1. 把高分辨率的图片分配给隐藏的,用于放大的ImageView。为了简单,下例在UI线程中加载了一个大图片资源。你会想到,要在一个独立的线程中来加载图片,并在UI线程中来设置位图,以便防止UI线程的阻塞。立项情况下,位图不应该比屏幕的尺寸大。

2. 给ImageView计算起始边界。

3. 从起始边界到结束边界,要把每四个位置和尺寸属性X,Y(SCALE_XSCALE_Y)同时作为一个动画。因此要把这个四个动画添加到AnimatorSet对象中,以便他们能够被同时开始。

4. 通过运行类似的动画,可以实现缩小动画。但是当用户点击被放大的图片时,动画处理与放大处理是方向的。通过给ImageView对象添加一个View.OnClickListener监听器来完成这件事。在点击时,ImageView缩小到缩略图的尺寸,并且要把ImageView对象的可先属性设置为GONE,以便隐藏它。

privatevoidzoomImageFromThumb(finalView thumbView,intimageResId){
   
// If there's an animationin progress, cancel it
    // immediately and proceedwith this one.
    if (mCurrentAnimator != null) {
        mCurrentAnimator.cancel();
    }

    // Load thehigh-resolution "zoomed-in" image.
    final ImageViewexpandedImageView = (ImageView) findViewById(
            R.id.expanded_image);
    expandedImageView.setImageResource(imageResId);

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

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

    // Adjust the start boundsto be the same aspect ratio as the final
    // bounds using the"center crop" technique. This prevents undesirable
    // stretching during theanimation. Also calculate the start scaling
    // factor (the end scalingfactor is always 1.0).
    float startScale;
    if ((float) finalBounds.width() / finalBounds.height()
            > (float) startBounds.width() / startBounds.height()) {
        // Extendstart 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 {
        // Extendstart 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 thumbnail andshow the zoomed-in view. When the animation
    // begins, it willposition the zoomed-in view in the place of the
    // thumbnail.
    thumbView.setAlpha(0f);
    expandedImageView.setVisibility(View.VISIBLE);

    // Set the pivot point forSCALE_X and SCALE_Y transformations
    // to the top-left cornerof the zoomed-in view (the default
    // is the center of theview).
    expandedImageView.setPivotX(0f);
    expandedImageView.setPivotY(0f);

    // Construct and run theparallel animation of the four translation and
    // scale properties (X, Y,SCALE_X, and SCALE_Y).
    AnimatorSet set = new AnimatorSet();
    set
            .play(ObjectAnimator.ofFloat(expandedImageView, View.X,
                   startBounds.left, finalBounds.left))
            .with(ObjectAnimator.ofFloat(expandedImageView, View.Y,
                   startBounds.top, finalBounds.top))
            .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X,
            startScale, 1f)).with(ObjectAnimator.ofFloat(expandedImageView,
                   View.SCALE_Y, startScale, 1f));
    set.setDuration(mShortAnimationDuration);
    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 thezoomed-in image, it should zoom back down
    // to the original boundsand show the thumbnail instead of
    // the expanded image.
    final float startScaleFinal = startScale;
    expandedImageView.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(expandedImageView, View.X, startBounds.left))
                       .with(ObjectAnimator
                               .ofFloat(expandedImageView,
                                       View.Y,startBounds.top))
                       .with(ObjectAnimator
                               .ofFloat(expandedImageView,
                                       View.SCALE_X, startScaleFinal))
                       .with(ObjectAnimator
                               .ofFloat(expandedImageView,
                                       View.SCALE_Y, startScaleFinal));
            set.setDuration(mShortAnimationDuration);
            set.setInterpolator(new DecelerateInterpolator());
            set.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                   thumbView.setAlpha(1f);
                   expandedImageView.setVisibility(View.GONE);
                   mCurrentAnimator = null;
                }

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

 

原创粉丝点击