形狀

Google Maps API for Android 提供一些簡單的做法,方便您在地圖中加入形狀,以根據應用程式進行自訂。

  • Polyline 是連續線段,可構成您想要的任何形狀,並可用來標記地圖上的路徑和路線。
  • Polygon 是封閉形狀,可用來在地圖上標記區域。
  • Circle 是地球表面上一個精確定位並繪製於地圖上的圓形投影。

視需求修改不同的屬性,即可自訂上述形狀的外觀。

程式碼範例

在新增多邊形和折線來代表區域和路徑的教學課程中,也提供了簡易 Android 應用程式適用的所有程式碼。

此外,GitHub 上的 ApiDemos 存放區也有相關範例,說明如何使用形狀及其地圖項目:

折線

Polyline 類別可定義地圖上的一組連續線段。Polyline 物件由一組 LatLng 地點組成,可建立依序連接各個地點的一系列線段。

這部影片說明如何使用折線在地圖上繪製路徑,引導使用者前往目的地。

如要建立折線,請先建立 PolylineOptions 物件並新增路徑點。路徑點代表地球表面上的一個點,以 LatLng 物件表示。根據您在 PolylineOptions 物件中加入路徑點的順序,系統會在點與點之間繪製線段。如要在 PolylineOptions 物件中新增路徑點,請呼叫 PolylineOptions.add()。請注意,此方法可接受任意數量的參數,因此您可以一次新增多個路徑點 (如果清單中已有路徑點,您也可以呼叫 PolylineOptions.addAll(Iterable<LatLng>))。

接著,您可以呼叫 GoogleMap.addPolyline(PolylineOptions) 將折線加入地圖。這個方法會傳回 Polyline 物件,日後您便可用該物件來修改折線。

以下程式碼片段說明如何在地圖中加入矩形:

Java

// Instantiates a new Polyline object and adds points to define a rectangle
PolylineOptions polylineOptions = new PolylineOptions()
    .add(new LatLng(37.35, -122.0))
    .add(new LatLng(37.45, -122.0))  // North of the previous point, but at the same longitude
    .add(new LatLng(37.45, -122.2))  // Same latitude, and 30km to the west
    .add(new LatLng(37.35, -122.2))  // Same longitude, and 16km to the south
    .add(new LatLng(37.35, -122.0)); // Closes the polyline.

// Get back the mutable Polyline
Polyline polyline = map.addPolyline(polylineOptions);
      

Kotlin

// Instantiates a new Polyline object and adds points to define a rectangle
val polylineOptions = PolylineOptions()
    .add(LatLng(37.35, -122.0))
    .add(LatLng(37.45, -122.0)) // North of the previous point, but at the same longitude
    .add(LatLng(37.45, -122.2)) // Same latitude, and 30km to the west
    .add(LatLng(37.35, -122.2)) // Same longitude, and 16km to the south
    .add(LatLng(37.35, -122.0)) // Closes the polyline.

// Get back the mutable Polyline
val polyline = map.addPolyline(polylineOptions)
      

如果您在加入折線後想修改其形狀,可以呼叫 Polyline.setPoints() 並為折線提供新的路徑點清單。

不管是在將折線加入地圖之前或之後,您都可以自訂折線的外觀。詳情請參閱下方「自訂外觀」一節。

折線事件

根據預設,折線不可點擊。您可以呼叫 Polyline.setClickable(boolean) 來啟用及停用可點擊屬性。

使用 OnPolylineClickListener 能監聽可點擊折線的點擊事件。如要在地圖上設定這個事件監聽器,請呼叫 GoogleMap.setOnPolylineClickListener(OnPolylineClickListener)。 這樣使用者點擊折線時,您就會收到 onPolylineClick(Polyline) 回呼。

多邊形

Polygon 物件與 Polyline 物件類似,都是由一系列座標依序組成。不過,多邊形並不是開放的線段,而是用來定義內部已填滿的封閉區域。

在地圖中新增 Polygon 的做法與加入 Polyline 的方式相同。首先要建立 PolygonOptions 物件並新增一些路徑點,這些點會構成多邊形的外框。 接著,請呼叫 GoogleMap.addPolygon(PolygonOptions) 來傳回 Polygon 物件,將多邊形加入地圖。

以下程式碼片段會將矩形加入地圖中 (請注意,由於我們尚未定義填滿顏色,因此預設的填滿顏色為透明,看起來會與前一節程式碼片段中的折線相同)。

Java

