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

画布:

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

尝试解决几天,请帮助我!将非常感谢!

4

0 回答 0