Android 如何使用使用使用矩阵缩放的ImageView设置缩小动画
所以我有一个ImageView,它使用一个矩阵来缩放我正在显示的位图。我可以双击放大到全尺寸,我的缩放动画处理放大的动画,一切正常 现在我想再次双击以缩小,但当我使用ScaleAnimation设置动画时,ImageView不会在当前视口收缩时绘制图像的新曝光区域,而是会看到可见图像的部分在缩小。我尝试过使用ViewGroup.setClipChildrenfalse,但这只会留下上一帧中最后绘制的瑕疵-导致三倍伸缩效果,但不完全是我想要的效果 我知道有许多与缩放相关的问题,但没有一个涉及到我的情况——特别是设置缩小操作的动画。我有机械工作-即除了缩小动画,双击放大和缩小工程罚款Android 如何使用使用使用矩阵缩放的ImageView设置缩小动画,android,Android,所以我有一个ImageView,它使用一个矩阵来缩放我正在显示的位图。我可以双击放大到全尺寸,我的缩放动画处理放大的动画,一切正常 现在我想再次双击以缩小,但当我使用ScaleAnimation设置动画时,ImageView不会在当前视口收缩时绘制图像的新曝光区域,而是会看到可见图像的部分在缩小。我尝试过使用ViewGroup.setClipChildrenfalse,但这只会留下上一帧中最后绘制的瑕疵-导致三倍伸缩效果,但不完全是我想要的效果 我知道有许多与缩放相关的问题,但没有一个涉及到我的
有什么建议吗?最后,我决定停止使用Android提供的动画类,因为ScaleAnimation将一个比例应用于ImageView作为一个整体,然后与ImageView的图像矩阵的比例相结合,这使得我的工作变得复杂,除了剪辑问题。 因为我真正需要的是动画化对ImageView的矩阵所做的更改,所以我在本文末尾实现了OnDoubleTapListener——我把它作为一个练习留给读者添加缺少的字段和方法——我使用一些PointF和矩阵字段来避免过多的垃圾创建。基本上,动画本身是通过使用View.post来实现的,以不断发布一个Runnable,该Runnable增量更改ImageView的图像矩阵:
public boolean onDoubleTap(MotionEvent e) {
final float x = e.getX();
final float y = e.getY();
matrix.reset();
matrix.set(imageView.getImageMatrix());
matrix.getValues(matrixValues);
matrix.invert(inverseMatrix);
doubleTapImagePoint[0] = x;
doubleTapImagePoint[1] = y;
inverseMatrix.mapPoints(doubleTapImagePoint);
final float scale = matrixValues[Matrix.MSCALE_X];
final float targetScale = scale < 1.0f ? 1.0f : calculateFitToScreenScale();
final float finalX;
final float finalY;
// assumption: if targetScale is less than 1, we're zooming out to fit the screen
if (targetScale < 1.0f) {
// scaling the image to fit the screen, we want the resulting image to be centred. We need to take
// into account the shift that is applied to zoom on the tapped point, easiest way is to reuse
// the transformation matrix.
RectF imageBounds = new RectF(imageView.getDrawable().getBounds());
// set up matrix for target
matrix.reset();
matrix.postTranslate(-doubleTapImagePoint[0], -doubleTapImagePoint[1]);
matrix.postScale(targetScale, targetScale);
matrix.mapRect(imageBounds);
finalX = ((imageView.getWidth() - imageBounds.width()) / 2.0f) - imageBounds.left;
finalY = ((imageView.getHeight() - imageBounds.height()) / 2.0f) - imageBounds.top;
}
// else zoom around the double-tap point
else {
finalX = x;
finalY = y;
}
final Interpolator interpolator = new AccelerateDecelerateInterpolator();
final long startTime = System.currentTimeMillis();
final long duration = 800;
imageView.post(new Runnable() {
@Override
public void run() {
float t = (float) (System.currentTimeMillis() - startTime) / duration;
t = t > 1.0f ? 1.0f : t;
float interpolatedRatio = interpolator.getInterpolation(t);
float tempScale = scale + interpolatedRatio * (targetScale - scale);
float tempX = x + interpolatedRatio * (finalX - x);
float tempY = y + interpolatedRatio * (finalY - y);
matrix.reset();
// translate initialPoint to 0,0 before applying zoom
matrix.postTranslate(-doubleTapImagePoint[0], -doubleTapImagePoint[1]);
// zoom
matrix.postScale(tempScale, tempScale);
// translate back to equivalent point
matrix.postTranslate(tempX, tempY);
imageView.setImageMatrix(matrix);
if (t < 1f) {
imageView.post(this);
}
}
});
return false;
}
最后,我决定停止使用Android提供的动画类,因为ScaleAnimation将一个比例应用于ImageView作为一个整体,然后与ImageView的图像矩阵的比例相结合,这使得工作变得复杂,除了剪辑问题之外。 因为我真正需要的是动画化对ImageView的矩阵所做的更改,所以我在本文末尾实现了OnDoubleTapListener——我把它作为一个练习留给读者添加缺少的字段和方法——我使用一些PointF和矩阵字段来避免过多的垃圾创建。基本上,动画本身是通过使用View.post来实现的,以不断发布一个Runnable,该Runnable增量更改ImageView的图像矩阵:
public boolean onDoubleTap(MotionEvent e) {
final float x = e.getX();
final float y = e.getY();
matrix.reset();
matrix.set(imageView.getImageMatrix());
matrix.getValues(matrixValues);
matrix.invert(inverseMatrix);
doubleTapImagePoint[0] = x;
doubleTapImagePoint[1] = y;
inverseMatrix.mapPoints(doubleTapImagePoint);
final float scale = matrixValues[Matrix.MSCALE_X];
final float targetScale = scale < 1.0f ? 1.0f : calculateFitToScreenScale();
final float finalX;
final float finalY;
// assumption: if targetScale is less than 1, we're zooming out to fit the screen
if (targetScale < 1.0f) {
// scaling the image to fit the screen, we want the resulting image to be centred. We need to take
// into account the shift that is applied to zoom on the tapped point, easiest way is to reuse
// the transformation matrix.
RectF imageBounds = new RectF(imageView.getDrawable().getBounds());
// set up matrix for target
matrix.reset();
matrix.postTranslate(-doubleTapImagePoint[0], -doubleTapImagePoint[1]);
matrix.postScale(targetScale, targetScale);
matrix.mapRect(imageBounds);
finalX = ((imageView.getWidth() - imageBounds.width()) / 2.0f) - imageBounds.left;
finalY = ((imageView.getHeight() - imageBounds.height()) / 2.0f) - imageBounds.top;
}
// else zoom around the double-tap point
else {
finalX = x;
finalY = y;
}
final Interpolator interpolator = new AccelerateDecelerateInterpolator();
final long startTime = System.currentTimeMillis();
final long duration = 800;
imageView.post(new Runnable() {
@Override
public void run() {
float t = (float) (System.currentTimeMillis() - startTime) / duration;
t = t > 1.0f ? 1.0f : t;
float interpolatedRatio = interpolator.getInterpolation(t);
float tempScale = scale + interpolatedRatio * (targetScale - scale);
float tempX = x + interpolatedRatio * (finalX - x);
float tempY = y + interpolatedRatio * (finalY - y);
matrix.reset();
// translate initialPoint to 0,0 before applying zoom
matrix.postTranslate(-doubleTapImagePoint[0], -doubleTapImagePoint[1]);
// zoom
matrix.postScale(tempScale, tempScale);
// translate back to equivalent point
matrix.postTranslate(tempX, tempY);
imageView.setImageMatrix(matrix);
if (t < 1f) {
imageView.post(this);
}
}
});
return false;
}
您好……我喜欢您的代码,但……您没有提供calculateFitToScreenScale方法代码……您能为我提供吗……?您好……我喜欢您的代码,但……您没有提供calculateFitToScreenScale方法代码……您能为我提供吗。。。。。?