// Instantiates a new Polygon object and adds points to define a rectangle
PolygonOptions polygonOptions = new PolygonOptions()
    .add(new LatLng(37.35, -122.0),
        new LatLng(37.45, -122.0),
        new LatLng(37.45, -122.2),
        new LatLng(37.35, -122.2),
        new LatLng(37.35, -122.0));

// Get back the mutable Polygon
Polygon polygon = map.addPolygon(polygonOptions);
      

Kotlin

// Instantiates a new Polygon object and adds points to define a rectangle
val rectOptions = PolygonOptions()
    .add(
        LatLng(37.35, -122.0),
        LatLng(37.45, -122.0),
        LatLng(37.45, -122.2),
        LatLng(37.35, -122.2),
        LatLng(37.35, -122.0)
    )

// Get back the mutable Polygon
val polygon = map.addPolygon(rectOptions)
      

如果您在加入多邊形後想修改其形狀,可以呼叫 Polygon.setPoints() 並為多邊形的外框提供新的路徑點清單。

不管是在將多邊形加入地圖之前或之後,您都可以自訂多邊形的外觀。詳情請參閱下方「自訂外觀」一節。

多邊形自動完成

上述範例中的多邊形是由五組座標組成,但請注意,第一組和最後一組座標是相同的位置,因此形成了一個迴圈。由於多邊形會定義封閉的區域,因此實際操作時,您不需要另外指定最後一組座標。如果最後一組座標與第一組不同,API 會在座標序列結尾處自動加上第一組座標,以便「封閉」多邊形。

以下兩個多邊形會完全相同,且呼叫 polygon.getPoints() 後都會傳回全部 4 個路徑點。

Java

Polygon polygon1 = map.addPolygon(new PolygonOptions()
    .add(new LatLng(0, 0),
        new LatLng(0, 5),
        new LatLng(3, 5),
        new LatLng(0, 0))
    .strokeColor(Color.RED)
    .fillColor(Color.BLUE));

Polygon polygon2 = map.addPolygon(new PolygonOptions()
    .add(new LatLng(0, 0),
        new LatLng(0, 5),
        new LatLng(3, 5))
    .strokeColor(Color.RED)
    .fillColor(Color.BLUE));
      

Kotlin

val polygon1 = map.addPolygon(
    PolygonOptions()
        .add(
            LatLng(0.0, 0.0),
            LatLng(0.0, 5.0),
            LatLng(3.0, 5.0),
            LatLng(0.0, 0.0)
        )
        .strokeColor(Color.RED)
        .fillColor(Color.BLUE)
)
val polygon2 = map.addPolygon(
    PolygonOptions()
        .add(
            LatLng(0.0, 0.0),
            LatLng(0.0, 5.0),
            LatLng(3.0, 5.0)
        )
        .strokeColor(Color.RED)
        .fillColor(Color.BLUE)
)
      

建立一個中空的多邊形

將多個路徑組合至單一 Polygon 物件可建立較複雜的形狀,例如填滿的環形,即「甜甜圈」形狀 (多邊形區域內中還有另一個「獨立」的多邊形)。複雜的形狀都是由多個較簡單的路徑組成。

兩個路徑必須在同一區域中進行定義。兩個區域中較大的一個將定義填滿區域,而且會是一個不含其他選項的簡單多邊形。接著,將第二的路徑傳遞至 addHole() 方法。當第二個 (較小的) 路徑完全封閉於較大的路徑範圍內,看起來會像是大的多邊形內部少了一塊區域。如果這個中空的部分與多邊形的外框相交,該多邊形算繪時將不會有填滿效果。

下方程式碼片段將建立內部有一塊中空小矩形的單一矩形。

Java

List<LatLng> hole = Arrays.asList(new LatLng(1, 1),
    new LatLng(1, 2),
    new LatLng(2, 2),
    new LatLng(2, 1),
    new LatLng(1, 1));
Polygon hollowPolygon = map.addPolygon(new PolygonOptions()
    .add(new LatLng(0, 0),
        new LatLng(0, 5),
        new LatLng(3, 5),
        new LatLng(3, 0),
        new LatLng(0, 0))
    .addHole(hole)
    .fillColor(Color.BLUE));
      

Kotlin

val hole = listOf(
    LatLng(1.0, 1.0),
    LatLng(1.0, 2.0),
    LatLng(2.0, 2.0),
    LatLng(2.0, 1.0),
    LatLng(1.0, 1.0)
)
val hollowPolygon = map.addPolygon(
    PolygonOptions()
        .add(
            LatLng(0.0, 0.0),
            LatLng(0.0, 5.0),
            LatLng(3.0, 5.0),
            LatLng(3.0, 0.0),
            LatLng(0.0, 0.0)
        )
        .addHole(hole)
        .fillColor(Color.BLUE)
)
      

