繁体   English   中英

设置Android PhotoView高度的动画

[英]Animate Android PhotoView height

我正在使用https://github.com/chrisbanes/PhotoView并尝试设置其高度的动画。

我使用ValueAnimator并更新布局高度,以触发内部PhotoViewAttacheronGlobalLayout来转换矩阵。

有什么解决方法可以防止缩放比例和y位置保持不变,例如我可以自己更新矩阵以使图像Y位置和scaleX / scaleY保持不变吗? 现在将它们重置为比例尺1.0和图像的y位置中心。

动画代码:

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

我查看了源代码,但尚未测试以下代码。 据我所知,您希望在动画期间阻止对onGlobalLayout()的调用。 以下应实现该目标:

onAnimationStart():

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

onAnimationEnd():

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

请注意, removeOnGlobalLayoutListener(OnGlobalLayoutListener)可用于> = 16的API版本。 在此之前,您将使用removeGlobalOnLayoutListener(OnGlobalLayoutListener)

onAnimationStart()onAnimationEnd()回调,通过添加ValueAnimator.AnimatorUpdateListenerValueAnimator

再次,我不知道这是否行得通-看起来应该如此。

编辑:

以下内容与上面的代码无关。

除了可以对PhotoViewheight设置动画之外,还可以为其topbottom属性设置动画。 在我的测试中,设置这些属性的动画不会重置y位置,也不会更改scaleX / scaleY值:

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

如果要动画化height以为PhotoView上方或下方的其他视图腾出空间,则动画top / bottom将无济于事。 在这种情况下,可以使用FrameLayout承载PhotoView和其他Views并控制其可见性。

这比最初的想法要棘手。 该库似乎没有公共API来使其正常工作,因此这里是使用私有方法和字段的解决方法。 以下解决方案似乎适用于我可以更改PhotoView的实际高度,并且在动画过程中scale + y位置保持不变的情况。

首先扩展PhotoView并编写以下代码:

// Private fields and methods
private Matrix mBaseMatrix;
private Field mAttacher;
private Method mGetDrawMatrix;
private Method mSetImageViewMatrix;
private Method mCheckMatrixBounds;

...

@Override
protected void init() {
    super.init();

    getViewTreeObserver().removeOnGlobalLayoutListener(
            (ViewTreeObserver.OnGlobalLayoutListener) getIPhotoViewImplementation());

    getViewTreeObserver().addOnGlobalLayoutListener(
            new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    updateBaseMatrix();
                }
            });
}

private void updateBaseMatrix() {
    try {
        if (mBaseMatrix == null) {
            mBaseMatrix = getMatrix("mBaseMatrix");
        }

        if (mBaseMatrix != null) {
            mBaseMatrix.setValues(new float[]{
                    1.0f, 0.0f, 0.0f,
                    0.0f, 1.0f, 0.0f,
                    0.0f, 0.0f, 1.0f
            });
        }

        if (mAttacher == null) {
            mAttacher = PhotoView.class.getDeclaredField("mAttacher");
            mAttacher.setAccessible(true);
        }

        if (mGetDrawMatrix == null) {
            mGetDrawMatrix = PhotoViewAttacher.class.getDeclaredMethod("getDrawMatrix");
            mGetDrawMatrix.setAccessible(true);
        }

        Matrix drawMatrix = (Matrix) mGetDrawMatrix.invoke(mAttacher.get(this));

        if (mSetImageViewMatrix == null) {
            mSetImageViewMatrix = PhotoViewAttacher.class
                    .getDeclaredMethod("setImageViewMatrix", Matrix.class);
            mSetImageViewMatrix.setAccessible(true);
        }

        mSetImageViewMatrix.invoke(mAttacher.get(this), drawMatrix);

        if (mCheckMatrixBounds == null) {
            mCheckMatrixBounds = PhotoViewAttacher.class.getDeclaredMethod("checkMatrixBounds");
            mCheckMatrixBounds.setAccessible(true);
        }

        mCheckMatrixBounds.invoke(mAttacher.get(this));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private Matrix getMatrix(String fieldName) {
    try {
        Field f = PhotoView.class.getDeclaredField("mAttacher");
        f.setAccessible(true);

        PhotoViewAttacher a = (PhotoViewAttacher) f.get(this);

        f = PhotoViewAttacher.class.getDeclaredField(fieldName);
        f.setAccessible(true);

        return (Matrix) f.get(a);
    } catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM