2

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);
}

何日も解決してみてください、助けてください!とても感謝しています!

4

0 に答える 0