[英]Animate Android PhotoView height
我正在使用https://github.com/chrisbanes/PhotoView并尝试设置其高度的动画。
我使用ValueAnimator
并更新布局高度,以触发内部PhotoViewAttacher
和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());
onAnimationEnd():
mPhotoView.getViewTreeObserver()
.addOnGlobalLayoutListener((PhotoViewAttacher)mPhotoView.getIPhotoViewImplementation());
请注意, removeOnGlobalLayoutListener(OnGlobalLayoutListener)
可用于> = 16的API版本。 在此之前,您将使用removeGlobalOnLayoutListener(OnGlobalLayoutListener)
。
onAnimationStart()
和onAnimationEnd()
回调,通过添加ValueAnimator.AnimatorUpdateListener
您ValueAnimator
。
再次,我不知道这是否行得通-看起来应该如此。
编辑:
以下内容与上面的代码无关。
除了可以对PhotoView
的height
设置动画之外,还可以为其top
和bottom
属性设置动画。 在我的测试中,设置这些属性的动画不会重置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.