8 votes

Android : Obtenir des coordonnées correctes avec un canevas mis à l'échelle et translaté

J'écris une application Android (Xamarin) qui permet de zoomer et de faire un panoramique sur une image. Un utilisateur peut également cliquer sur une position de l'image. J'ai besoin de ces coordonnées sur l'image pour une utilisation ultérieure.

Le code suivant permet d'effectuer des zooms et des panoramiques sur l'image :

protected override void OnDraw(Canvas canvas)
{
    base.OnDraw(canvas);

    _maxX = canvas.Width;
    _maxY = canvas.Height;

    canvas.Translate(_posX, _posY);

    if (_scaleDetector.IsInProgress)
        canvas.Scale(_scaleFactor, _scaleFactor, _scaleDetector.FocusX, _scaleDetector.FocusY);
    else
        canvas.Scale(_scaleFactor, _scaleFactor, _lastGestureX, _lastGestureY);
}

Jusqu'ici tout va bien, maintenant j'ai quelques MotionEvent en cours d'utilisation, qui est un LongPressListener . J'ai écrit le code suivant pour convertir les coordonnées du fichier MotionEvent aux coordonnées de l'image :

var actualX = e.GetX() - (_parent._posX / _parent._scaleFactor);
var actualY = e.GetY() - (_parent._posY / _parent._scaleFactor);

e dans ce cas, il s'agit du cadre de l'image. Le cadre contient une image (qui est _parent ), l'utilisateur peut faire glisser l'image. _parent._posX/Y sont modifiées lorsque cela se produit. L'utilisateur peut également zoomer sur l'image. _scaleFactor .

Ainsi, lorsqu'un utilisateur tape n'importe où dans e Je dois donc traduire ces coordonnées en coordonnées d'image.

Ces deux lignes de code fonctionnent, mais lorsque l'utilisateur zoome, les coordonnées ne sont pas correctes, comme vous pouvez le voir dans l'image ci-jointe :

Screen recording

Les points rouges représentent les positions calculées. Comme vous pouvez le voir, si l'utilisateur zoome, les coordonnées deviennent plus imprécises. Qu'est-ce qui ne va pas dans ce calcul ?

3voto

Amol Jindal Points 106

Essayez de le faire :-

  var actualX = (e.GetX() - _parent._posX) / _parent._scaleFactor;

  var actualY = (e.GetY() - _parent._posY) / _parent._scaleFactor;

0voto

Nekeniehl Points 563

Je pense que votre problème est dû au fait que le Canvas n'est pas mis à jour. Canvas.UpdateLayout après un zoom.

0voto

Giovanni Terlingen Points 2027

J'ai réussi à le réparer en utilisant un Matrix :

private float[] TranslateCoordinates(float[] coordinates)
{
    var matrix = new Matrix(Matrix);

    matrix.PreScale(_scaleFactor, _scaleFactor);
    matrix.PreTranslate(_posX, _posY);

    matrix.Invert(matrix);
    matrix.MapPoints(coordinates);

    return coordinates;
}

En float[] contient les valeurs de MotionEvent 's GetX() y GetY() .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X