
In einem
früheren Artikel habe ich darüber gesprochen, wie man eine mobile Anwendung mit einer Karte erstellt. In der Fortsetzung der Reihe "Am Knie" teile ich Ihnen die Werkzeuge zur Umsetzung von Grundrissen mit.
Die erste Erklärung des Problems in vereinfachter Form: Ich möchte das Grundrissdiagramm in Ihrer mobilen Anwendung visualisieren und den Standort einer bestimmten Organisation darauf anzeigen können. Ich möchte auch den Standort des Benutzers sehen, aber hier liegt das Problem in der technischen Ebene - Sie benötigen Geräte, mit denen Sie die Koordinaten des Geräts in Innenräumen abrufen können. Deshalb lassen wir diesen Aspekt außerhalb des Geltungsbereichs des Artikels und konzentrieren uns auf den Softwareteil.
Im Folgenden zeige ich Ihnen einige Möglichkeiten, mit denen Sie die oben beschriebenen Anforderungen umsetzen können. Es hängt alles davon ab, über welche Daten Sie verfügen und was genau die Anwendung tun kann. Und wir werden mit dem Einfachsten beginnen.
Die erste Möglichkeit. Fertige API mit Daten
Die erste Option, die wir in Betracht ziehen werden, ist die Verwendung eines vorgefertigten Widgets von 2GIS. Die API-Beschreibung kann auf
api.2gis.ru eingesehen
werden. Es wird Ihnen passen, wenn das Gebäude, an dem Sie interessiert sind, bereits in 2GIS präsentiert wird und die Fußböden bereits im Gebäude gezeichnet wurden. Das heißt, in Bezug auf die Daten wurde bereits alles getan. Und am wichtigsten ist, dass Sie online bereit sind, da diese Option ausschließlich mit dem Internet funktioniert.
In diesem Fall ist praktisch nichts von Ihnen erforderlich, um die Fußböden anzuzeigen. Implementierung der Ausführung als Web-Widget, das Sie nur in den WebView einfügen müssen.
<WebView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/am_webview" android:layout_marginTop="160dp" />
In diesem Container platzieren wir unser Widget. Wir initialisieren es wie folgt:
webView = findViewById(R.id.am_webview) webView.settings.javaScriptEnabled = true webView.settings.useWideViewPort = true webView.settings.loadWithOverviewMode = true
Wir konfigurieren das WebView selbst. Stellen Sie sicher, dass JavaScript aktiviert ist (javaScriptEnabled = true), da wir über dieses Widget mit dem Widget interagieren. Bei Bedarf können Sie die Bildlaufleisten und Zoom-Schaltflächen aktivieren (siehe den kommentierten Code), aber es funktioniert nicht sehr gut, weshalb ich es nicht empfehle.
Das Wichtigste ist, HTML mit unserem Widget
webView.loadUrl ("file: ///android_asset/map_api.html") zu laden und bei Bedarf Ereignisse zu abonnieren. Im obigen Beispiel rufen wir nach dem Laden der Karte die in
map_api.html definierte
initMap- Methode auf und übergeben den Bezeichner des Gebäudes, für das wir die Stockwerke anzeigen möchten.
HTML ist ziemlich einfacher Code. Es
wird die Methode
DG.FloorsWidget.init aufgerufen , in die das json-Objekt übergeben wird, das die zu initialisierenden Daten enthält. Geben Sie als Container die ID an, mit der wir oben im HTML-Markup ein div deklariert haben. Passen Sie die Breite und Höhe an. Und in
initData übergeben wir das Gebäude im
complexId- Tag sowie weitere Widget-Anzeigeparameter, die in der API-Dokumentation zu finden sind. Die Kennung kann übrigens als Antwort auf die Suchabfrage angezeigt werden, die 2GIS sendet, wenn Sie auf das Gebäude klicken, das Sie an
2gis.ru interessiert. In meinem Beispiel habe ich die Dubai Mall benutzt. Aber niemand macht sich die Mühe, auf ein anderes Gebäude mit Fußböden hinzuweisen.
Der letzte Schliff. Um zu einer bestimmten Firma zu wechseln, rufen Sie die Methode showFirm auf und übergeben Sie die Firmen-ID
webView.loadUrl("javascript:showFirm('$firmId')")
Es ist ziemlich einfach. Ein fertiges Implementierungsbeispiel kann auf
Github eingesehen werden.

