web-dev-qa-db-fra.com

Android échelle de matrice de vue d'image + traduire

J'essaie d'obtenir manuellement une image à l'intérieur d'une image centrée et d'ajuster l'écran. Je dois le faire avec une matrice (je changerai plus tard dynamiquement la transformation de la matrice).

Le problème est que je ne parviens pas à centrer l'image dans la vue (l'échelle est appropriée). Voici le code:

// Compute the scale to choose (this works)
float scaleX = (float) displayWidth / (float) imageWidth;
float scaleY = (float) displayHeight / (float) imageHeight;
float minScale = Math.min(scaleX, scaleY);

// tx, ty should be the translation to take the image back to the screen center
float tx = Math.max(0, 
        0.5f * ((float) displayWidth - (minScale * imageWidth)));
float ty = Math.max(0, 
        0.5f * ((float) displayHeight - (minScale * imageHeight)));

// Compute the matrix
Matrix m = new Matrix();
m.reset();

// Middle of the image should be the scale pivot
m.postScale(minScale, imageWidth/2, imageHeight/2);

// Translate
m.postTranslate(tx, ty);

imageView.setImageMatrix(m);

Le code ci-dessus fonctionne si je ne centre pas l'échelle sur le centre de l'image (mais je devrai le faire plus tard, je dois donc comprendre la formule maintenant).

Je pensais que faire ce qui suit corrigerait le problème, mais l'image est toujours décalée (vers le bas et la droite).

tx += 0.5*imageWidth*minScale;
ty += 0.5*imageHeight*minScale;

Quelques valeurs que j'ai: - image: 200x133 - affichage: 800x480 - minScale: 2.4 - dernier coin supérieur gauche de l'image: 100, 67 (devrait être 17, 0)

30

Il existe une méthode pratique appelée Matrix.setRectToRect (RectF, RectF, ScaleToFit) pour vous aider ici.

Matrix m = imageView.getImageMatrix();
RectF drawableRect = new RectF(0, 0, imageWidth, imageHeight);
RectF viewRect = new RectF(0, 0, imageView.getWidth(), imageView.getHeight());
m.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.CENTER);
imageView.setImageMatrix(m);

Cela devrait définir la matrice m pour avoir un combo de mise à l'échelle et traduire les valeurs nécessaires pour montrer le dessinable centré et tenir dans le widget ImageView.

66
Joakim Erdfelt

Voici comment j'ai résolu mon problème en utilisant des matrices (demandé par joakime dans l'autre réponse):

private void setImageTransformation(float tx, float ty, float scale) {
    savedMatrix.reset();
    savedMatrix.postTranslate(-imageWidth / 2f, -imageHeight / 2f);
    savedMatrix.postScale(scale, scale);
    savedMatrix.postTranslate(tx, ty);
    imageView.setImageMatrix(savedMatrix);
}

public void resetImageMatrix() {
    if (!isImageLoaded()) return;

    imageWidth = imageView.getDrawable().getIntrinsicWidth();
    imageHeight = imageView.getDrawable().getIntrinsicHeight();

    float scaleX = (float) displayWidth / (float) imageWidth;
    float scaleY = (float) displayHeight / (float) imageHeight;
    minScale = Math.min(scaleX, scaleY);
    maxScale = 2.5f * minScale;

    initialTranslation.set(
              Math.max(0, 
                minScale * imageWidth / 2f 
                + 0.5f * (displayWidth - (minScale * imageWidth))), 
              Math.max(0, 
                minScale * imageHeight / 2f
                + 0.5f * (displayHeight - (minScale * imageHeight))));

    currentScale = minScale;
    currentTranslation.set(initialTranslation);
    initialImageRect.set(0, 0, imageWidth, imageHeight);

    setImageTransformation(initialTranslation.x, initialTranslation.y, 
                minScale);
}

Je triche un peu ici car le pincement n'est pas vraiment centré entre les doigts de l'utilisateur, ce qui est acceptable dans mon cas.

5

Ou en utilisant

    m.postScale(minScale, minScale); //keep aspect ratio

    float tx = (getWidth() - bitmap1.getWidth()* scale) * 0.5f ;
    float ty = (getHeight() - bitmap1.getHeight()* scale) * 0.5f ;

    matrix.postTranslate(tx, ty );

où getWidth est la largeur de votre imageView. Fonctionne parfaitement pour moi

1
voytez

Hé, j'avais le même problème, et tu étais si proche! C'était une question d'ordre des opérations, du moins pour moi. Ce qui suit a fonctionné pour moi:

tx = (width - imgWidth) * 0.5f * scale;
1
scone