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();
}
drawOnCanvas:
@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);
}
onTouchEvent:
@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);
}
何日も解決してみてください、助けてください!とても感謝しています!