Vorteile der in Betracht gezogenen Option:
- vorgefertigte Daten mit Grundrissen und Firmendaten;
- vorgefertigte, leichte Implementierung in Webview;
- bereite Suche nach 2GIS.
Nachteile:
- Internet erforderlich;
- Grundkenntnisse in HTML und JavaScript sind erforderlich;
- nur 2GIS-Daten und nur die Gebäude, die bereits Stockwerke haben.
Die zweite Möglichkeit. Grundriss als Bild
Wenn die Option mit fertigen Daten und API nicht für Sie geeignet ist, können Sie Folgendes verwenden.
In diesem Fall benötigen Sie einen Grundriss in Form eines Bildes, beispielsweise JPEG oder PNG. Wenn Interaktivität vom Typ "Ins Bild gestochen - Objektkarte geöffnet" erforderlich ist, ist auch eine Geokodierung erforderlich, die unabhängig implementiert werden muss. Wenn Sie an globalen Koordinaten ausrichten, sollte das Bild korrekt skaliert und eine der Ecken an die realen Koordinaten gezogen werden, damit Sie die Verschiebungen daraus berechnen können. Wir werden auf dieses Thema nicht näher eingehen, ich hoffe, dass hier alles klar ist.
Das Wichtigste ist, dieses Bild in der Anwendung zu zeigen. Und dafür ist die
TileView- Bibliothek ideal für uns. Tatsächlich können mit dieser Bibliothek im Prinzip Kartenkacheln angezeigt werden. Es passt aber auch zu uns, da es die Möglichkeit bietet, sich zu bewegen und zu zoomen, an einer bestimmten Position zu zentrieren, Markierungen anzuzeigen, Koordinaten zu transformieren und verschiedene Ereignisse zu abonnieren.
Damit die Bibliothek so effizient wie möglich arbeitet, muss das Originalbild vorbereitet werden, indem es in Kacheln geschnitten wird. Hierfür gibt es eine ziemlich einfache
Anweisung . Ich empfehle ein Skript am Ende der angegebenen Seite, das 4 Kachelsätze erstellt. Wir fügen das erhaltene Ergebnis zu Assets hinzu und zeigen unser Bild in der Aktivität mit einem einfachen Code an:
tileView.setSize(floorWidth, floorHeight) tileView.setShouldRenderWhilePanning(true) tileView.addDetailLevel(1f, "tiles/floors1/1000/%d_%d.jpg") tileView.addDetailLevel(0.500f, "tiles/floors1/500/%d_%d.jpg") tileView.addDetailLevel(0.250f, "tiles/floors1/250/%d_%d.jpg") tileView.addDetailLevel(0.125f, "tiles/floors1/125/%d_%d.jpg") tileView.defineBounds(0.0, 0.0, floorWidth.toDouble(), floorHeight.toDouble()) tileView.setScaleLimits(0f, 5f) tileView.setMinimumScaleMode(ZoomPanLayout.MinimumScaleMode.FIT)
Alles, das Display ist fertig. Sie können Ereignisse abonnieren und die erforderliche Logik hinzufügen. Ein Marker kann beispielsweise folgendermaßen angezeigt werden:
tileView.setMarkerAnchorPoints(-0.5f, -0.5f) tileView.addMarker(imageView, x, floorHeight - y, null, null)
Ein vollständiges Beispiel finden Sie bei
Github .

