Tak, możesz używać niestandardowych kafelków z Android Maps API v2 - możesz zobaczyć w pełni działający przykład w naszej aplikacji OpenTripPlanner dla Androida na Github . (Możesz także pobrać aplikację bezpośrednio z Google Play )
Obsługujemy następujących dostawców kafelków:
- LyrkOpenStreetMap
- MapQuestOpenStreetMap
- Mapnik
- CycleMap
- Google (normalny, satelitarny, hybrydowy, teren)
Naszą klasę CustomUrlTileProvider można zobaczyć tutaj na Github , a także wkleiłem ją poniżej:
public class CustomUrlTileProvider extends UrlTileProvider {
private String baseUrl;
public CustomUrlTileProvider(int width, int height, String url) {
super(width, height);
this.baseUrl = url;
}
@Override
public URL getTileUrl(int x, int y, int zoom) {
try {
return new URL(baseUrl.replace("{z}", "" + zoom).replace("{x}", "" + x)
.replace("{y}", "" + y));
} catch (MalformedURLException e) {
e.printStackTrace();
}
return null;
}
}
A oto kod, który przełącza się między dostawcami kafelków mapy, w zależności od preferencji użytkownika:
/**
* Changes the tiles used to display the map and sets max zoom level.
*
* @param overlayString tiles URL for custom tiles or description for
* Google ones
*/
public void updateOverlay(String overlayString) {
int tile_width = OTPApp.CUSTOM_MAP_TILE_SMALL_WIDTH;
int tile_height = OTPApp.CUSTOM_MAP_TILE_SMALL_HEIGHT;
if (overlayString == null) {
overlayString = mPrefs.getString(OTPApp.PREFERENCE_KEY_MAP_TILE_SOURCE,
mApplicationContext.getResources()
.getString(R.string.map_tiles_default_server));
}
if (mSelectedTileOverlay != null) {
mSelectedTileOverlay.remove();
}
if (overlayString.startsWith(OTPApp.MAP_TILE_GOOGLE)) {
int mapType = GoogleMap.MAP_TYPE_NORMAL;
if (overlayString.equals(OTPApp.MAP_TILE_GOOGLE_HYBRID)) {
mapType = GoogleMap.MAP_TYPE_HYBRID;
} else if (overlayString.equals(OTPApp.MAP_TILE_GOOGLE_NORMAL)) {
mapType = GoogleMap.MAP_TYPE_NORMAL;
} else if (overlayString.equals(OTPApp.MAP_TILE_GOOGLE_TERRAIN)) {
mapType = GoogleMap.MAP_TYPE_TERRAIN;
} else if (overlayString.equals(OTPApp.MAP_TILE_GOOGLE_SATELLITE)) {
mapType = GoogleMap.MAP_TYPE_SATELLITE;
}
mMap.setMapType(mapType);
mMaxZoomLevel = mMap.getMaxZoomLevel();
} else {
if (overlayString.equals(getResources().getString(R.string.tiles_mapnik))) {
mMaxZoomLevel = getResources().getInteger(R.integer.tiles_mapnik_max_zoom);
} else if (overlayString.equals(getResources().getString(R.string.tiles_lyrk))) {
mMaxZoomLevel = getResources().getInteger(R.integer.tiles_lyrk_max_zoom);
tile_width = OTPApp.CUSTOM_MAP_TILE_BIG_WIDTH;
tile_height = OTPApp.CUSTOM_MAP_TILE_BIG_HEIGHT;
} else {
mMaxZoomLevel = getResources().getInteger(R.integer.tiles_maquest_max_zoom);
}
mMap.setMapType(GoogleMap.MAP_TYPE_NONE);
CustomUrlTileProvider mTileProvider = new CustomUrlTileProvider(
tile_width,
tile_height, overlayString);
mSelectedTileOverlay = mMap.addTileOverlay(
new TileOverlayOptions().tileProvider(mTileProvider)
.zIndex(OTPApp.CUSTOM_MAP_TILE_Z_INDEX));
if (mMap.getCameraPosition().zoom > mMaxZoomLevel) {
mMap.moveCamera(CameraUpdateFactory.zoomTo(mMaxZoomLevel));
}
}
}
Oto zrzut ekranu kafelków MapQuest OpenStreetMap:
Aby uzyskać więcej informacji na temat tworzenia własnych kafelków, zobacz dokumentację Google dla TileOverlay, a także wiki OpenStreetMap dla „Tworzenie własnych kafelków” .
W szczególności dokumentacja Google mówi:
Zwróć uwagę, że świat jest rzutowany za pomocą projekcji Mercator (patrz Wikipedia) z lewą (zachodnią) stroną mapy odpowiadającą -180 stopniom długości geograficznej i prawą (wschodnią) stroną mapy odpowiadającą 180 stopniom długości geograficznej. Aby mapa była kwadratowa, górna (północna) strona mapy odpowiada 85,0511 stopni szerokości geograficznej, a dolna (południowa) strona mapy odpowiada -85.0511 stopni szerokości geograficznej. Obszary poza tym zakresem szerokości geograficznej nie są renderowane.
Na każdym poziomie powiększenia mapa jest podzielona na kafelki, a tylko kafelki pokrywające ekran są pobierane i renderowane. Każdy kafelek jest kwadratowy, a mapa jest podzielona na kafelki w następujący sposób:
Na poziomie powiększenia 0 jeden kafelek reprezentuje cały świat. Współrzędne tego kafelka to (x, y) = (0, 0).
Na poziomie powiększenia 1 świat jest podzielony na 4 płytki ułożone w siatkę 2 x 2. ...
- Na poziomie powiększenia N świat jest podzielony na 4N kafelki ułożone w siatkę 2N x 2N.
Pamiętaj, że minimalny poziom powiększenia obsługiwany przez aparat (który może zależeć od różnych czynników) to GoogleMap.getMinZoomLevel, a maksymalny poziom powiększenia to GoogleMap.getMaxZoomLevel.
Współrzędne płytek są mierzone od lewego górnego (północno-zachodniego) rogu mapy. Na poziomie powiększenia N wartości x współrzędnych płytki wynoszą od 0 do 2N - 1 i zwiększają się z zachodu na wschód, a wartości y mieszczą się w zakresie od 0 do 2N - 1 i zwiększają się z północy na południe.
Sformatowane adresy URL używane w systemie OTP Android w odniesieniu do każdego dostawcy kafelków wyglądają następująco:
Tak więc dla powyższych dostawców obrazy kafelkowe są plikami PNG ułożonymi w strukturze katalogów wskazanej w dokumentacji Google. Postępowałbyś w podobnym formacie, aby stworzyć własne kafelki mapy hostowane na twoim serwerze. Pamiętaj, że te adresy URL / obrazy muszą być publicznie dostępne dla urządzenia mobilnego (tzn. Nie mogą być chronione hasłem).
Najbardziej rozbudowane rozwiązanie, jakie znalazłem, znajduje się w tej odpowiedzi StackOverflow :
Zasadniczo musisz wdrożyć własnego TileProvider i używać go jako TileOverlay
W kilku aplikacjach użyliśmy tego rodzaju warstwy do wyświetlenia kafelków na mapie, ale okazało się, że kafelki zajmowały dużo miejsca. Dlatego przeszliśmy na używanie mbtiles i tej biblioteki do wyświetlania danych z mbtiles na mapie.
źródło