多邊形事件

根據預設,多邊形不可點擊。您可以呼叫 Polygon.setClickable(boolean) 來啟用及停用可點擊屬性。

使用 OnPolygonClickListener 能監聽可點擊多邊形的點擊事件。如要在地圖上設定這個事件監聽器,請呼叫 GoogleMap.setOnPolygonClickListener(OnPolygonClickListener)。 這樣使用者點擊多邊形時,您就會收到 onPolygonClick(Polygon) 回呼。

圓形

除了一般的 Polygon 類別之外,Maps API 還提供 Circle 物件的專屬類別,可簡化其建構作業。

如要建構圓形,您必須指定以下兩個屬性:

  • LatLng 格式指定的 center
  • radius (單位為公尺)。

接著,將圓形定義為地球表面上距離 center radius 公尺的所有點的集合。Maps API 使用的麥卡托投影會在平面上算繪球體,而受到該投影方式的影響,圓形位於赤道附近時,在地圖上呈現出來的會是近乎完美的圓形,但一旦離赤道越來越遠,(在螢幕上) 看起來就越不像圓形。

下方程式碼片段會建構 CircleOptions 物件並呼叫 GoogleMap.addCircle(CircleOptions),將圓形加入地圖中:

Java

// Instantiates a new CircleOptions object and defines the center and radius
CircleOptions circleOptions = new CircleOptions()
    .center(new LatLng(37.4, -122.1))
    .radius(1000); // In meters

// Get back the mutable Circle
Circle circle = map.addCircle(circleOptions);
      

Kotlin

// Instantiates a new CircleOptions object and defines the center and radius
val circleOptions = CircleOptions()
    .center(LatLng(37.4, -122.1))
    .radius(1000.0) // In meters

// Get back the mutable Circle
val circle = map.addCircle(circleOptions)
      

如果您在加入圓形後想修改其形狀,可以呼叫 Circle.setRadius()Circle.setCenter() 並提供新的值。

不管是在將圓形加入地圖之前或之後,您都可以自訂圓形的外觀。詳情請參閱下方「自訂外觀」一節。

圓形事件

根據預設,圓形不可點擊。您可以呼叫 GoogleMap.addCircle()CircleOptions.clickable(boolean) (或呼叫 Circle.setClickable(boolean)) 來啟用及停用可點擊屬性。

使用 OnCircleClickListener 能監聽可點擊圓形的點擊事件。如要在地圖上設定這個事件監聽器,請呼叫 GoogleMap.setOnCircleClickListener(OnCircleClickListener)

這樣使用者點擊圓形時,您就會收到 onCircleClick(Circle) 回呼,如下列程式碼範例所示:

Java

Circle circle = map.addCircle(new CircleOptions()
    .center(new LatLng(37.4, -122.1))
    .radius(1000)
    .strokeWidth(10)
    .strokeColor(Color.GREEN)
    .fillColor(Color.argb(128, 255, 0, 0))
    .clickable(true));

map.setOnCircleClickListener(new GoogleMap.OnCircleClickListener() {
    @Override
    public void onCircleClick(Circle circle) {
        // Flip the r, g and b components of the circle's stroke color.
        int strokeColor = circle.getStrokeColor() ^ 0x00ffffff;
        circle.setStrokeColor(strokeColor);
    }
});
      

Kotlin

val circle = map.addCircle(
    CircleOptions()
        .center(LatLng(37.4, -122.1))
        .radius(1000.0)
        .strokeWidth(10f)
        .strokeColor(Color.GREEN)
        .fillColor(Color.argb(128, 255, 0, 0))
        .clickable(true)
)
map.setOnCircleClickListener {
    // Flip the r, g and b components of the circle's stroke color.
    val strokeColor = it.strokeColor xor 0x00ffffff
    it.strokeColor = strokeColor
}
      

自訂外觀

不管是在將形狀加入地圖之前 (方法是在選項物件上指定需要的屬性) 或之後,您都可以修改形狀的外觀。所有屬性都能使用 getter,因此您可以輕鬆存取形狀的目前狀態。

下列程式碼片段會針對墨爾本至伯斯的測地線段,加上粗的藍色折線。以下各節將詳細解釋這些屬性。

Java

