我对 Android 中的图像缩放和拖动有疑问。我创建了自己的视图。视图的一部分是可缩放和可拖动的图像。只要图像的这一部分与整个视图一样大,一切正常。图像缩放和拖动完美,限制也很好。但是,当我尝试只用位图填充视图的一部分时,我对图像右下角的限制就会中断。图像缩放得越多,右下角的冗余偏移量就越多。
矩阵需要独立于屏幕和视图大小,因为用户可以保存视图的矩阵。为了使矩阵独立,我声明了一个值 getPIXEL_INDEPENDENT_INNER_WIDTH / getPIXEL_INDEPENDENT_INNER_HEIGHT,它是图像的大小。整个视图的大小在 getPIXEL_INDEPENDENT_HEIGHT / getPIXEL_INDEPENDENT_WIDTH 中声明。结果,即使视图变形,视图的比例也始终相同。
我认为原因是图像的后期缩放/翻译。另一方面,ondraw 方法不会改变矩阵。它制作一个副本,然后重新翻译和重新缩放视图内部的图像。
这里以图片来演示这个问题:
源代码:
设置内容:
private float minScale;
private float PIXEL_INDEPENDENT_INNER_WIDTH;
private float PIXEL_INDEPENDENT_INNER_HEIGHT;
public void setContent(FailPictureInfoContainer ic, Bitmap bm) {
if (ic == null)
return;
ic.text[0] = (ic.text[0] != null) ? ic.text[0] : "";
ic.text[1] = (ic.text[1] != null) ? ic.text[1] : "";
bitmap = bm;
//CREATE MATRIX
Matrix m = new Matrix();
float[] matrixAsFloats = new float[9];
if (bitmap != null) {//Wenn Bild vorhanden und noch ohne Matrix, angepasste Matrix erzeugen.
//Wenn breiter als hoch
if (getPIXEL_INDEPENDENT_INNER_WIDTH()/bm.getWidth() < getPIXEL_INDEPENDENT_INNER_HEIGHT()/bm.getHeight())
m.postScale(getPIXEL_INDEPENDENT_INNER_HEIGHT() / bm.getHeight(), getPIXEL_INDEPENDENT_INNER_HEIGHT() / bm.getHeight());
//Wenn höher als breit
else
m.postScale(getPIXEL_INDEPENDENT_INNER_WIDTH() / bm.getWidth(), getPIXEL_INDEPENDENT_INNER_WIDTH() / bm.getWidth());
}
m.getValues(matrixAsFloats);
setMinScale((matrixAsFloats[Matrix.MSCALE_X]>matrixAsFloats[Matrix.MSCALE_Y]) ? matrixAsFloats[Matrix.MSCALE_X] : matrixAsFloats[Matrix.MSCALE_Y]);
if (ic.matrix == null)
ic.matrix = matrixAsFloats;
this.ic = ic;
update();
}
画布:
@Override
void drawOnCanvas(Canvas canvas, float width, float height) {
if (bitmap == null || matrix_pixel_independent == null || ic == null)
return;
System.out.println(Arrays.toString(getIc().matrix));
// TopText & BottomText ANGLEICHEN
TextPaint_TOP = getFormattedTextView((int) (ic.textsize[0] * width / getPIXEL_OUTPUT_WIDTH()), ic.color[0]);
TextPaint_BOTTOM = getFormattedTextView((int) (ic.textsize[1] * width / getPIXEL_OUTPUT_WIDTH()), ic.color[1]);
// Canvas anpassen.
canvas.setDensity(bitmap.getDensity());
matrix_pixel_dependent.set(matrix_pixel_independent);
float borderPadding = 7f * width / getPIXEL_INDEPENDENT_WIDTH(); //Abstand zwischen Linie und Bild.
float paddingFactor = (getPIXEL_INDEPENDENT_WIDTH() - getPIXEL_INDEPENDENT_INNER_WIDTH()) / 2 * width
/ getPIXEL_INDEPENDENT_WIDTH(); //Abstand zwischen View und Bild.
float lowerBound = getPIXEL_INDEPENDENT_INNER_HEIGHT() * height / getPIXEL_INDEPENDENT_HEIGHT() + paddingFactor + borderPadding; // Entspricht y-Wert unter Bild und Padding.
matrix_pixel_dependent.preScale(width / getPIXEL_INDEPENDENT_WIDTH(), height / getPIXEL_INDEPENDENT_HEIGHT(), 0,0);
matrix_pixel_dependent.postTranslate(paddingFactor, paddingFactor);
canvas.drawBitmap(bitmap, matrix_pixel_dependent, paint);
paint.setColorFilter(null);
}
触摸事件:
@Override
public boolean onTouchEvent(MotionEvent event) {
if (bitmap == null || getIc() == null)
return true;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
//DOUBLE TAP
lastTapped = System.currentTimeMillis() - lastTapped;
if (lastTapped < 350 && lastTapped > 90){
touchEnabled = !touchEnabled;
lastTapped = System.currentTimeMillis()-900;
}else
lastTapped = System.currentTimeMillis();
if (!touchEnabled) {
invalidate();
return false;
}
//MOVE PREPARE
savedMatrix.set(matrix_pixel_independent);
Finger_startPosition.set(event.getX(), event.getY());
mode = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN:
Finger_oldDistance = spacing(event);
if (Finger_oldDistance > 3f) {
savedMatrix.set(matrix_pixel_independent);
midPoint(Finger_Midpoint, event);
mode = ZOOM;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_OUTSIDE:
mode = NONE;
if (posChanged) {
posChanged = false;
if (getIc().matrix[Matrix.MSCALE_X] < getMinScale()) {
float scale = getMinScale() / getIc().matrix[Matrix.MSCALE_X];
matrix_pixel_independent.preScale(scale, scale, Finger_Midpoint.x, Finger_Midpoint.y);
}
matrix_pixel_independent.getValues(getIc().matrix);
float newX_post = 0;
float newY_post = 0;
float imageWidth_post = newX_post + bitmap.getWidth() * getIc().matrix[Matrix.MSCALE_X];
float imageHeight_post = newY_post + bitmap.getHeight() * getIc().matrix[Matrix.MSCALE_Y];
RectF drawingRect_post = new RectF(getIc().matrix[Matrix.MTRANS_X], getIc().matrix[Matrix.MTRANS_Y],
getIc().matrix[Matrix.MTRANS_X] + imageWidth_post, getIc().matrix[Matrix.MTRANS_Y] + imageHeight_post);
float diffUp_post = Math.min(getPIXEL_INDEPENDENT_INNER_HEIGHT() - drawingRect_post.bottom, -drawingRect_post.top);
float diffDown_post = Math.max(getPIXEL_INDEPENDENT_INNER_HEIGHT() - drawingRect_post.bottom, -drawingRect_post.top);
float diffLeft_post = Math.min(getPIXEL_INDEPENDENT_INNER_WIDTH() - drawingRect_post.right, -drawingRect_post.left);
float diffRight_post = Math.max(getPIXEL_INDEPENDENT_INNER_WIDTH() - drawingRect_post.right, -drawingRect_post.left);
if (diffUp_post > 0)
newY_post += diffUp_post;
if (diffDown_post < 0)
newY_post += diffDown_post;
if (diffLeft_post > 0)
newX_post += diffLeft_post;
if (diffRight_post < 0)
newX_post += diffRight_post;
matrix_pixel_independent.postTranslate(newX_post, newY_post);
Log.d(MainActivity.TAG, "width: "+imageWidth_post+" height: "+imageHeight_post+ " xstart: "+getIc().matrix[Matrix.MTRANS_X]+ " ystart: " +getIc().matrix[Matrix.MTRANS_Y]+ " xend: "+ getIc().matrix[Matrix.MTRANS_X] + imageWidth_post+" yend: "+getIc().matrix[Matrix.MTRANS_Y] + imageHeight_post);
//Listener anstupsen.
if (OnMeGustaViewChangedListener != null)
OnMeGustaViewChangedListener.onViewChanged();
matrix_pixel_independent.getValues(getIc().matrix);
}
break;
case MotionEvent.ACTION_MOVE:
matrix_pixel_independent.set(savedMatrix);
if (mode == DRAG) {
//DRAGGING
float eventX = event.getX() - Finger_startPosition.x;
float eventY = event.getY() - Finger_startPosition.y;
matrix_pixel_independent.postTranslate(eventX, eventY);
//Position hat sich geändert -> Listener.
posChanged = eventX != 0 || eventY != 0;
} else if (mode == ZOOM) {
//ZOOMING
float newDist = spacing(event);
if (newDist > 3f) {
float scale = newDist / Finger_oldDistance;
matrix_pixel_independent.postScale(scale, scale, Finger_Midpoint.x, Finger_Midpoint.y);
//Position hat sich geändert -> Listener.
posChanged = true;
}
}
matrix_pixel_independent.getValues(getIc().matrix);
}
invalidate();
return true;
}
/**
* Spacing between Fingers on event.
*
* @param event
* @return
*/
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
/**
* MidPoint between Fingers on event.
*
* @param point
* @param event
*/
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
尝试解决几天,请帮助我!将非常感谢!