圖塊疊加層

圖塊疊加層 (有時也稱為圖塊圖層) 是顯示在基本地圖圖塊上的一組圖像。

程式碼範例

GitHub 上的 ApiDemos 存放區有圖塊疊加層地圖項目的說明範例:

簡介

TileOverlay 定義疊加在基本地圖圖塊上的一組圖像。

您必須針對要支援的每個縮放等級提供圖塊。如果能在多個縮放等級提供足夠的圖塊,就可以讓整份地圖的 Google 地圖資料更完整。

當您想在地圖上加入大量圖像時 (通常涵蓋大範圍地理區域),圖塊疊加層就非常實用。相反地,如果您想修正地圖上某個區域的單張圖片,就比較適合使用區域疊加層

您也可以使用透明圖塊疊加層,在地圖中加入額外的地圖項目;方法是以程式輔助方式在圖塊疊加層上設定透明度係數,或提供透明的圖塊圖片。

圖塊座標和縮放等級

Google Maps API 會將各縮放等級的圖像分為一組正方形地圖圖塊,並排列成格狀。地圖移動到新位置或調至新的縮放等級時,Maps API 會判斷需要哪些圖塊,然後將該資訊轉譯成要擷取的一組圖塊。

座標為 (0,0) 的圖塊一律位於地圖的西北角,同時 x 值會由西到東遞增,y 值則由北到南遞增。系統會使用從該原點開始的 (x,y) 座標來建立圖塊索引。

縮放等級為 0 時,全世界會算繪為單一圖塊。每個縮放等級會將地圖放大兩倍,因此,縮放等級為 1 時,地圖會算繪為 2x2 的圖塊方格。縮放等級為 2 時,是 4x4 方格;縮放等級為 3 時,則會是 8x8 方格,以此類推。

舉例來說,縮放等級為 2 時,地球會分成 16 個圖塊,每個圖塊都可參照由 x、y 座標及縮放等級構成的專屬組合:

建立圖塊圖層的圖片時,您必須針對每個要支援的縮放等級,分別為每個圖塊建立圖片。Google 地圖在顯示圖塊時是以 256 DP (裝置獨立像素) 為目標。針對高解析度裝置,建議您傳回高 DPI 圖塊 (512x512 像素)。請參閱 Android 開發人員說明文件,瞭解如何支援不同的螢幕大小和像素密度。

注意:相機支援的縮放等級取決於多項因素,與圖塊支援的縮放等級無關。

  1. GoogleMap.getMaxZoomLevel() 會傳回目前相機位置可用的最高縮放等級。這項資訊會考量目前正在使用的地圖類型,舉例來說,衛星地圖或地形圖的最高縮放等級可能低於基本地圖圖塊。
  2. GoogleMap.getMinZoomLevel() 會針對每個地點傳回相同的最低縮放等級 (這點不同於最高縮放等級),但可能因裝置和地圖大小而有差異。

新增圖塊疊加層

建立圖塊疊加層最簡單及最常見的方法,就是提供指向相關圖塊圖片的網址。UrlTileProviderTileProvider 的其中一部分,會跟據網址提供圖片圖塊。此類別要求所有圖片的尺寸都必須相同。

您必須導入 UrlTileProvider.getTileUrl(),其可接受圖塊座標 (x, y, 縮放) 並傳回網址 (指向圖塊要使用的圖片)。如果指定的 x、y 和縮放沒有對應的圖塊,此方法應傳回空值。網址可指向網路資源、Android 素材資源或本機磁碟上的檔案。

針對所有要支援的 x、y 座標和縮放等級,在已定義的伺服器上設定圖塊圖片的圖庫,然後新增圖塊疊加層:

  1. 定義 UrlTileProvider 以提供圖塊圖片。
  2. 覆寫 getTileUrl() 以建構每個圖塊圖片的網址。
  3. 提供含相關選項的 TileOverlayOptions 物件:
    • fadeIn:布林值,用於指定圖塊是否應淡入,預設值為 true。在不同的圖塊疊加層之間快速切換時,您可以考慮關閉淡入效果。若想瞭解透明度和淡出效果之間的關係,請參閱下方「透明度」一節。
    • tileProvider:此疊加層要使用的 TileProvider
    • transparency:浮點值,用於設定圖塊圖片的透明度係數。這個值必須在 [0.0f, 1.0f] 範圍內,其中 0.0f 表示完全不透明 (預設),而 1.0f 表示完全透明。如需程式碼範例或想瞭解透明度和淡入效果之間的關係,請參閱下方「透明度」一節。
    • visible:布林值,用於指定圖塊疊加層的顯示設定。隱形的圖塊疊加層 (值 false) 不會繪製在地圖上,但會保留所有其他屬性。預設值為 true
    • zIndex:決定圖塊疊加層與其他疊加層之間的繪製順序,包括區域疊加層圓形、折線和多邊形。系統會將 Z-index 順序較高的疊加層繪製在順序較低的疊加層之上。如果疊加層的 Z-index 值相同,則由系統任意決定。預設的 Z-index 值為 0。請注意,無論其他疊加層的 Z-index 值為何,標記一律繪製在其他疊加層之上。
  4. 呼叫 GoogleMap.addTileOverlay() 將疊加層加入地圖。

Java

private GoogleMap map;

