我的问题最类似于:
Android 4.3 ImageView ScaleType.MATRIX
但也回响:
但是,使用这些答案的解决方案解决了我的问题。
我正在使用 Mike Ortiz 的 TouchImageView 的修改版本,以允许双击和常规缩放手势来缩放我的 ImageView。对于Android 4.2.2及更低版本,注释掉“setScaleType(ScaleType.MATRIX)”就可以了,图片在ImageView中居中,可以随意放大缩小。但是,取消注释会导致 ImageView 的图像大小不正确。所有这一切都很好,因为我刚刚留下那行评论,一切正常。
但是,从 Android 4.3 开始,您无法在没有 setScaleType(ScaleType.MATRIX) 的情况下进行缩放。所以我不得不取消注释该行,但我从未解决的老问题又回来了。
那么,首先,当我所做的只是设置 ScaleType 时,为什么我的计算无法产生正确的图像/ImageView 比率?其次,为什么它会在 4.2.2 上放大而不设置比例类型,但在 4.3 上却不会?最后,有人可以给我一些资源来了解更多关于 ScaleType.MATRIX 的真正作用吗?我已经阅读了一些资料,并进行了一些谷歌搜索,但并不完全掌握它。
提前谢谢你,下面的代码。
public class TouchImageView extends ImageView {
Matrix matrix = new Matrix();
// We can be in one of these 3 states
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
// Remember some things for zooming
PointF last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 10f;
float[] floatArray;
float unusedWidth, unusedHeight;
float imageViewWidth, imageViewHeight;
float initialScale = 1f;
float right, bottom, origWidth, origHeight, imageWidth, imageHeight;
boolean zoomedInLastTime = false;
PointF zoomCenter;
ScaleGestureDetector mScaleDetector;
GestureDetector mDetector;
Context context;
public TouchImageView(Context context) {
super(context);
sharedConstructing(context);
}
public TouchImageView(Context context, AttributeSet attrs) {
super(context, attrs);
sharedConstructing(context);
}
private void sharedConstructing(Context context) {
super.setClickable(true);
this.context = context;
setScaleType(ScaleType.MATRIX);
//matrix = this.getImageMatrix();
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
//this is an empty GestureDetector
mDetector = new GestureDetector(this.context, new GestureDetector.OnGestureListener() {
@Override
public boolean onDown(MotionEvent motionEvent) {
return false;
}
@Override
public void onShowPress(MotionEvent motionEvent) {
}
@Override
public boolean onSingleTapUp(MotionEvent motionEvent) {
return false;
}
@Override
public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent2, float v, float v2) {
return false;
}
@Override
public void onLongPress(MotionEvent motionEvent) {
}
@Override
public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent2, float v, float v2) {
return false;
}
}, null, true);
mDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener(){
@Override
public boolean onSingleTapConfirmed(MotionEvent motionEvent) {
return false;
}
@Override
public boolean onDoubleTap(MotionEvent motionEvent) {
Log.d("TouchImageView", "double tap heard");
PointF currentTapLocation = new PointF(motionEvent.getX(), motionEvent.getY());
if (!zoomedInLastTime){
(new ScaleListener()).scaleIt(3f,currentTapLocation.x,currentTapLocation.y);
zoomCenter = currentTapLocation;
zoomedInLastTime = true;
}else {
(new ScaleListener()).scaleIt(.33f, zoomCenter.x, zoomCenter.y);
zoomedInLastTime = false;
}
return true;
}
@Override
public boolean onDoubleTapEvent(MotionEvent motionEvent) {
return false;
}
});
matrix.setTranslate(1f, 1f);
floatArray = new float[9];
setImageMatrix(matrix);
setOnTouchListener(new DoubleTapPinchZoomListener());
}
@Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
if(bm != null) {
if (Build.VERSION.SDK_INT > 17){
imageWidth = bm.getWidth();
imageHeight = bm.getHeight();
} else {
imageWidth = 2*bm.getWidth();
imageHeight = 2*bm.getHeight();
}
}
}
public void setMaxZoom(float x)
{
maxScale = x;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
mode = ZOOM;
return true;
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
float mScaleFactor = detector.getScaleFactor();
scaleIt(mScaleFactor, detector.getFocusX(), detector.getFocusY());
return true;
}
public void scaleIt(float mScaleFactor, float focusx, float focusy){
float origScale = initialScale;
initialScale *= mScaleFactor;
if (initialScale > maxScale) {
initialScale = maxScale;
mScaleFactor = maxScale / origScale;
} else if (initialScale < minScale) {
initialScale = minScale;
mScaleFactor = minScale / origScale;
}
right = imageViewWidth * initialScale - imageViewWidth - (2 * unusedWidth * initialScale);
bottom = imageViewHeight * initialScale - imageViewHeight - (2 * unusedHeight * initialScale);
if (origWidth * initialScale <= imageViewWidth || origHeight * initialScale <= imageViewHeight) {
matrix.postScale(mScaleFactor, mScaleFactor, imageViewWidth / 2, imageViewHeight / 2);
if (mScaleFactor < 1) {
matrix.getValues(floatArray);
float x = floatArray[Matrix.MTRANS_X];
float y = floatArray[Matrix.MTRANS_Y];
if (mScaleFactor < 1) {
if (Math.round(origWidth * initialScale) < imageViewWidth) {
if (y < -bottom)
matrix.postTranslate(0, -(y + bottom));
else if (y > 0)
matrix.postTranslate(0, -y);
} else {
if (x < -right)
matrix.postTranslate(-(x + right), 0);
else if (x > 0)
matrix.postTranslate(-x, 0);
}
}
}
} else {
matrix.postScale(mScaleFactor, mScaleFactor, focusx, focusy);
matrix.getValues(floatArray);
float x = floatArray[Matrix.MTRANS_X];
float y = floatArray[Matrix.MTRANS_Y];
if (mScaleFactor < 1) {
if (x < -right)
matrix.postTranslate(-(x + right), 0);
else if (x > 0)
matrix.postTranslate(-x, 0);
if (y < -bottom)
matrix.postTranslate(0, -(y + bottom));
else if (y > 0)
matrix.postTranslate(0, -y);
}
}
}
}
@Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
imageViewWidth = MeasureSpec.getSize(widthMeasureSpec);
imageViewHeight = MeasureSpec.getSize(heightMeasureSpec);
/*RectF drawableRect = new RectF(0, 0, imageWidth, imageHeight);
RectF viewRect = new RectF(0, 0, imageViewWidth, imageViewHeight);
//draw the image in the view
matrix.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.CENTER);*/
//Fit to screen.
float scale;
float scaleX = (float) imageViewWidth / (float)(imageWidth);
float scaleY = (float) imageViewHeight / (float)(imageHeight);
scale = Math.min(scaleX, scaleY);
matrix.setScale(scale, scale);
setImageMatrix(matrix);
initialScale = 1f;
// Center the image
unusedHeight = (float) imageViewHeight - (scale * (float) imageHeight) ;
unusedWidth = (float) imageViewWidth - (scale * (float) imageWidth);
unusedHeight /= (float)2;
unusedWidth /= (float)2;
matrix.postTranslate(unusedWidth, unusedHeight);
origWidth = imageViewWidth - 2 * unusedWidth;
origHeight = imageViewHeight - 2 * unusedHeight;
right = imageViewWidth * initialScale - imageViewWidth - (2 * unusedWidth * initialScale);
bottom = imageViewHeight * initialScale - imageViewHeight - (2 * unusedHeight * initialScale);
setImageMatrix(matrix);
}
class DoubleTapPinchZoomListener implements OnTouchListener {
@Override
public boolean onTouch(View v, MotionEvent event) {
mScaleDetector.onTouchEvent(event);
mDetector.onTouchEvent(event);
matrix.getValues(floatArray);
float x = floatArray[Matrix.MTRANS_X];
float y = floatArray[Matrix.MTRANS_Y];
PointF curr = new PointF(event.getX(), event.getY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
last.set(event.getX(), event.getY());
start.set(last);
mode = DRAG;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
float deltaX = curr.x - last.x;
float deltaY = curr.y - last.y;
float scaleWidth = Math.round(origWidth * initialScale);
float scaleHeight = Math.round(origHeight * initialScale);
if (scaleWidth < imageViewWidth) {
deltaX = 0;
if (y + deltaY > 0)
deltaY = -y;
else if (y + deltaY < -bottom)
deltaY = -(y + bottom);
} else if (scaleHeight < imageViewHeight) {
deltaY = 0;
if (x + deltaX > 0)
deltaX = -x;
else if (x + deltaX < -right)
deltaX = -(x + right);
} else {
if (x + deltaX > 0)
deltaX = -x;
else if (x + deltaX < -right)
deltaX = -(x + right);
if (y + deltaY > 0)
deltaY = -y;
else if (y + deltaY < -bottom)
deltaY = -(y + bottom);
}
matrix.postTranslate(deltaX, deltaY);
last.set(curr.x, curr.y);
}
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
}
setImageMatrix(matrix);
invalidate();
return true;
}
}
}