Vorteile:
- die Fähigkeit, vollständig offline zu tun;
- relativ einfache Datenaufbereitung, Grundriss in Bildform.
Nachteile:
- Mangel an dynamischem Styling.
Die dritte Option. Vektordaten
Diese Option ist am weitesten fortgeschritten und am schwierigsten. Es wird davon ausgegangen, dass Sie Vektordaten vorbereitet haben, dh Stockwerke, die vollständig im Vektor gezeichnet sind. Sie benötigen mehrere Arten von Objekten. Bereiche von Organisationen, Parkplätze, Food Courts, Bühnen, Eisbahnen und so weiter. Lineare Objekte - hauptsächlich Wände, Strömungsrichtungen. Punktobjekte: Ein- / Ausgänge, Aufzüge, Geldautomaten und dergleichen.
So sieht ein Grundriss in Fidschi, dem internen 2GIS-System, aus:

Nun, für ihre Visualisierung ist die Vektor-Engine, über die ich im
vorherigen Artikel gesprochen habe , mapsforge-vtm, für uns geeignet.
Um den Ansatz zu demonstrieren, habe ich Testdaten erstellt: eine Reihe von Quadraten und Linien für mehrere Stockwerke am Beispiel eines Gebäudes auf der Sonneninsel Zypern. Zur Vorbereitung nahm ich die ursprüngliche Geometrie des Gebäudes und schnitt sie der Einfachheit halber in Stücke, die den Bestandteilen der Geometrie entsprachen. Wie Sie wissen, ist der schwierigste Teil die Aufbereitung von Qualitätsdaten. Der Rest ist eine Frage der Technologie. Sie benötigen Schaltflächen zum Wechseln der Etagen, vorbereitete Stile zum Rendern verschiedener Quadrate und Linien sowie eine Überlagerung zum Rendern.
Den vollständigen Code finden Sie
hier .
Die
FloorData- Klasse enthält den Test-Geodatencode für unsere Böden, und die
FloorsManager- Klasse
dient zum Rendern dieser Böden.
Im Konstruktor definieren wir Stile für Quadrate und Wände:
styles.put(ObjectType.Floor, org.oscim.layers.vector.geometries.Style.builder() .fillColor(Color.GRAY) .build());
Und in der
drawFloor- Methode legen
wir die Logik fest, mit der Objekte zu Layern auf der Karte hinzugefügt werden:
public void drawFloor(int floorId) { hideFloors(); indoorLayer = new CustomVectorLayer(this.map); List<GeoData> geoObjects = this.floorData.getFloorData(floorId); for (GeoData geo: geoObjects) { indoorLayer.add(geo.getGeometry(), styles.get(geo.getObjectType())); } this.map.layers().add(indoorLayer); indoorLayer.update(); }
Hier ist alles elementar. Erstellen Sie eine neue Ebene
indoorLayer , fügen Sie vorbereitete
Bodendaten mit den erforderlichen Stilen hinzu und fügen Sie die Ebene der Karte hinzu
this.map.layers (). Add (indoorLayer) .
Es müssen noch Knöpfe hinzugefügt werden, um die Etagen zu wechseln. Dazu gibt es ein
FloorPickerControl auf Basis der
RecyclerView , das genau das tut, was Sie brauchen. Verschwenden wir keine Zeit damit, siehe Quelle.
Und hier ist die Dubai Mall in unserer Anwendung. Es wurde auch die Bearbeitung von Geo-Objekten implementiert.

Vorteile:
- wieder die Fähigkeit, vollständig offline zu tun;
- qualitativ hochwertiges Bild;
- die Möglichkeit einer Vielzahl von dynamischen Stilisierungen;
- die Fähigkeit, einen Dateneditor zu implementieren.
Nachteile:
- komplexe Datenaufbereitung.
Am Ende des Artikels möchte ich sagen, dass die Aufgabe, Grundrisse in der Anwendung anzuzeigen, nicht so schrecklich ist, wie es auf den ersten Blick scheinen mag. Sie haben mehrere Möglichkeiten mit Ihren Vor- und Nachteilen, aus denen Sie die für die Lösung Ihres Problems am besten geeignete auswählen können.
Alle Referenzen an einem Ort:
Artikel über die Karte im HandyAPI 2GIS2GIS API-BeispielTileView-BibliothekTileView-BeispielEin Beispiel für mapsforge-vtm