Android: Erzielen einer gedrehten OSM-Karte zum Ausfüllen des gesamten Bildschirms

8

Ich arbeite an einer Anwendung, die die OpenStreetMap (OSM) API verwendet, um verschiedene Punkte von Interesse auf einer Offline-Karte anzuzeigen, die aus statischen Kacheln besteht.

Eine der Funktionen, die ich derzeit implementiere, ist, dass sich die Karte entsprechend der vom Telefon festgelegten Peilung (via GPS) dreht. Ich konnte die eigentliche Rotation ohne viel Aufwand implementieren, aber da mein Code die gesamte Leinwand dreht - vielleicht eine ziemlich naive Vorgehensweise - habe ich jetzt leere Ecken auf dem Bildschirm, auf denen keine neuen Kacheln geladen werden, um das auszugleichen dass die gedrehten Kacheln diese Pixel nicht mehr füllen.

Nach ein bisschen Googeln fand ich ein paar Vorschläge, wie ich dieses Problem lösen könnte, aber bisher kein Glück.

In einem Mr. Romain Guy's Beiträge erwähnt er folgendes:

  

Ich habe das in der Vergangenheit gemacht und es erfordert, um einen Brauch zu erstellen   ViewGroup, die Canvas in der Methode dispatchDraw () rotiert. Sie   muss auch die Größe des MapView erhöhen (damit es genug zeichnet)   Pixel gedreht.) Sie müssen auch die Touch-Ereignisse drehen   VersandTouchEvent (). Oder wenn Sie Android 3.0 verwenden, können Sie einfach anrufen   theMapView.rotate ()

Ich habe seinen Rat bezüglich der Kartenrotation genommen und habe dispatchDraw () und dispatchTouchEvent () wie vorgeschlagen implementiert, aber ich habe Probleme mit dem Teil, wo er erwähnt, dass ich die MapView vergrößern muss?

Ist das etwas, was ich in der XML-Datei mache, wie in Dieser Thread ?

Oder kann ich die Funktion onMeasure () in meiner Klasse "RelativeLayout", die meine Kartenrotation behandelt, irgendwie außer Kraft setzen?

Anregungen und Hinweise sind sehr willkommen.

UPDATE:

Um eine akzeptable Lösung für dieses Problem zu finden, habe ich versucht, die Größe des Canvas zu ändern. Der Gedanke war, dass ich mit einer Leinwandgröße, die größer als die tatsächliche Bildschirmgröße ist, in der Lage sein könnte, die leeren Ecken vollständig vom Bildschirm zu entfernen. Leider scheint es keine tatsächliche canvas.size () -Option zu geben; Das Beste, was ich gefunden habe, war canvas.scale ().

Mit canvas.scale () konnte ich den Maßstab der Leinwand sowohl in horizontaler als auch in vertikaler Richtung um den Faktor 2 vergrößern. Dies bedeutet jedoch, dass das Bild effektiv vergrößert wird, was zu einer nicht akzeptablen Verpixelung der Kartenkacheln führt.

Weiß jemand, wo die Größe des Canvas deklariert wird, und wenn das Ändern der Größe des Canvas tatsächlich mein Problem lösen könnte?

    
Tim Severeijns 29.08.2011, 23:46
quelle

1 Antwort

3

Ich folgte schließlich dem Rat von Romain Guy (derselbe Rat, den ich in meiner Frage geschrieben habe). Das heißt, ich habe meine eigene benutzerdefinierte ViewGroup erstellt, indem ich die RelativeLayout erweitert habe, und dann habe ich die Größe meiner mapView erhöht, um den gesamten Bildschirm abzudecken. Das RelativeLayout ViewGroup zu erweitern war notwendig, damit ich die Funktionen dispatchDraw(...) , onMeasure(...) sowie dispatchTouchEvent(...) überschreiben konnte, um die gewünschten Funktionen zur Kartenrotation für meine Anwendung zu aktivieren.

Die Funktion dispatchDraw(...) fängt im Wesentlichen Aufrufe der Funktion onDraw(...) ab, führt einige spezifische Manipulationen an der Eingabe für diese Funktion durch und gibt sie dann zur Verarbeitung frei. In unserem Fall sollten wir den mapView -Bildschirm drehen, bevor er zur eigentlichen onDraw(...) -Funktion gelangt. Deshalb müssen wir diese Funktion außer Kraft setzen.

Insbesondere verwendet die Funktion dispatchDraw(...) als Eingabe ein Zeichenflächenobjekt, das (in diesem Fall) das OSM-Objekt mapView darstellt (wie in der folgenden XML-Datei definiert). Wenn eine Drehung auf die Leinwand angewendet werden soll, werden wir den Mittelpunkt der Karte suchen, die Karte so verschieben (dh verschieben), dass der Mittelpunkt der Karte auf dem Ursprung des Koordinatensystems liegt, und die Karte gedreht der Ursprung des Koordinatensystems, und schließlich wollen wir diese modifizierte Zeichenfläche an die nächste Stufe in der Rendering-Pipeline schicken.

Mein Code dafür ist unten; Beachten Sie, dass Manager meine eigene Singleton-Erstellung ist, die in Ihrer Implementierung nicht existiert, es sei denn, Sie schreiben selbst eine!

%Vor%

Als nächstes müssen wir dispatchTouchEvent(...) überschreiben, weil jede Drehung des OSM mapView -Leinwands nicht nur die grafische Darstellung der Karte, sondern auch alles andere, das mit dieser Aktivität in Beziehung steht, dreht (dies geschieht als eine Seite) Auswirkung meiner spezifischen Implementierung); Das heißt, Touch-Ereigniskoordinaten bleiben nach der Drehung relativ zum mapView -Leinwand und nicht relativ zum tatsächlichen Telefon. Wenn wir uns zum Beispiel vorstellen, dass die Leinwand um 180 Grad gedreht ist, wird der Benutzer, wenn er versucht, die Karte nach links zu verschieben, stattdessen auf die Karte nach rechts verschieben, da alles auf dem Kopf steht!

Im Code könnten Sie dieses Problem folgendermaßen beheben:

%Vor%

Schließlich besteht der Trick, den entsprechenden XML-Code für die Kartenaktivität korrekt zu verwenden, darin, ein FrameLayout als übergeordnetes Element für alle anderen GUI-Elemente in meinem Layout zu verwenden. Dadurch konnte ich die mapView Dimensionen erheblich größer als die Abmessungen des Displays auf meinem Nexus One (480 x 800) machen. Diese Lösung erlaubte mir auch, ein RelativeLayout in mein FrameLayout zu verschachteln, während die tatsächlichen Anzeigedimensionen des Geräts bei Verwendung von match_parent und ähnlichen Parametern berücksichtigt wurden.

Der relevante Teil meines XML-Layouts sieht so aus:

%Vor%

Ich möchte anmerken, dass diese Lösung keineswegs die beste Lösung ist, aber dass sie für meine Proof-of-Concept-Anwendung gut funktioniert hat!

    
Tim Severeijns 26.09.2012, 21:39
quelle

Tags und Links