Polyline polyline = map.addPolyline(new PolylineOptions()
    .add(new LatLng(-37.81319, 144.96298), new LatLng(-31.95285, 115.85734))
    .width(25)
    .color(Color.BLUE)
    .geodesic(true));
      

Kotlin

val polyline = map.addPolyline(
    PolylineOptions()
        .add(LatLng(-37.81319, 144.96298), LatLng(-31.95285, 115.85734))
        .width(25f)
        .color(Color.BLUE)
        .geodesic(true)
)
      

注意:雖然大多數屬性都可以套用至所述的形狀,但某些屬性可能不適用於特定形狀 (例如折線沒有內部區域,因此不能填滿顏色)。

筆劃顏色

筆劃顏色是 32 位元的 ARGB (Alpha、紅、綠、藍) 整數,用於指定形狀筆劃的不透明度和顏色。您可以呼叫 *Options.strokeColor(),在形狀的選項物件上設定這個屬性;如為折線則呼叫 PolylineOptions.color()。如果未指定,則預設的筆劃顏色為黑色 (Color.BLACK)。

在地圖中加入形狀後,呼叫 getStrokeColor() 可存取筆劃顏色,如為折線則呼叫 getColor();而呼叫 setStrokeColor() 可進行變更,如為折線則呼叫 setColor() for a polyline

填滿顏色

填滿顏色僅適用於多邊形和圓形。這個屬性不適用於折線,因為折線沒有定義的內部區域。此外,以多邊形來說,中空部分並不算是多邊形的內部區域,因此即使您設定了填滿顏色,中空部分也不會填色。

填滿顏色是 32 位元的 ARGB (Alpha、紅、綠、藍) 整數,用於指定形狀內部區域的不透明度和顏色。如要設定形狀選項物件的這個屬性,請呼叫 *Options.fillColor()。如果未指定,則預設值為透明 (Color.TRANSPARENT)。

在地圖中加入形狀後,呼叫 getFillColor() 可存取填滿顏色,呼叫 setFillColor() 則可進行變更。

筆劃寬度

線條筆劃的寬度是以像素 (px) 為單位的浮動值。縮放地圖時,寬度的尺寸不會改變 (也就是說,在所有縮放等級中,形狀的筆劃寬度都是相同的)。如要設定形狀選項物件的這個屬性,請呼叫 *Options.strokeWidth();如為折線則呼叫 PolylineOptions.width()。如果未指定,則預設的筆劃寬度為 10 像素。

在地圖中加入形狀後,呼叫 getStrokeWidth() 可存取筆劃寬度,如為折線則呼叫 getWidth();而呼叫 setStrokeWidth() 可進行變更,如為折線則呼叫 setWidth() for a polyline

筆劃圖案

多邊形和圓形的外框及折線的預設筆劃圖案為實線。您可以為 PatternItem 物件指定自訂筆劃圖案,各個圖案項目分別是破折號、點或間隔。

下列範例針對折線設定的圖案是依照「一個點,接著長度為 20 像素的間隔、長度為 30 像素的破折號,及另一個長度為 20 像素的間隔」的順序重複顯示。

Java

List<PatternItem> pattern = Arrays.asList(
    new Dot(), new Gap(20), new Dash(30), new Gap(20));
polyline.setPattern(pattern);
      

Kotlin

val pattern = listOf(
    Dot(), Gap(20F), Dash(30F), Gap(20F)
)
polyline.pattern = pattern
      

整組圖案會沿著線條依序重複出現 (從形狀的第一個端點開始顯示第一個圖案項目)。

連接類型

您可以利用 JointType 為折線和多邊形的外框指定斜角或圓角,取代預設的固定斜切連接類型。

以下範例會為折線套用圓角連接類型:

Java

polyline.setJointType(JointType.ROUND);
      

Kotlin

polyline.jointType = JointType.ROUND
      

連接類型會影響線條的內部彎曲。如果線條的筆劃圖案包含破折號,則當連接處剛好是破折號時,該圖案項目也會套用連接類型。點則不受連接類型的影響,因為點一定是圓形。

線條末端

您可以為折線的兩端指定 Cap 樣式,選項包括貼齊 (預設值)、方角、圓滑或自訂點陣圖。在 PolylineOptions.startCapPolylineOptions.endCap 中設定樣式,或使用適當的 getter 和 setter 方法。

下列程式碼片段是針對折線的開端指定圓滑樣式。

Java

polyline.setStartCap(new RoundCap());
      

Kotlin

polyline.startCap = RoundCap()
      

下列程式碼片段會為結尾端指定自訂點陣圖:

