web-dev-qa-db-fra.com

Android: comment faire pivoter une image sur un point central

Je cherche depuis plus d'une journée une solution à ce problème mais rien n'y fait, même les réponses ici. La documentation n'explique rien aussi.

J'essaie simplement d'obtenir une rotation dans la direction d'un autre objet. Le problème est que le bitmap n'est pas pivoté autour d'un point fixe, mais plutôt autour des bitmaps (0,0).

Voici le code avec lequel j'ai des problèmes:

  Matrix mtx = new Matrix();
  mtx.reset();
  mtx.preTranslate(-centerX, -centerY);
  mtx.setRotate((float)direction, -centerX, -centerY);
  mtx.postTranslate(pivotX, pivotY);
  Bitmap rotatedBMP = Bitmap.createBitmap(bitmap, 0, 0, spriteWidth, spriteHeight, mtx, true);
  this.bitmap = rotatedBMP;

La partie étrange est, peu importe la façon dont je change les valeurs dans pre/postTranslate() et les arguments flottants dans setRotation(). Quelqu'un peut-il s'il vous plaît aider et me pousser dans la bonne direction? :)

82
Stefan

J'espère que la séquence de code suivante vous aidera:

Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight, config);
Canvas canvas = new Canvas(targetBitmap);
Matrix matrix = new Matrix();
matrix.setRotate(mRotation,source.getWidth()/2,source.getHeight()/2);
canvas.drawBitmap(source, matrix, new Paint());

Si vous vérifiez la méthode suivante à partir de ~frameworks\base\graphics\Java\Android\graphics\Bitmap.Java

public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
        Matrix m, boolean filter)

cela expliquerait ce qu'il fait avec rotation et traduire.

100
Sudar Nimalan

Edité: code optimisé.

public static Bitmap RotateBitmap(Bitmap source, float angle)
{
      Matrix matrix = new Matrix();
      matrix.postRotate(angle);
      return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}

Pour obtenir du bitmap à partir de ressources:

Bitmap source = BitmapFactory.decodeResource(this.getResources(), R.drawable.your_img);
77
Arvis

Je suis revenu à ce problème maintenant que nous finalisions le jeu et je pensais juste à poster ce qui a fonctionné pour moi.

Voici la méthode de rotation de la matrice:

this.matrix.reset();
this.matrix.setTranslate(this.floatXpos, this.floatYpos);
this.matrix.postRotate((float)this.direction, this.getCenterX(), this.getCenterY()); 

(this.getCenterX() est fondamentalement la position X des bitmaps + la largeur des bitmaps/2)

Et la méthode pour dessiner le bitmap (appelée via une classe RenderManager):

canvas.drawBitmap(this.bitmap, this.matrix, null);

C'est donc assez simple, mais je trouve cela un peu étrange de ne pas pouvoir le faire fonctionner par setRotate suivi de postTranslate. Peut-être que certains savent pourquoi cela ne fonctionne pas? Désormais, toutes les bitmaps pivotent correctement, mais cela ne va pas sans une légère diminution de la qualité bitmap: /

Quoi qu'il en soit, merci pour votre aide!

25
Ste

Vous pouvez également faire pivoter le ImageView en utilisant un RotateAnimation:

RotateAnimation rotateAnimation = new RotateAnimation(from, to,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                0.5f);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setDuration(ANIMATION_DURATION);
rotateAnimation.setFillAfter(true);

imageView.startAnimation(rotateAnimation);
7
Macarse

Vous pouvez utiliser quelque chose comme suit:


Matrix matrix = new Matrix();
matrix.setRotate(mRotation,source.getWidth()/2,source.getHeight()/2);
RectF rectF = new RectF(0, 0, source.getWidth(), source.getHeight());
matrix.mapRect(rectF);
Bitmap targetBitmap = Bitmap.createBitmap(rectF.width(), rectF.height(), config);
Canvas canvas = new Canvas(targetBitmap);
canvas.drawBitmap(source, matrix, new Paint());
5
Sudar Nimalan

Regardez l'exemple de Google appelé Lunar Lander, l'image du bateau y est tournée dynamiquement.

exemple de code Lunar Lander

1
sprite

J'ai utilisé cette configuration et j'ai toujours le problème de la pixelisation:

Bitmap bmpOriginal = BitmapFactory.decodeResource(this.getResources(), R.drawable.map_pin);
        Bitmap targetBitmap = Bitmap.createBitmap((bmpOriginal.getWidth()),
                (bmpOriginal.getHeight()), 
                Bitmap.Config.ARGB_8888);
        Paint p = new Paint();
        p.setAntiAlias(true);

        Matrix matrix = new Matrix();       
        matrix.setRotate((float) lock.getDirection(),(float) (bmpOriginal.getWidth()/2),
                (float)(bmpOriginal.getHeight()/2));

        RectF rectF = new RectF(0, 0, bmpOriginal.getWidth(), bmpOriginal.getHeight());
        matrix.mapRect(rectF);

        targetBitmap = Bitmap.createBitmap((int)rectF.width(), (int)rectF.height(), Bitmap.Config.ARGB_8888);


        Canvas tempCanvas = new Canvas(targetBitmap); 
        tempCanvas.drawBitmap(bmpOriginal, matrix, p);
1
MSaudi
matrix.reset();
matrix.setTranslate( anchor.x, anchor.y );
matrix.postRotate((float) rotation , 0,0);
matrix.postTranslate(positionOfAnchor.x, positionOfAnchor.x);
c.drawBitmap(bitmap, matrix, null); 
0
Louie Almeda