Offseting le centre de la MapFragment pour une animation le déplacement de la cible lat/lng et le niveau de zoom
J'ai une INTERFACE utilisateur qui dispose d'un MapFragment avec une Vue transparente placée au-dessus d'elle. La carte reprend la totalité de l'écran, tandis que la Vue est juste le tiers gauche de l'écran. En conséquence, la valeur par défaut "centre" de la carte est éteint. Lorsque quelqu'un clique sur un marqueur, je veux de centre de marqueur dans la filiale zone visible de la MapFragment (pas le centre de la MapFragment lui-même).
Car c'est difficile à décrire avec des mots, permettez-moi de prendre quelques photos. Supposons que c'est la façon dont mon INTERFACE utilisateur semble:
Lorsque l'utilisateur clique sur un marqueur, je veux à la fois le centre il et zoomer pour voir de plus près. Sans aucun réglage, c'est ce que vous obtiendrez:
Ce que je veux, c'est pour le marqueur à être centré, mais dans l'espace à droite, comme ceci:
Il est très facile à réaliser cet exploit si vous n'êtes pas changer le niveau de zoom à l'aide de la carte de projection:
//Offset the target latitude/longitude by preset x/y ints
LatLng target = new LatLng(latitude, longitude);
Projection projection = getMap().getProjection();
Point screenLocation = projection.toScreenLocation(target);
screenLocation.x += offsetX;
screenLocation.y += offsetY;
LatLng offsetTarget = projection.fromScreenLocation(screenLocation);
//Animate to the calculated lat/lng
getMap().animateCamera(CameraUpdateFactory.newLatLng(offsetTarget));
Toutefois, si vous décidez de changer le niveau de zoom dans le même temps, les calculs ci-dessus ne fonctionnent pas (depuis le lat/lng décalages de changement à différents niveaux de zoom).
Permettez-moi de lancer une liste de tentative de correctifs:
-
Changer le niveau de zoom rapidement, en faisant les calculs, le zoom arrière à l'original de la position de la caméra, puis l'animer. Malheureusement, le brusque changement de caméra (même si c'est seulement pour une fraction de seconde) est malheureusement très évident et je voudrais éviter le scintillement.
-
La superposition de deux MapFragments sur le dessus les uns des autres, d'en avoir un pour faire les calculs, tandis que l'autre affiche. J'ai trouvé que MapFragments ne sont pas vraiment construit pour être superposées les unes aux autres (il y a des inévitables bugs en bas de cette route).
-
La modification de l'emplacement d'un écran de x/y par la différence de niveau de zoom au carré. Théoriquement, cela devrait fonctionner, mais c'est toujours par un peu (~.1 latitude/longitude, ce qui est suffisant pour être loin).
Est-il un moyen de calculer la offsetTarget même avec le niveau de zoom en train de changer?
- "depuis le lat/lng modifications requises à différents niveaux de zoom" -- qui n'a pas vraiment beaucoup de sens pour moi. Au-delà de ça, je ne suis pas certain pourquoi vous allez à travers tout l'écran de coordonner les choses. "Le tiers gauche" est "le tiers gauche" si vous mesurez en pixels, en degrés, en millimètres, de parsecs, ou quoi que ce soit. Permettrait de garder tous vos calculs en termes de latitude et de longitude de l'aide?
- J'ai pensé que ce serait difficile à expliquer avec de simples mots; permettez-moi de tenter de dresser une image qui éclaire le problème.
- Là, même question mais avec des aides visuelles. Le problème avec l'aide de tous latitude/longitude pour les calculs, c'est que le décalage je désir est purement mesurée en pixels (basé sur la taille de l'écran et la façon dont beaucoup de la MapFragment est visible).
- "le décalage je désir est purement mesurée en pixels" -- alors, quand vous avez écrit "la Vue est juste le tiers gauche de l'écran", ce n'était pas une déclaration exacte? Parce que, si elle est exacte, les pixels ne sont pas pertinents, comme un tiers, un tiers, un tiers, indépendamment des unités de mesure.
- Les pixels qui constituent 1/3ème de l'écran change en fonction la taille de l'écran. L'appareil changements nécessitent une cible LatLng, donc je dois être capable de tout convertir/de LatLng. Essentiellement, je suis en train de convertir les pixels sur l'écran à un décalage en latitude/longitude. Que lat/lng compenser les variations selon le niveau de zoom, depuis plus de zoom, plus les degrés de changement, vous devez déplacer autour de la carte.
- En outre, je suis en simplifiant le problème un peu pour des raisons de concision. La Vue sur la gauche n'est pas 1/3ème, c'est en fait un ensemble de largeur qui varie selon la min-largeur de la tablette. En outre, je tiens aussi à décaler verticalement (car je veux montrer certains de l'information interactive au-dessus du marqueur ainsi, dans une fenêtre contextuelle).
- Ah! OK, je comprends maintenant pourquoi vous avez besoin de pixels. Malheureusement, je n'ai pas de solution pour vous. 🙁
- vous l'avez résolu ? J'ai le même problème!
Vous devez vous connecter pour publier un commentaire.
La plus récente version de la pièce de la bibliothèque de services ajoute un
setPadding()
fonction deGoogleMap
. Ce rembourrage va projeter tous les mouvements de caméra pour le décalage de la carte du centre. Ce document décrit en outre comment la carte de rembourrage se comporte.La question initialement posée ici peuvent maintenant être simplement résolu par l'ajout de remplissage à gauche de l'équivalent de la largeur de la gauche mise en page.
J'ai trouvé une solution qui convient vraiment à ce problème.
La solution est de calculer le décalage du centre dans le zoom de l'original de l'offset, et puis d'animer la carte de l'appareil photo.
Pour cela, commencez par déplacer la carte de l'appareil photo pour le niveau de zoom désiré, calculer le décalage pour que le niveau de zoom, puis de restaurer le zoom d'origine. Après le calcul de la nouveau centre, nous pouvons faire de l'animation avec CameraUpdateFactory.newLatLngZoom.
J'espère que cela aide!
Edit: Le code ci-dessous est pour le obsolète v1 cartes. Ceci AFIN de répondre à ces états à exécuter des actions similaires dans la v2: Comment obtenir la Latitude/Longitude durée de Google Map V2 pour Android
Les principales méthodes dont vous avez besoin doivent travailler en long/lat et les pourcentages au lieu de pixels. Maintenant, la mapview un zoom autour du centre de la carte, et de passer ensuite à "recentrer" le pin dans la zone exposée. Vous pouvez obtenir la largeur après le zoom en degrés, facteur dans certaines écran de biais, puis recentrer la carte. Voici un exemple de capture d'écran du code ci-dessous dans l'action après avoir appuyé sur le"+": avant
après
Code principal:
Tous les code:
et une structure de base:
Si ce n'est pas de répondre complètement à votre question, s'il vous plaît laissez-moi savoir que c'était une expérience amusante à jouer avec.
L'API projection de la substance n'est pas utile, j'ai rencontré le même problème et roulé mon propre.
L'aide de ce code, vous pouvez transformer la carte autour d'une nouvelle cible (c'est à dire de ne pas le centre). J'ai opté pour l'utilisation d'un point d'ancrage du système, d'où (0.5, 0.5) est la valeur par défaut et représente le milieu de l'écran. (0,0) est en haut à gauche et (1, 1) est en bas à gauche.
Fondamentalement, vous utilisez la projection d'obtenir le monde XY co-ord, alors compenser ce point et tourner à nouveau dans une LatLng. Vous pouvez ensuite passer à votre carte. PointD est de type simple qui contient x,y, doubles, et fait aussi de la rotation.
Remarque, si vous êtes à la mise à jour de la carte de roulement et l'emplacement dans le même temps, il est important que vous utilisez le nouveau roulement dans getOffsetLocation.
Le moyen le plus facile serait de la chaîne d'animations de caméra. Tout d'abord vous zoom normalement à votre image #2 à l'aide de animateCamera avec 3 paramètres et dans
CancellableCallback.onFinish
- vous de faire vos calculs de projection et d'animer à l'aide de votre code de changer de centre.Je crois (n'a pas à le tester) ce sera très bien si vous définissez quelques bonnes valeurs pour l'animation de la durée pour les deux animations. Peut-être deuxième animation devrait être beaucoup plus rapide que la première. Aussi, si votre transparent, surmonté de Vue n'est pas visible lorsque aucun marqueur est sélectionné, une belle UX serait pour animer il en de gauche au cours de la deuxième animation.
À la dure serait de mettre en place votre propre Spherical Mercator Projection comme l'un des Maps API v2 utilise en interne. Si vous avez seulement besoin de longitude décalage qui ne devrait pas être difficile. Si vos utilisateurs peuvent changer le roulement et vous ne voulez pas de le remettre à 0 lors d'un zoom, vous avez besoin de latitude décalage trop et ce sera probablement un peu plus complexe à mettre en œuvre.
Je pense aussi qu'il serait bon d'avoir des Maps API v2 fonctionnalités où vous pouvez obtenir de projection pour tout CameraPosition et pas seulement de courant de sorte que vous pouvez soumettre une demande de fonctionnalité ici: http://code.google.com/p/gmaps-api-issues/issues/list?can=2&q=apitype=Android2. Vous pourrez facilement l'utiliser dans votre code pour l'effet que vous voulez.
Pour la fixation d'un marqueur, nous utilisons des Superpositions dans Android, En superposition de classe==> sur la méthode de tirage
la place de cette chose
boundCenter(marqueur);
et dans le constructeur a également mentionner comme ceci:
J'ai presque exactement le même problème que vous (seulement mon décalage est à la verticale), et j'ai essayé une solution qui n'a pas fonctionné comme prévu, mais pourrait aider à vous (nous) de trouver une meilleure solution.
Ce que j'ai fait était de déplacer la caméra de la carte pour obtenir la projection sur la cible, et d'appliquer le décalage là.
J'ai placé le code dans une classe Utils et il ressemble à ceci:
Alors vous pouvez utiliser les CameraBuilder renvoyées par ces méthodes, pour l'animation, au lieu de l'original (pas offseted) de la cible.
Il fonctionne (plus ou moins), mais il a deux gros problèmes:
Donc je n'ai pas aller pour cela, mais ça m'a fait penser à une alternative: Si vous aviez un nombre identique de la carte, mais caché, vous pouvez utiliser cette carte pour les calculs, puis utiliser le résultat final sur le visible de la carte.
Je pense que cette solution serait de travailler, mais c'est horrible, car vous aurez besoin de mantain deux cartes identiques, avec le traitement qui va avec, pour vous et pour l'appareil.
Comme je l'ai dit, je n'ai pas de solution définitive, mais peut-être que cela aide un peu.
J'espère que cela aide!
J'ai résolu le problème en calculant une distance de vecteur à l'aide de la LatLng valeurs de deux points fixes sur la carte, puis la création d'un autre LatLng en utilisant le Marqueur de position, ce vecteur et un pré-définis valeur du ratio. Il y a beaucoup d'objets impliqués dans celui-ci, toutefois, il ne dépend pas du niveau de zoom et la rotation de la carte, et peut travailler comme une grande pour vous!
J'avais affaire à la même tâche et s'est terminée avec la même solution que votre dernière option :
Mais au lieu de point de division de l'offset sur
2<<zoomDifference
je suis de calcul de la compensation de différences entre la longitude et la latitude des valeurs. Ils sontdouble
s, donc il me donne une assez bonne précision. Donc, essayez de convertir vos crédits à la lat/lng pas votre emplacement de pixels et l'viens de faire le même calcul.Édité
Enfin j'ai réussi à le résoudre d'une autre manière (plus approprié, comme je le crois). Map API v2 a rembourrage paramètres. Juste de la configuration à faire de la caméra à prendre toutes pas partie cachée de
MapView
. L'appareil serait reflètent le centre du collier de la région aprèsanimateCamera()