Skip to content

Commit 93e8bfc

Browse files
committed
Support both instantianion styles
1 parent 8a88f5e commit 93e8bfc

6 files changed

Lines changed: 541 additions & 3 deletions

File tree

examples/Example03Markers/src/main/kotlin/de/afarber/openmapview/example03markers/MainActivity.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import androidx.compose.ui.viewinterop.AndroidView
2323
import de.afarber.openmapview.BitmapDescriptorFactory
2424
import de.afarber.openmapview.LatLng
2525
import de.afarber.openmapview.Marker
26+
import de.afarber.openmapview.MarkerOptions
2627
import de.afarber.openmapview.OpenMapView
2728

2829
class MainActivity : ComponentActivity() {
@@ -102,6 +103,16 @@ fun MapViewScreen() {
102103
),
103104
)
104105

106+
// Alternative: Google Maps API style using MarkerOptions builder
107+
addMarker(
108+
MarkerOptions()
109+
.position(LatLng(51.4650, 7.2500))
110+
.title("Builder Pattern")
111+
.snippet("Created with MarkerOptions")
112+
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_CYAN))
113+
.alpha(0.8f),
114+
)
115+
105116
// Set marker click listener
106117
// Info window is shown automatically if marker has title or snippet
107118
setOnMarkerClickListener { marker ->

examples/Example08Circles/src/main/kotlin/de/afarber/openmapview/example08circles/MainActivity.kt

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import androidx.compose.ui.Modifier
3636
import androidx.compose.ui.platform.LocalContext
3737
import androidx.compose.ui.unit.dp
3838
import androidx.compose.ui.viewinterop.AndroidView
39+
import de.afarber.openmapview.Circle
3940
import de.afarber.openmapview.CircleOptions
4041
import de.afarber.openmapview.LatLng
4142
import de.afarber.openmapview.OpenMapView
@@ -118,8 +119,23 @@ fun MapViewScreen() {
118119
.tag("Large Green Circle - 1500m"),
119120
)
120121

121-
circleCount += 3
122-
Toast.makeText(context, "Added 3 demonstration circles", Toast.LENGTH_SHORT).show()
122+
// Circle 4: Alternative Kotlin-style direct instantiation
123+
val offset3 = LatLng(bochumCenter.latitude + 0.005, bochumCenter.longitude - 0.015)
124+
map.addCircle(
125+
Circle(
126+
center = offset3,
127+
radius = 750f,
128+
strokeColor = Color.MAGENTA,
129+
strokeWidth = 6f,
130+
fillColor = Color.argb(64, 255, 0, 255),
131+
clickable = true,
132+
zIndex = 1.5f,
133+
tag = "Kotlin Style Circle - 750m",
134+
),
135+
)
136+
137+
circleCount += 4
138+
Toast.makeText(context, "Added 4 demonstration circles", Toast.LENGTH_SHORT).show()
123139
}
124140
}
125141

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/*
2+
* Copyright (c) 2025 Alexander Farber
3+
* SPDX-License-Identifier: MIT
4+
*
5+
* This file is part of the OpenMapView project (https://github.com/afarber/OpenMapView)
6+
*/
7+
8+
package de.afarber.openmapview
9+
10+
/**
11+
* Builder class for creating Marker instances with a fluent API.
12+
* Matches the Google Maps API pattern for marker configuration.
13+
*
14+
* Example usage:
15+
* ```
16+
* val marker = MarkerOptions()
17+
* .position(LatLng(51.4818, 0.0))
18+
* .title("Greenwich Observatory")
19+
* .snippet("Prime Meridian")
20+
* .draggable(true)
21+
* .alpha(0.8f)
22+
* ```
23+
*/
24+
class MarkerOptions {
25+
private var position: LatLng? = null
26+
private var title: String? = null
27+
private var snippet: String? = null
28+
private var icon: BitmapDescriptor? = null
29+
private var anchor: Pair<Float, Float> = Pair(0.5f, 1.0f)
30+
private var visible: Boolean = true
31+
private var alpha: Float = 1.0f
32+
private var draggable: Boolean = false
33+
private var zIndex: Float = 0f
34+
private var tag: Any? = null
35+
36+
/**
37+
* Sets the position of the marker.
38+
* @param position Geographic location of the marker
39+
*/
40+
fun position(position: LatLng): MarkerOptions {
41+
this.position = position
42+
return this
43+
}
44+
45+
/**
46+
* Sets the title text for the marker's info window.
47+
* @param title Title text (optional)
48+
*/
49+
fun title(title: String?): MarkerOptions {
50+
this.title = title
51+
return this
52+
}
53+
54+
/**
55+
* Sets the snippet text for the marker's info window.
56+
* @param snippet Snippet text (optional)
57+
*/
58+
fun snippet(snippet: String?): MarkerOptions {
59+
this.snippet = snippet
60+
return this
61+
}
62+
63+
/**
64+
* Sets a custom icon for the marker.
65+
* @param icon BitmapDescriptor for the icon (null for default red marker)
66+
*/
67+
fun icon(icon: BitmapDescriptor?): MarkerOptions {
68+
this.icon = icon
69+
return this
70+
}
71+
72+
/**
73+
* Sets the anchor point for the marker icon.
74+
* @param anchorU Horizontal anchor (0.0 = left edge, 0.5 = center, 1.0 = right edge)
75+
* @param anchorV Vertical anchor (0.0 = top edge, 0.5 = center, 1.0 = bottom edge)
76+
*/
77+
fun anchor(
78+
anchorU: Float,
79+
anchorV: Float,
80+
): MarkerOptions {
81+
this.anchor = Pair(anchorU, anchorV)
82+
return this
83+
}
84+
85+
/**
86+
* Sets whether the marker is visible.
87+
* @param visible true to show the marker, false to hide it
88+
*/
89+
fun visible(visible: Boolean): MarkerOptions {
90+
this.visible = visible
91+
return this
92+
}
93+
94+
/**
95+
* Sets the opacity of the marker.
96+
* @param alpha Opacity value between 0.0 (transparent) and 1.0 (opaque)
97+
*/
98+
fun alpha(alpha: Float): MarkerOptions {
99+
this.alpha = alpha
100+
return this
101+
}
102+
103+
/**
104+
* Sets whether the marker can be dragged.
105+
* @param draggable true to enable dragging, false otherwise
106+
*/
107+
fun draggable(draggable: Boolean): MarkerOptions {
108+
this.draggable = draggable
109+
return this
110+
}
111+
112+
/**
113+
* Sets the z-index for draw order.
114+
* @param zIndex Higher values are drawn on top (default: 0f)
115+
*/
116+
fun zIndex(zIndex: Float): MarkerOptions {
117+
this.zIndex = zIndex
118+
return this
119+
}
120+
121+
/**
122+
* Sets optional user data associated with the marker.
123+
* @param tag Any object to attach to the marker
124+
*/
125+
fun tag(tag: Any?): MarkerOptions {
126+
this.tag = tag
127+
return this
128+
}
129+
130+
/**
131+
* Builds and returns a Marker instance.
132+
* @throws IllegalArgumentException if position is not set
133+
*/
134+
internal fun build(): Marker {
135+
val positionValue = position ?: throw IllegalArgumentException("Marker position must be set")
136+
137+
return Marker(
138+
position = positionValue,
139+
title = title,
140+
snippet = snippet,
141+
icon = icon,
142+
anchor = anchor,
143+
visible = visible,
144+
alpha = alpha,
145+
draggable = draggable,
146+
zIndex = zIndex,
147+
tag = tag,
148+
)
149+
}
150+
}

