Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/195.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为Android PhotoView高度设置动画_Android_Android Photoview - Fatal编程技术网

为Android PhotoView高度设置动画

为Android PhotoView高度设置动画,android,android-photoview,Android,Android Photoview,我正在使用并尝试设置其高度的动画 我使用ValueAnimator并更新布局高度,以便触发内部photoviewatcher和onGlobalLayout,从而变换矩阵 是否有任何方法可以防止缩放和y位置保持不变,比如我是否可以自己更新矩阵以保持图像y位置和scaleX/scaleY不变?现在,它们被重置为比例1.0和图像的y位置中心 动画代码: ValueAnimator animator = ValueAnimator.ofInt(start, end).setDuration(300);

我正在使用并尝试设置其高度的动画

我使用
ValueAnimator
并更新布局高度,以便触发内部
photoviewatcher
onGlobalLayout
,从而变换矩阵

是否有任何方法可以防止缩放和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());
mPhotoView.getViewTreeObserver()
    .addOnGlobalLayoutListener((PhotoViewAttacher)mPhotoView.getIPhotoViewImplementation());
onAnimationEnd():

mPhotoView.getViewTreeObserver()
    .removeOnGlobalLayoutListener((PhotoViewAttacher)mPhotoView.getIPhotoViewImplementation());
mPhotoView.getViewTreeObserver()
    .addOnGlobalLayoutListener((PhotoViewAttacher)mPhotoView.getIPhotoViewImplementation());
请注意,
removeOnGlobalLayoutListener(OnGlobalLayoutListener)
可用于API版本>=16。在此之前,您将使用
removeGlobalOnlyOutliner(OnGlobalLayListener)

onAnimationStart()
onAnimationEnd()
回调可通过将
ValueAnimator.AnimatorUpdateListener
添加到
ValueAnimator
中来实现

再说一次,我不知道这是否有效——看起来应该如此

编辑:

mPhotoView.getViewTreeObserver()
    .removeOnGlobalLayoutListener((PhotoViewAttacher)mPhotoView.getIPhotoViewImplementation());
mPhotoView.getViewTreeObserver()
    .addOnGlobalLayoutListener((PhotoViewAttacher)mPhotoView.getIPhotoViewImplementation());
下面的代码独立于上面的代码

您可以设置其
顶部
底部
属性的动画,而不是设置
PhotoView
高度
的动画。在我的测试中,设置这些属性的动画不会重置
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();
}

如果您正在设置<代码>高度的动画,以便为<代码>照片视图上方或下方的其他视图腾出空间,则设置<代码>顶部/
底部
的动画将无济于事。在这种情况下,使用
FrameLayout
来承载
PhotoView
和其他
视图
,并控制它们的可见性可能是一种选择。

这比最初想象的要复杂得多。该库似乎没有公共API来实现这一点,因此这里有一个使用私有方法和字段的变通方法。以下解决方案似乎适用于我的情况,我可以更改
PhotoView
的实际高度,并且缩放+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;
}

你能发布动画代码吗?这种方法有多个问题,首先当动画结束时比例和y位置会被重置。另外,如果您滚动图像视图底部,然后设置其高度动画,则只有在动画完成后,显示矩阵才会正确更新。@Niko根据您的问题,我推断您不希望在动画过程中更新
照片视图
(根据
高度
的变化进行调整)。既然我的假设是错误的,你能解释一下预期的行为是什么吗?是的,我想调整高度,但我也希望比例和y位置保持不变。也许解释有点夸张confusing@Niko我已经对上面的答案进行了修改。将等待您对此的评论。正确的方法是分叉库并在那里添加代码,但这种解决方法对我来说已经足够了。谢谢你的帮助:)