Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animate Android PhotoView height

I am using https://github.com/chrisbanes/PhotoView and trying to animate its height.

I use ValueAnimator and update the layout height, so that triggers the internal PhotoViewAttacher and onGlobalLayoutwhich transforms the matrix.

Is there any workaround to prevent scale and y position to be unchanged, like could I somehow update the matrix myself to keep the image Y position and scaleX/scaleY unchanged? Now those are reset to scale 1.0 and y position center of image.

Animation code:

ValueAnimator animator = ValueAnimator.ofInt(start, end).setDuration(300);

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            mImageView.getLayoutParams().height = (int) animation.getAnimatedValue();
            mImageView.requestLayout();
        }
    });

animator.start();
like image 412
Niko Avatar asked Nov 26 '15 16:11

Niko


1 Answers

I went through the source code, but haven't tested the following code. From what I can tell, you want to block the call to onGlobalLayout() for the duration of the animation. The following should achieve that:

onAnimationStart():

mPhotoView.getViewTreeObserver()
    .removeOnGlobalLayoutListener((PhotoViewAttacher)mPhotoView.getIPhotoViewImplementation());

onAnimationEnd():

mPhotoView.getViewTreeObserver()
    .addOnGlobalLayoutListener((PhotoViewAttacher)mPhotoView.getIPhotoViewImplementation());

Note thatremoveOnGlobalLayoutListener(OnGlobalLayoutListener) is available for API versions >=16. Before this, you'll use removeGlobalOnLayoutListener(OnGlobalLayoutListener).

onAnimationStart() and onAnimationEnd() callbacks are available by adding a ValueAnimator.AnimatorUpdateListener to your ValueAnimator.

Again, I don't know if this will work - looks like it should.

Edit:

Following is independent of the code above.

Instead of animating the height of PhotoView, you could animate its top & bottom properties. In my tests, animating these properties did not reset the y position, or change the scaleX/scaleY values:

int mOrigImageViewTop, mOrigImageViewBottom;

void crunchImageView() {
    // Hold on to original values
    if (mOrigImageViewTop == 0) {
        mOrigImageViewTop = mImageView.getTop();
        mOrigImageViewBottom = mImageView.getBottom();
    }

    // Top
    ObjectAnimator objectAnimatorTop = ObjectAnimator.ofInt(mImageView, 
            "top", mOrigImageViewTop, 
            mOrigImageViewTop + 200 /*should be calculated dynamically*/);

    // Bottom
    ObjectAnimator objectAnimatorBottom = ObjectAnimator.ofInt(mImageView, 
            "bottom", mOrigImageViewBottom, 
            mOrigImageViewBottom - 200 /*should be calculated dynamically*/);

    AnimatorSet animatorSet = new AnimatorSet();
    animatorSet.playTogether(objectAnimatorTop, objectAnimatorBottom);
    animatorSet.setDuration(5000L);
    animatorSet.start();
}

If you are animating the height to make room for other views above or below the PhotoView, animating top/bottom will not help. In this case, using a FrameLayout to host the PhotoView & other Views, and controlling their visibility may be an option.

like image 147
Vikram Avatar answered Oct 27 '22 15:10

Vikram