Android enlarge image from thumb to center

I am following the following tutorial to enlarge thumbnail image in Android http://developer.android.com/training/animation/zoom.html

Everything works fine, except that I would like the zoomed image to be centered in the view and at its maximum size (not fill_parent or match_parent as in the tutorial). I have identical code, but my XML is different from trying to center the image, but it doesn't work. What is the problem?

<FrameLayout.....
<RelativeLayout
    android:id="@+id/te"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <ImageView
        android:id="@+id/memory_expanded_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:maxHeight="150dp"
        android:maxWidth="150dp"
        android:adjustViewBounds="true"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:scaleType="fitCenter"
        android:visibility="invisible"
        android:contentDescription="@string/description_zoom_touch_close" />

</RelativeLayout>
</FrameLayout>

      

Part of the scaling code (identical to the tutorial). I think I need to change something here in the finale, but I couldn't figure it out.

// 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 thumbnail,
// and the final bounds are the global visible rectangle of the container
// view. Also set the container view offset as the origin for the
// bounds, since that the 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)

      

+3


source to share


1 answer


You need to resize finalBounds

it to fit the actual image size. Something like that

int imageHeight = expandedImageView.getHeight();
int imageWidth = expandedImageView.getWidth();
int horizontalMargin = 0,  verticalMargin = 0;
if (imageHeight < finalBounds.height()) {
    verticalMargin = (finalBounds.height() / 2) - (imageHeight / 2);
}
if (imageWidth < finalBounds.width()) {
    horizontalMargin = (finalBounds.width() / 2) - (imageWidth / 2);
}
finalBounds.set(finalBounds.left + horizontalMargin, finalBounds.top + verticalMargin, finalBounds.right - horizontalMargin, finalBounds.bottom - verticalMargin);

      

Complete code:

Markup:



<Framelayout
...
...
<ImageView
   android:id="@+id/memory_expanded_image"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:contentDescription="@string/description_zoom_touch_close"
   android:visibility="invisible"/>

      

Activity:

private void zoomImageFromThumb(final View thumbView, int imageResId) {
        // If there an animation in progress, cancel it immediately and proceed with this one.
        if (mCurrentAnimator != null) {
            mCurrentAnimator.cancel();
        }

        // Load the high-resolution "zoomed-in" image.
        final ImageView expandedImageView = (ImageView) findViewById(R.id.memory_expanded_image);
        expandedImageView.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 thumbnail, and the
        // final bounds are the global visible rectangle of the container view. Also
        // set the container view offset as the origin for the bounds, since that's
        // the 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);

        //modify the final rect to match actual size of the image
        int imageHeight = expandedImageView.getHeight();
        int imageWidth = expandedImageView.getWidth();
        int horizontalMargin = 0,  verticalMargin = 0;
        if (imageHeight < finalBounds.height()) {
            verticalMargin = (finalBounds.height() / 2) - (imageHeight / 2);
        }
        if (imageWidth < finalBounds.width()) {
            horizontalMargin = (finalBounds.width() / 2) - (imageWidth / 2);
        }
        finalBounds.set(finalBounds.left + horizontalMargin, finalBounds.top + verticalMargin, finalBounds.right - horizontalMargin, finalBounds.bottom - verticalMargin);


        // 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 thumbnail and show the zoomed-in view. When the animation begins,
        // it will position the zoomed-in view in the place of the thumbnail.
        thumbView.setAlpha(0f);
        expandedImageView.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).
        expandedImageView.setPivotX(0f);
        expandedImageView.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(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 the zoomed-in image, it should zoom back down to the original bounds
        // and 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;
            }
        });
    }

      

+2


source







All Articles