Java

polyline.setEndCap(
    new CustomCap(BitmapDescriptorFactory.fromResource(R.drawable.arrow), 16));
      

Kotlin

polyline.endCap = CustomCap(BitmapDescriptorFactory.fromResource(R.drawable.arrow), 16F)
      

使用自訂點陣圖時,應指定參照筆劃寬度 (以像素為單位)。API 會根據該筆劃寬度調整點陣圖。參照筆劃寬度是指您在設計末端的點陣圖圖片時,所使用的筆劃寬度 (以圖片的原始尺寸為準)。預設的參照筆劃寬度為 10 像素。提示:如要設定參照筆劃寬度,請在圖片編輯器中開啟點陣圖圖片並縮放至 100%,然後繪製相對於圖片的指定線條筆劃寬度。

如果您使用 BitmapDescriptorFactory.fromResource() 來建立點陣圖,請務必使用密度獨立資源 (nodpi)。

測地線段

測地線設定僅適用於折線和多邊形;圓形不是線段的集合,因此不適用。

測地線設定可決定折線/多邊形連續端點之間的線段繪製方式。測地線段是指依照地球表面 (球體) 上最短路徑繪製的線條,在麥卡托投影地圖中通常會顯示為曲線。非測地線段在地圖上則繪製成直線。

如要設定形狀選項物件的這個屬性,請呼叫 *Options.geodesic()true 代表線段應繪製成測地線段,false 代表線段應繪製成直線。 如果未指定,則預設為非測地線段 (false)。

在地圖中加入形狀後,呼叫 isGeodesic() 可存取測地線設定,呼叫 setGeodesic() 則可進行變更。

Z-index

Z-index 會指定這個形狀相對於地圖上其他疊加層 (其他形狀、區域疊加層和圖塊疊加層) 的堆疊順序。系統會將 Z-index 順序高的疊加層繪製在順序較低的疊加層之上。若兩個疊加層的 Z-index 值相同,則由系統任意決定繪製順序。

請注意,無論其他疊加層的 Z-index 值為何,標記一律繪製在其他疊加層之上。

如要設定形狀選項物件的這個屬性,請呼叫 *Options.zIndex()。如果未指定,則預設的 Z-index 為 0。在地圖中加入形狀後,呼叫 getZIndex() 可存取 Z-index,呼叫 setZIndex() 則可進行變更。

顯示設定

顯示設定將指定是否要在地圖上繪製形狀,true 代表應繪製,false 代表不要繪製。您可以透過此設定,讓形狀暫時不要顯示於地圖上。如要從地圖上永久移除形狀,請針對該形狀呼叫 remove()

如要設定形狀選項物件的這個屬性,請呼叫 *Options.visible()。如果未指定,則預設的顯示設定為 true。 在地圖中加入形狀後,呼叫 isVisible() 可存取顯示設定,呼叫 setVisible() 則可進行變更。

為資料與形狀建立關聯

您可以使用形狀的 setTag() 方法儲存具有折線、多邊形或圓形的任意資料物件,並使用 getTag() 擷取資料物件。舉例來說,呼叫 Polyline.setTag() 可使用折線儲存資料物件,而呼叫 Polyline.getTag() 則可擷取資料物件。

以下程式碼會定義特定折線的任意標記 (A)。

Java

Polyline polyline = map.addPolyline((new PolylineOptions())
    .clickable(true)
    .add(new LatLng(-35.016, 143.321),
        new LatLng(-34.747, 145.592),
        new LatLng(-34.364, 147.891),
        new LatLng(-33.501, 150.217),
        new LatLng(-32.306, 149.248),
        new LatLng(-32.491, 147.309)));

polyline.setTag("A");
      

Kotlin

val polyline = map.addPolyline(
    PolylineOptions()
        .clickable(true)
        .add(
            LatLng(-35.016, 143.321),
            LatLng(-34.747, 145.592),
            LatLng(-34.364, 147.891),
            LatLng(-33.501, 150.217),
            LatLng(-32.306, 149.248),
            LatLng(-32.491, 147.309)
        )
)
polyline.tag = "A"
      

以下列舉一些利用形狀能更方便儲存/擷取資料的情境範例:

  • 應用程式支援不同類型的形狀,而您想要在使用者點擊形狀時,分別以不同的方式處理。
  • 您操作的系統可能採用不重複的記錄 ID,而在該系統內,形狀代表特定記錄。
  • 形狀資料可指定優先順序,藉此決定形狀的 Z-index。