TileProvider tileProvider = new UrlTileProvider(256, 256) {

    @Override
    public URL getTileUrl(int x, int y, int zoom) {

        /* Define the URL pattern for the tile images */
        String s = String.format("http://my.image.server/images/%d/%d/%d.png", zoom, x, y);

        if (!checkTileExists(x, y, zoom)) {
            return null;
        }

        try {
            return new URL(s);
        } catch (MalformedURLException e) {
            throw new AssertionError(e);
        }
    }

    /*
     * Check that the tile server supports the requested x, y and zoom.
     * Complete this stub according to the tile range you support.
     * If you support a limited range of tiles at different zoom levels, then you
     * need to define the supported x, y range at each zoom level.
     */
    private boolean checkTileExists(int x, int y, int zoom) {
        int minZoom = 12;
        int maxZoom = 16;

        return (zoom >= minZoom && zoom <= maxZoom);
    }
};

TileOverlay tileOverlay = map.addTileOverlay(new TileOverlayOptions()
    .tileProvider(tileProvider));
      

Kotlin

private lateinit var map: GoogleMap

var tileProvider: TileProvider = object : UrlTileProvider(256, 256) {
    override fun getTileUrl(x: Int, y: Int, zoom: Int): URL? {

        /* Define the URL pattern for the tile images */
        val url = "http://my.image.server/images/$zoom/$x/$y.png"
        return if (!checkTileExists(x, y, zoom)) {
            null
        } else try {
            URL(url)
        } catch (e: MalformedURLException) {
            throw AssertionError(e)
        }
    }

    /*
     * Check that the tile server supports the requested x, y and zoom.
     * Complete this stub according to the tile range you support.
     * If you support a limited range of tiles at different zoom levels, then you
     * need to define the supported x, y range at each zoom level.
     */
    private fun checkTileExists(x: Int, y: Int, zoom: Int): Boolean {
        val minZoom = 12
        val maxZoom = 16
        return zoom in minZoom..maxZoom
    }
}

val tileOverlay = map.addTileOverlay(
    TileOverlayOptions()
        .tileProvider(tileProvider)
)
      

如要查看 UrlTileProvider 的應用實例,請參閱 Google Play 服務 SDK 隨附程式碼範例中的 TileOverlayDemoActivity

設定圖塊疊加層的透明度

在地圖上疊加透明圖塊是很不錯的做法,這樣能讓使用者看到疊加圖塊下方的基本地圖。您可以自行提供透明圖塊,或以程式輔助方式在圖塊疊加層上設定透明度係數。

下列程式碼範例會在 0.5f0.0f 之間切換圖塊疊加層的透明度:

Java

private TileOverlay tileOverlayTransparent;

@Override
public void onMapReady(GoogleMap map) {
    tileOverlayTransparent = map.addTileOverlay(new TileOverlayOptions()
        .tileProvider(new UrlTileProvider(256, 256) {
            // ...
        })
        .transparency(0.5f));
}

// Switch between 0.0f and 0.5f transparency.
public void toggleTileOverlayTransparency() {
    if (tileOverlayTransparent != null) {
        tileOverlayTransparent.setTransparency(0.5f - tileOverlayTransparent.getTransparency());
    }
}
      

Kotlin

private var tileOverlayTransparent: TileOverlay? = null

override fun onMapReady(map: GoogleMap) {
    tileOverlayTransparent = map.addTileOverlay(
        TileOverlayOptions()
            .tileProvider(object : UrlTileProvider(256, 256) {
                // ...
            })
            .transparency(0.5f)
    )
}

// Switch between 0.0f and 0.5f transparency.
fun toggleTileOverlayTransparency() {
    tileOverlayTransparent?.let {
        it.transparency = 0.5f - it.transparency
    }
}
      

圖塊圖片的透明度會以 Alpha 色版調節係數的形式實作。如要設定圖塊疊加層的透明度,請提供 transparency[0.0f, 1.0f] 範圍內的 TileOverlayOptions 物件,如上方範例所示。0.0f 值表示圖塊疊加層是完全不透明,而 1.0f 表示完全透明。預設值為 0.0f (不透明)。

呼叫 TileOverlay.getTransparency() 可存取圖塊疊加層的透明度,呼叫 TileOverlay.setTransparency() 則可加以變更。

透明度、動畫和淡入效果

透明度變更時不會有動畫效果。透明度選項會和 fdeIn 選項一起運作。

淡入選項會在圖塊載入時呈現透明度動畫。如果您設定了透明度的值,圖塊會從完全透明淡入到定義的透明度。如果您在淡入效果期間變更透明度,動畫會以新的透明度為目標繼續進行。

移除圖塊疊加層

使用 TileOverlay.remove() 方法可以移除圖塊疊加層。

Java

tileOverlay.remove();
      

Kotlin

tileOverlay.remove()
      

清除過時的圖塊

如果圖塊疊加層提供的圖塊變成「過時」,您可以呼叫 clearTileCache() 強制重新整理。這會使系統重新載入此疊加層的所有圖塊。舉例來說,如果 TileProvider 提供的圖塊變更了,您之後就必須呼叫 clearTileCache(),確保系統不會繼續算繪之前的圖塊。

Java

tileOverlay.clearTileCache();
      

Kotlin

tileOverlay.clearTileCache()