openmapview/src/main/kotlin/de/afarber/openmapview/OpenMapView.kt

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,27 @@ class OpenMapView
488488
return result
489489
}
490490

491+
/**
492+
* Adds a marker to the map using MarkerOptions builder (Google Maps API style).
493+
*
494+
* Example:
495+
* ```kotlin
496+
* mapView.addMarker(
497+
* MarkerOptions()
498+
* .position(LatLng(51.5, 0.0))
499+
* .title("London")
500+
* .draggable(true)
501+
* )
502+
* ```
503+
*
504+
* @param markerOptions Configuration for the marker
505+
* @return The created Marker instance
506+
*/
507+
fun addMarker(markerOptions: MarkerOptions): Marker {
508+
val marker = markerOptions.build()
509+
return addMarker(marker)
510+
}
511+
491512
/**
492513
* Removes a marker from the map.
493514
*
@@ -721,6 +742,28 @@ class OpenMapView
721742
return result
722743
}
723744

745+
/**
746+
* Adds a polyline to the map using PolylineOptions builder (Google Maps API style).
747+
*
748+
* Example:
749+
* ```kotlin
750+
* mapView.addPolyline(
751+
* PolylineOptions()
752+
* .add(LatLng(51.5, 0.0))
753+
* .add(LatLng(51.6, 0.1))
754+
* .color(Color.BLUE)
755+
* .width(5f)
756+
* )
757+
* ```
758+
*
759+
* @param polylineOptions Configuration for the polyline
760+
* @return The created Polyline instance
761+
*/
762+
fun addPolyline(polylineOptions: PolylineOptions): Polyline {
763+
val polyline = polylineOptions.build()
764+
return addPolyline(polyline)
765+
}
766+
724767
/**
725768
* Removes a polyline from the map.
726769
*
@@ -760,6 +803,28 @@ class OpenMapView
760803
return result
761804
}
762805

806+
/**
807+
* Adds a polygon to the map using PolygonOptions builder (Google Maps API style).
808+
*
809+
* Example:
810+
* ```kotlin
811+
* mapView.addPolygon(
812+
* PolygonOptions()
813+
* .add(LatLng(51.5, 0.0))
814+
* .add(LatLng(51.6, 0.0))
815+
* .add(LatLng(51.6, 0.1))
816+
* .fillColor(Color.argb(128, 255, 0, 0))
817+
* )
818+
* ```
819+
*
820+
* @param polygonOptions Configuration for the polygon
821+
* @return The created Polygon instance
822+
*/
823+
fun addPolygon(polygonOptions: PolygonOptions): Polygon {
824+
val polygon = polygonOptions.build()
825+
return addPolygon(polygon)
826+
}
827+
763828
/**
764829
* Removes a polygon from the map.
765830
*
@@ -788,13 +853,44 @@ class OpenMapView
788853
fun getPolygons(): List<Polygon> = controller.getPolygons()
789854

790855
/**
791-
* Adds a circle to the map using CircleOptions.
856+
* Adds a circle to the map using CircleOptions builder (Google Maps API style).
857+
*
858+
* Example:
859+
* ```kotlin
860+
* mapView.addCircle(
861+
* CircleOptions()
862+
* .center(LatLng(51.5, 0.0))
863+
* .radius(1000f)
864+
* .fillColor(Color.argb(128, 0, 0, 255))
865+
* )
866+
* ```
792867
*
793868
* @param circleOptions Configuration for the circle
794869
* @return The created Circle instance
795870
*/
796871
fun addCircle(circleOptions: CircleOptions): Circle {
797872
val circle = circleOptions.build()
873+
return addCircle(circle)
874+
}
875+
876+
/**
877+
* Adds a circle to the map (Kotlin-style direct instantiation).
878+
*
879+
* Example:
880+
* ```kotlin
881+
* mapView.addCircle(
882+
* Circle(
883+
* center = LatLng(51.5, 0.0),
884+
* radius = 1000f,
885+
* fillColor = Color.argb(128, 0, 0, 255)
886+
* )
887+
* )
888+
* ```
889+
*
890+
* @param circle The circle to add
891+
* @return The added circle instance
892+
*/
893+
fun addCircle(circle: Circle): Circle {
798894
val result = controller.addCircle(circle)
799895
invalidate()
800896
return result

0 commit comments

Comments
 (0)