Add a marker with info window to a map

This example identifies a location on the map with a marker. When the user taps a marker, an info window appears.

For more information, see the documentation.

Get started

Before you can try the sample code, you must configure your development environment. For more information, see Maps SDK for Android code samples .

View the code

Kotlin

 class 
  
 MarkerDemoActivity 
  
 : 
  
 SamplesBaseActivity 
 (), 
  
 OnMarkerClickListener 
 , 
  
 OnInfoWindowClickListener 
 , 
  
 OnMarkerDragListener 
 , 
  
 OnInfoWindowLongClickListener 
 , 
  
 OnInfoWindowCloseListener 
 , 
  
 OnMapAndViewReadyListener 
 . 
 OnGlobalLayoutAndMapReadyListener 
  
 { 
  
 private 
  
 val 
  
 TAG 
  
 = 
  
 MarkerDemoActivity 
 :: 
 class 
 . 
 java 
 . 
 name 
  
 /** This is ok to be lateinit as it is initialised in onMapReady */ 
  
 private 
  
 lateinit 
  
 var 
  
 map 
 : 
  
 GoogleMap 
  
 /** 
 * Keeps track of the last selected marker (though it may no longer be selected).  This is 
 * useful for refreshing the info window. 
 * 
 * Must be nullable as it is null when no marker has been selected 
 */ 
  
 private 
  
 var 
  
 lastSelectedMarker 
 : 
  
 Marker? 
 = 
  
 null 
  
 private 
  
 val 
  
 markerRainbow 
  
 = 
  
 ArrayList<Marker> 
 () 
  
 /** map to store place names and locations */ 
  
 private 
  
 val 
  
 places 
  
 = 
  
 mapOf 
 ( 
  
 "BRISBANE" 
  
 to 
  
 LatLng 
 ( 
 - 
 27.47093 
 , 
  
 153.0235 
 ), 
  
 "MELBOURNE" 
  
 to 
  
 LatLng 
 ( 
 - 
 37.81319 
 , 
  
 144.96298 
 ), 
  
 "DARWIN" 
  
 to 
  
 LatLng 
 ( 
 - 
 12.4634 
 , 
  
 130.8456 
 ), 
  
 "SYDNEY" 
  
 to 
  
 LatLng 
 ( 
 - 
 33.87365 
 , 
  
 151.20689 
 ), 
  
 "ADELAIDE" 
  
 to 
  
 LatLng 
 ( 
 - 
 34.92873 
 , 
  
 138.59995 
 ), 
  
 "PERTH" 
  
 to 
  
 LatLng 
 ( 
 - 
 31.952854 
 , 
  
 115.857342 
 ), 
  
 "ALICE_SPRINGS" 
  
 to 
  
 LatLng 
 ( 
 - 
 24.6980 
 , 
  
 133.8807 
 ) 
  
 ) 
  
 /** These can be lateinit as they are set in onCreate */ 
  
 private 
  
 lateinit 
  
 var 
  
 topText 
 : 
  
 TextView 
  
 private 
  
 lateinit 
  
 var 
  
 rotationBar 
 : 
  
 SeekBar 
  
 private 
  
 lateinit 
  
 var 
  
 flatBox 
 : 
  
 CheckBox 
  
 private 
  
 lateinit 
  
 var 
  
 options 
 : 
  
 RadioGroup 
  
 private 
  
 val 
  
 random 
  
 = 
  
 Random 
 () 
  
 /** Demonstrates customizing the info window and/or its contents.  */ 
  
 internal 
  
 inner 
  
 class 
  
 CustomInfoWindowAdapter 
  
 : 
  
 InfoWindowAdapter 
  
 { 
  
 // These are both view groups containing an ImageView with id "badge" and two 
  
 // TextViews with id "title" and "snippet". 
  
 private 
  
 val 
  
 window 
 : 
  
 View 
  
 = 
  
 layoutInflater 
 . 
 inflate 
 ( 
 R 
 . 
 layout 
 . 
 custom_info_window 
 , 
  
 null 
 ) 
  
 private 
  
 val 
  
 contents 
 : 
  
 View 
  
 = 
  
 layoutInflater 
 . 
 inflate 
 ( 
 R 
 . 
 layout 
 . 
 custom_info_contents 
 , 
  
 null 
 ) 
  
 override 
  
 fun 
  
 getInfoWindow 
 ( 
 marker 
 : 
  
 Marker 
 ): 
  
 View? 
 { 
  
 if 
  
 ( 
 options 
 . 
 checkedRadioButtonId 
  
 != 
  
 R 
 . 
 id 
 . 
 custom_info_window 
 ) 
  
 { 
  
 // This means that getInfoContents will be called. 
  
 return 
  
 null 
  
 } 
  
 render 
 ( 
 marker 
 , 
  
 window 
 ) 
  
 return 
  
 window 
  
 } 
  
 override 
  
 fun 
  
 getInfoContents 
 ( 
 marker 
 : 
  
 Marker 
 ): 
  
 View? 
 { 
  
 if 
  
 ( 
 options 
 . 
 checkedRadioButtonId 
  
 != 
  
 R 
 . 
 id 
 . 
 custom_info_contents 
 ) 
  
 { 
  
 // This means that the default info contents will be used. 
  
 return 
  
 null 
  
 } 
  
 render 
 ( 
 marker 
 , 
  
 contents 
 ) 
  
 return 
  
 contents 
  
 } 
  
 private 
  
 fun 
  
 render 
 ( 
 marker 
 : 
  
 Marker 
 , 
  
 view 
 : 
  
 View 
 ) 
  
 { 
  
 val 
  
 badge 
  
 = 
  
 when 
  
 ( 
 marker 
 . 
 title 
 !! 
 ) 
  
 { 
  
 "Brisbane" 
  
 - 
>  
 R 
 . 
 drawable 
 . 
 badge_qld 
  
 "Adelaide" 
  
 - 
>  
 R 
 . 
 drawable 
 . 
 badge_sa 
  
 "Sydney" 
  
 - 
>  
 R 
 . 
 drawable 
 . 
 badge_nsw 
  
 "Melbourne" 
  
 - 
>  
 R 
 . 
 drawable 
 . 
 badge_victoria 
  
 "Perth" 
  
 - 
>  
 R 
 . 
 drawable 
 . 
 badge_wa 
  
 in 
  
 "Darwin Marker 1" 
 .. 
 "Darwin Marker 4" 
  
 - 
>  
 R 
 . 
 drawable 
 . 
 badge_nt 
  
 else 
  
 - 
>  
 0 
  
 // Passing 0 to setImageResource will clear the image view. 
  
 } 
  
 view 
 . 
 findViewById<ImageView> 
 ( 
 R 
 . 
 id 
 . 
 badge 
 ). 
 setImageResource 
 ( 
 badge 
 ) 
  
 // Set the title and snippet for the custom info window 
  
 val 
  
 title 
 : 
  
 String? 
  
 = 
  
 marker 
 . 
 title 
  
 val 
  
 titleUi 
  
 = 
  
 view 
 . 
 findViewById<TextView> 
 ( 
 R 
 . 
 id 
 . 
 title 
 ) 
  
 if 
  
 ( 
 title 
  
 != 
  
 null 
 ) 
  
 { 
  
 // Spannable string allows us to edit the formatting of the text. 
  
 titleUi 
 . 
 text 
  
 = 
  
 SpannableString 
 ( 
 title 
 ). 
 apply 
  
 { 
  
 setSpan 
 ( 
 ForegroundColorSpan 
 ( 
 Color 
 . 
 RED 
 ), 
  
 0 
 , 
  
 length 
 , 
  
 0 
 ) 
  
 } 
  
 } 
  
 else 
  
 { 
  
 titleUi 
 . 
 text 
  
 = 
  
 "" 
  
 } 
  
 val 
  
 snippet 
 : 
  
 String? 
  
 = 
  
 marker 
 . 
 snippet 
  
 val 
  
 snippetUi 
  
 = 
  
 view 
 . 
 findViewById<TextView> 
 ( 
 R 
 . 
 id 
 . 
 snippet 
 ) 
  
 if 
  
 ( 
 snippet 
  
 != 
  
 null 
 && 
 snippet 
 . 
 length 
 > 
 12 
 ) 
  
 { 
  
 snippetUi 
 . 
 text 
  
 = 
  
 SpannableString 
 ( 
 snippet 
 ). 
 apply 
  
 { 
  
 setSpan 
 ( 
 ForegroundColorSpan 
 ( 
 Color 
 . 
 MAGENTA 
 ), 
  
 0 
 , 
  
 10 
 , 
  
 0 
 ) 
  
 setSpan 
 ( 
 ForegroundColorSpan 
 ( 
 Color 
 . 
 BLUE 
 ), 
  
 12 
 , 
  
 snippet 
 . 
 length 
 , 
  
 0 
 ) 
  
 } 
  
 } 
  
 else 
  
 { 
  
 snippetUi 
 . 
 text 
  
 = 
  
 "" 
  
 } 
  
 } 
  
 } 
  
 override 
  
 fun 
  
 onCreate 
 ( 
 savedInstanceState 
 : 
  
 Bundle?) 
  
 { 
  
 super 
 . 
 onCreate 
 ( 
 savedInstanceState 
 ) 
  
 setContentView 
 ( 
 R 
 . 
 layout 
 . 
 marker_demo 
 ) 
  
 topText 
  
 = 
  
 findViewById 
 ( 
 R 
 . 
 id 
 . 
 top_text 
 ) 
  
 rotationBar 
  
 = 
  
 findViewById<SeekBar> 
 ( 
 R 
 . 
 id 
 . 
 rotationSeekBar 
 ). 
 apply 
  
 { 
  
 max 
  
 = 
  
 360 
  
 setOnSeekBarChangeListener 
 ( 
 object 
 : 
  
 OnSeekBarChangeListener 
  
 { 
  
 /** Called when the Rotation progress bar is moved */ 
  
 override 
  
 fun 
  
 onProgressChanged 
 ( 
 seekBar 
 : 
  
 SeekBar?, 
  
 progress 
 : 
  
 Int 
 , 
  
 fromUser 
 : 
  
 Boolean 
 ) 
  
 { 
  
 val 
  
 rotation 
  
 = 
  
 seekBar 
 ?. 
 progress 
 ?. 
 toFloat 
 () 
  
 checkReadyThen 
  
 { 
  
 markerRainbow 
 . 
 map 
  
 { 
  
 it 
 . 
 rotation 
  
 = 
  
 rotation 
  
 ?: 
  
 0f 
  
 } 
  
 } 
  
 } 
  
 override 
  
 fun 
  
 onStartTrackingTouch 
 ( 
 p0 
 : 
  
 SeekBar?) 
  
 { 
  
 // do nothing 
  
 } 
  
 override 
  
 fun 
  
 onStopTrackingTouch 
 ( 
 p0 
 : 
  
 SeekBar?) 
  
 { 
  
 //do nothing 
  
 } 
  
 } 
  
 ) 
  
 } 
  
 flatBox 
  
 = 
  
 findViewById 
 ( 
 R 
 . 
 id 
 . 
 flat 
 ) 
  
 options 
  
 = 
  
 findViewById<RadioGroup> 
 ( 
 R 
 . 
 id 
 . 
 custom_info_window_options 
 ). 
 apply 
  
 { 
  
 setOnCheckedChangeListener 
  
 { 
  
 _ 
 , 
  
 _ 
  
 - 
>  
 if 
  
 ( 
 lastSelectedMarker 
 ?. 
 isInfoWindowShown 
  
 == 
  
 true 
 ) 
  
 { 
  
 // Refresh the info window when the info window's content has changed. 
  
 // must deal with the possibility that lastSelectedMarker has changed in 
  
 // another thread between the null check and this line, do this with !! 
  
 lastSelectedMarker 
 ?. 
 showInfoWindow 
 () 
  
 } 
  
 } 
  
 } 
  
 val 
  
 mapFragment 
  
 = 
  
 supportFragmentManager 
 . 
 findFragmentById 
 ( 
 R 
 . 
 id 
 . 
 map 
 ) 
  
 as 
  
 SupportMapFragment 
  
 OnMapAndViewReadyListener 
 ( 
 mapFragment 
 , 
  
 this 
 ) 
  
 applyInsets 
 ( 
 findViewById<View?>(R 
 . 
 id 
 . 
 map_container 
 )) 
  
 } 
  
 /** 
 * This is the callback that is triggered when the GoogleMap has loaded and is ready for use 
 */ 
  
 override 
  
 fun 
  
 onMapReady 
 ( 
 googleMap 
 : 
  
 GoogleMap?) 
  
 { 
  
 // return early if the map was not initialised properly 
  
 map 
  
 = 
  
 googleMap 
  
 ?: 
  
 return 
  
 // create bounds that encompass every location we reference 
  
 val 
  
 boundsBuilder 
  
 = 
  
 LatLngBounds 
 . 
 Builder 
 () 
  
 // include all places we have markers for on the map 
  
 places 
 . 
 keys 
 . 
 map 
  
 { 
  
 place 
  
 - 
>  
 boundsBuilder 
 . 
 include 
 ( 
 places 
 . 
 getValue 
 ( 
 place 
 )) 
  
 } 
  
 val 
  
 bounds 
  
 = 
  
 boundsBuilder 
 . 
 build 
 () 
  
 with 
 ( 
 map 
 ) 
  
 { 
  
 // Hide the zoom controls as the button panel will cover it. 
  
 uiSettings 
 . 
 isZoomControlsEnabled 
  
 = 
  
 false 
  
 // Setting an info window adapter allows us to change the both the contents and 
  
 // look of the info window. 
  
 setInfoWindowAdapter 
 ( 
 CustomInfoWindowAdapter 
 ()) 
  
 // Set listeners for marker events.  See the bottom of this class for their behavior. 
  
 setOnMarkerClickListener 
 ( 
 this 
 @MarkerDemoActivity 
 ) 
  
 setOnInfoWindowClickListener 
 ( 
 this 
 @MarkerDemoActivity 
 ) 
  
 setOnMarkerDragListener 
 ( 
 this 
 @MarkerDemoActivity 
 ) 
  
 setOnInfoWindowCloseListener 
 ( 
 this 
 @MarkerDemoActivity 
 ) 
  
 setOnInfoWindowLongClickListener 
 ( 
 this 
 @MarkerDemoActivity 
 ) 
  
 // Override the default content description on the view, for accessibility mode. 
  
 // Ideally this string would be localised. 
  
 setContentDescription 
 ( 
 "Map with lots of markers." 
 ) 
  
 moveCamera 
 ( 
 CameraUpdateFactory 
 . 
 newLatLngBounds 
 ( 
 bounds 
 , 
  
 50 
 )) 
  
 } 
  
 // Add lots of markers to the googleMap. 
  
 addMarkersToMap 
 () 
  
 } 
  
 /** 
 * Show all the specified markers on the map 
 */ 
  
 private 
  
 fun 
  
 addMarkersToMap 
 () 
  
 { 
  
 val 
  
 placeDetailsMap 
  
 = 
  
 mutableMapOf 
 ( 
  
 // Uses a coloured icon 
  
 "BRISBANE" 
  
 to 
  
 PlaceDetails 
 ( 
  
 position 
  
 = 
  
 places 
 . 
 getValue 
 ( 
 "BRISBANE" 
 ), 
  
 title 
  
 = 
  
 "Brisbane" 
 , 
  
 snippet 
  
 = 
  
 "Population: 2,074,200" 
 , 
  
 icon 
  
 = 
  
 BitmapDescriptorFactory 
  
 . 
 defaultMarker 
 ( 
 BitmapDescriptorFactory 
 . 
 HUE_AZURE 
 ) 
  
 ), 
  
 // Uses a custom icon with the info window popping out of the center of the icon. 
  
 "SYDNEY" 
  
 to 
  
 PlaceDetails 
 ( 
  
 position 
  
 = 
  
 places 
 . 
 getValue 
 ( 
 "SYDNEY" 
 ), 
  
 title 
  
 = 
  
 "Sydney" 
 , 
  
 snippet 
  
 = 
  
 "Population: 4,627,300" 
 , 
  
 icon 
  
 = 
  
 BitmapDescriptorFactory 
 . 
 fromResource 
 ( 
 R 
 . 
 drawable 
 . 
 arrow 
 ), 
  
 infoWindowAnchorX 
  
 = 
  
 0.5f 
 , 
  
 infoWindowAnchorY 
  
 = 
  
 0.5f 
  
 ), 
  
 // Will create a draggable marker. Long press to drag. 
  
 "MELBOURNE" 
  
 to 
  
 PlaceDetails 
 ( 
  
 position 
  
 = 
  
 places 
 . 
 getValue 
 ( 
 "MELBOURNE" 
 ), 
  
 title 
  
 = 
  
 "Melbourne" 
 , 
  
 snippet 
  
 = 
  
 "Population: 4,137,400" 
 , 
  
 draggable 
  
 = 
  
 true 
  
 ), 
  
 // Use a vector drawable resource as a marker icon. 
  
 "ALICE_SPRINGS" 
  
 to 
  
 PlaceDetails 
 ( 
  
 position 
  
 = 
  
 places 
 . 
 getValue 
 ( 
 "ALICE_SPRINGS" 
 ), 
  
 title 
  
 = 
  
 "Alice Springs" 
 , 
  
 icon 
  
 = 
  
 vectorToBitmap 
 ( 
  
 R 
 . 
 drawable 
 . 
 ic_android 
 , 
  
 Color 
 . 
 parseColor 
 ( 
 "#A4C639" 
 )) 
  
 ), 
  
 // More markers for good measure 
  
 "PERTH" 
  
 to 
  
 PlaceDetails 
 ( 
  
 position 
  
 = 
  
 places 
 . 
 getValue 
 ( 
 "PERTH" 
 ), 
  
 title 
  
 = 
  
 "Perth" 
 , 
  
 snippet 
  
 = 
  
 "Population: 1,738,800" 
  
 ), 
  
 "ADELAIDE" 
  
 to 
  
 PlaceDetails 
 ( 
  
 position 
  
 = 
  
 places 
 . 
 getValue 
 ( 
 "ADELAIDE" 
 ), 
  
 title 
  
 = 
  
 "Adelaide" 
 , 
  
 snippet 
  
 = 
  
 "Population: 1,213,000" 
  
 ) 
  
 ) 
  
 // add 4 markers on top of each other in Darwin with varying z-indexes 
  
 ( 
 0 
  
 until 
  
 4 
 ). 
 map 
  
 { 
  
 placeDetailsMap 
 . 
 put 
 ( 
  
 "DARWIN 
 ${ 
 it 
  
 + 
  
 1 
 } 
 " 
 , 
  
 PlaceDetails 
 ( 
  
 position 
  
 = 
  
 places 
 . 
 getValue 
 ( 
 "DARWIN" 
 ), 
  
 title 
  
 = 
  
 "Darwin Marker 
 ${ 
 it 
  
 + 
  
 1 
 } 
 " 
 , 
  
 snippet 
  
 = 
  
 "z-index initially 
 ${ 
 it 
  
 + 
  
 1 
 } 
 " 
 , 
  
 zIndex 
  
 = 
  
 it 
 . 
 toFloat 
 () 
  
 ) 
  
 ) 
  
 } 
  
 // place markers for each of the defined locations 
  
 placeDetailsMap 
 . 
 keys 
 . 
 map 
  
 { 
  
 with 
 ( 
 placeDetailsMap 
 . 
 getValue 
 ( 
 it 
 )) 
  
 { 
  
 map 
 . 
 addMarker 
 ( 
 MarkerOptions 
 () 
  
 . 
 position 
 ( 
 position 
 ) 
  
 . 
 title 
 ( 
 title 
 ) 
  
 . 
 snippet 
 ( 
 snippet 
 ) 
  
 . 
 icon 
 ( 
 icon 
 ) 
  
 . 
 infoWindowAnchor 
 ( 
 infoWindowAnchorX 
 , 
  
 infoWindowAnchorY 
 ) 
  
 . 
 draggable 
 ( 
 draggable 
 ) 
  
 . 
 zIndex 
 ( 
 zIndex 
 )) 
  
 } 
  
 } 
  
 // Creates a marker rainbow demonstrating how to create default marker icons of different 
  
 // hues (colors). 
  
 val 
  
 numMarkersInRainbow 
  
 = 
  
 12 
  
 ( 
 0 
  
 until 
  
 numMarkersInRainbow 
 ). 
 mapTo 
 ( 
 markerRainbow 
 ) 
  
 { 
  
 map 
 . 
 addMarker 
 ( 
 MarkerOptions 
 (). 
 apply 
 { 
  
 position 
 ( 
 LatLng 
 ( 
  
 - 
 30 
  
 + 
  
 10 
  
 * 
  
 Math 
 . 
 sin 
 ( 
 it 
  
 * 
  
 Math 
 . 
 PI 
  
 / 
  
 ( 
 numMarkersInRainbow 
  
 - 
  
 1 
 )), 
  
 135 
  
 - 
  
 10 
  
 * 
  
 Math 
 . 
 cos 
 ( 
 it 
  
 * 
  
 Math 
 . 
 PI 
  
 / 
  
 ( 
 numMarkersInRainbow 
  
 - 
  
 1 
 )))) 
  
 title 
 ( 
 "Marker 
 $ 
 it 
 " 
 ) 
  
 icon 
 ( 
 BitmapDescriptorFactory 
 . 
 defaultMarker 
 (( 
 it 
  
 * 
  
 360 
  
 / 
  
 numMarkersInRainbow 
 ) 
  
 . 
 toFloat 
 ())) 
  
 flat 
 ( 
 flatBox 
 . 
 isChecked 
 ) 
  
 rotation 
 ( 
 rotationBar 
 . 
 progress 
 . 
 toFloat 
 ()) 
  
 }) 
 !! 
  
 } 
  
 } 
  
 /** 
 * Demonstrates converting a [Drawable] to a [BitmapDescriptor], 
 * for use as a marker icon. 
 */ 
  
 private 
  
 fun 
  
 vectorToBitmap 
 ( 
 @DrawableRes 
  
 id 
  
 : 
  
 Int 
 , 
  
 @ColorInt 
  
 color 
  
 : 
  
 Int 
 ): 
  
 BitmapDescriptor 
  
 { 
  
 val 
  
 vectorDrawable 
 : 
  
 Drawable? 
 = 
  
 ResourcesCompat 
 . 
 getDrawable 
 ( 
 resources 
 , 
  
 id 
 , 
  
 null 
 ) 
  
 if 
  
 ( 
 vectorDrawable 
  
 == 
  
 null 
 ) 
  
 { 
  
 Log 
 . 
 e 
 ( 
 TAG 
 , 
  
 "Resource not found" 
 ) 
  
 return 
  
 BitmapDescriptorFactory 
 . 
 defaultMarker 
 () 
  
 } 
  
 val 
  
 bitmap 
  
 = 
  
 Bitmap 
 . 
 createBitmap 
 ( 
 vectorDrawable 
 . 
 intrinsicWidth 
 , 
  
 vectorDrawable 
 . 
 intrinsicHeight 
 , 
  
 Bitmap 
 . 
 Config 
 . 
 ARGB_8888 
 ) 
  
 val 
  
 canvas 
  
 = 
  
 Canvas 
 ( 
 bitmap 
 ) 
  
 vectorDrawable 
 . 
 setBounds 
 ( 
 0 
 , 
  
 0 
 , 
  
 canvas 
 . 
 width 
 , 
  
 canvas 
 . 
 height 
 ) 
  
 DrawableCompat 
 . 
 setTint 
 ( 
 vectorDrawable 
 , 
  
 color 
 ) 
  
 vectorDrawable 
 . 
 draw 
 ( 
 canvas 
 ) 
  
 return 
  
 BitmapDescriptorFactory 
 . 
 fromBitmap 
 ( 
 bitmap 
 ) 
  
 } 
  
 /** Called when the Clear button is clicked.  */ 
  
 @Suppress 
 ( 
 "UNUSED_PARAMETER" 
 ) 
  
 fun 
  
 onClearMap 
 ( 
 view 
 : 
  
 View 
 ) 
  
 { 
  
 checkReadyThen 
  
 { 
  
 map 
 . 
 clear 
 () 
  
 } 
  
 } 
  
 /** Called when the Reset button is clicked.  */ 
  
 @Suppress 
 ( 
 "UNUSED_PARAMETER" 
 ) 
  
 fun 
  
 onResetMap 
 ( 
 view 
 : 
  
 View 
 ) 
  
 { 
  
 checkReadyThen 
  
 { 
  
 map 
 . 
 clear 
 () 
  
 addMarkersToMap 
 () 
  
 } 
  
 } 
  
 /** Called when the Flat check box is checked or unchecked */ 
  
 @Suppress 
 ( 
 "UNUSED_PARAMETER" 
 ) 
  
 fun 
  
 onToggleFlat 
 ( 
 view 
 : 
  
 View 
 ) 
  
 { 
  
 checkReadyThen 
  
 { 
  
 markerRainbow 
 . 
 map 
  
 { 
  
 marker 
  
 - 
>  
 marker 
 . 
 isFlat 
  
 = 
  
 flatBox 
 . 
 isChecked 
  
 } 
  
 } 
  
 } 
  
 // 
  
 // Marker related listeners. 
  
 // 
  
 override 
  
 fun 
  
 onMarkerClick 
 ( 
 marker 
  
 : 
  
 Marker 
 ): 
  
 Boolean 
  
 { 
  
 // Markers have a z-index that is settable and gettable. 
  
 marker 
 . 
 zIndex 
  
 += 
  
 1.0f 
  
 Toast 
 . 
 makeText 
 ( 
 this 
 , 
  
 " 
 ${ 
 marker 
 . 
 title 
 } 
 z-index set to 
 ${ 
 marker 
 . 
 zIndex 
 } 
 " 
 , 
  
 Toast 
 . 
 LENGTH_SHORT 
 ). 
 show 
 () 
  
 lastSelectedMarker 
  
 = 
  
 marker 
  
 if 
  
 ( 
 marker 
 . 
 position 
  
 == 
  
 places 
 . 
 getValue 
 ( 
 "PERTH" 
 )) 
  
 { 
  
 // This causes the marker at Perth to bounce into position when it is clicked. 
  
 val 
  
 handler 
  
 = 
  
 Handler 
 () 
  
 val 
  
 start 
  
 = 
  
 SystemClock 
 . 
 uptimeMillis 
 () 
  
 val 
  
 duration 
  
 = 
  
 1500 
  
 val 
  
 interpolator 
  
 = 
  
 BounceInterpolator 
 () 
  
 handler 
 . 
 post 
 ( 
 object 
  
 : 
  
 Runnable 
  
 { 
  
 override 
  
 fun 
  
 run 
 () 
  
 { 
  
 val 
  
 elapsed 
  
 = 
  
 SystemClock 
 . 
 uptimeMillis 
 () 
  
 - 
  
 start 
  
 val 
  
 t 
  
 = 
  
 Math 
 . 
 max 
 ( 
  
 1 
  
 - 
  
 interpolator 
 . 
 getInterpolation 
 ( 
 elapsed 
 . 
 toFloat 
 () 
  
 / 
  
 duration 
 ), 
  
 0f 
 ) 
  
 marker 
 . 
 setAnchor 
 ( 
 0.5f 
 , 
  
 1.0f 
  
 + 
  
 2 
  
 * 
  
 t 
 ) 
  
 // Post again 16ms later. 
  
 if 
  
 ( 
 t 
 > 
 0.0 
 ) 
  
 { 
  
 handler 
 . 
 postDelayed 
 ( 
 this 
 , 
  
 16 
 ) 
  
 } 
  
 } 
  
 }) 
  
 } 
  
 else 
  
 if 
  
 ( 
 marker 
 . 
 position 
  
 == 
  
 places 
 . 
 getValue 
 ( 
 "ADELAIDE" 
 )) 
  
 { 
  
 // This causes the marker at Adelaide to change color and alpha. 
  
 marker 
 . 
 apply 
  
 { 
  
 setIcon 
 ( 
 BitmapDescriptorFactory 
 . 
 defaultMarker 
 ( 
 random 
 . 
 nextFloat 
 () 
  
 * 
  
 360 
 )) 
  
 alpha 
  
 = 
  
 random 
 . 
 nextFloat 
 () 
  
 } 
  
 } 
  
 // We return false to indicate that we have not consumed the event and that we wish 
  
 // for the default behavior to occur (which is for the camera to move such that the 
  
 // marker is centered and for the marker's info window to open, if it has one). 
  
 return 
  
 false 
  
 } 
  
 override 
  
 fun 
  
 onInfoWindowClick 
 ( 
 marker 
  
 : 
  
 Marker 
 ) 
  
 { 
  
 Toast 
 . 
 makeText 
 ( 
 this 
 , 
  
 "Click Info Window" 
 , 
  
 Toast 
 . 
 LENGTH_SHORT 
 ). 
 show 
 () 
  
 } 
  
 override 
  
 fun 
  
 onInfoWindowClose 
 ( 
 marker 
  
 : 
  
 Marker 
 ) 
  
 { 
  
 Toast 
 . 
 makeText 
 ( 
 this 
 , 
  
 "Close Info Window" 
 , 
  
 Toast 
 . 
 LENGTH_SHORT 
 ). 
 show 
 () 
  
 } 
  
 override 
  
 fun 
  
 onInfoWindowLongClick 
 ( 
 marker 
  
 : 
  
 Marker 
 ) 
  
 { 
  
 Toast 
 . 
 makeText 
 ( 
 this 
 , 
  
 "Info Window long click" 
 , 
  
 Toast 
 . 
 LENGTH_SHORT 
 ). 
 show 
 () 
  
 } 
  
 override 
  
 fun 
  
 onMarkerDragStart 
 ( 
 marker 
  
 : 
  
 Marker 
 ) 
  
 { 
  
 topText 
 . 
 text 
  
 = 
  
 getString 
 ( 
 R 
 . 
 string 
 . 
 on_marker_drag_start 
 ) 
  
 } 
  
 override 
  
 fun 
  
 onMarkerDragEnd 
 ( 
 marker 
  
 : 
  
 Marker 
 ) 
  
 { 
  
 topText 
 . 
 text 
  
 = 
  
 getString 
 ( 
 R 
 . 
 string 
 . 
 on_marker_drag_end 
 ) 
  
 } 
  
 override 
  
 fun 
  
 onMarkerDrag 
 ( 
 marker 
  
 : 
  
 Marker 
 ) 
  
 { 
  
 topText 
 . 
 text 
  
 = 
  
 getString 
 ( 
 R 
 . 
 string 
 . 
 on_marker_drag 
 , 
  
 marker 
 . 
 position 
 . 
 latitude 
 , 
  
 marker 
 . 
 position 
 . 
 longitude 
 ) 
  
 } 
  
 /** 
 * Checks if the map is ready, the executes the provided lambda function 
 * 
 * @param stuffToDo the code to be executed if the map is ready 
 */ 
  
 private 
  
 fun 
  
 checkReadyThen 
 ( 
 stuffToDo 
  
 : 
  
 () 
  
 - 
>  
 Unit 
 ) 
  
 { 
  
 if 
  
 ( 
 !:: 
 map 
 . 
 isInitialized 
 ) 
  
 { 
  
 Toast 
 . 
 makeText 
 ( 
 this 
 , 
  
 R 
 . 
 string 
 . 
 map_not_ready 
 , 
  
 Toast 
 . 
 LENGTH_SHORT 
 ). 
 show 
 () 
  
 } 
  
 else 
  
 { 
  
 stuffToDo 
 () 
  
 } 
  
 } 
 } 
  
  

Java

 public 
  
 class 
 MarkerDemoActivity 
  
 extends 
  
 SamplesBaseActivity 
  
 implements 
  
 OnMarkerClickListener 
 , 
  
 OnInfoWindowClickListener 
 , 
  
 OnMarkerDragListener 
 , 
  
 OnSeekBarChangeListener 
 , 
  
 OnInfoWindowLongClickListener 
 , 
  
 OnInfoWindowCloseListener 
 , 
  
 OnMapAndViewReadyListener 
 . 
 OnGlobalLayoutAndMapReadyListener 
  
 { 
  
 private 
  
 static 
  
 final 
  
 LatLng 
  
 BRISBANE 
  
 = 
  
 new 
  
 LatLng 
 ( 
 - 
 27.47093 
 , 
  
 153.0235 
 ); 
  
 private 
  
 static 
  
 final 
  
 LatLng 
  
 MELBOURNE 
  
 = 
  
 new 
  
 LatLng 
 ( 
 - 
 37.81319 
 , 
  
 144.96298 
 ); 
  
 private 
  
 static 
  
 final 
  
 LatLng 
  
 DARWIN 
  
 = 
  
 new 
  
 LatLng 
 ( 
 - 
 12.4634 
 , 
  
 130.8456 
 ); 
  
 private 
  
 static 
  
 final 
  
 LatLng 
  
 SYDNEY 
  
 = 
  
 new 
  
 LatLng 
 ( 
 - 
 33.87365 
 , 
  
 151.20689 
 ); 
  
 private 
  
 static 
  
 final 
  
 LatLng 
  
 ADELAIDE 
  
 = 
  
 new 
  
 LatLng 
 ( 
 - 
 34.92873 
 , 
  
 138.59995 
 ); 
  
 private 
  
 static 
  
 final 
  
 LatLng 
  
 PERTH 
  
 = 
  
 new 
  
 LatLng 
 ( 
 - 
 31.952854 
 , 
  
 115.857342 
 ); 
  
 private 
  
 static 
  
 final 
  
 LatLng 
  
 ALICE_SPRINGS 
  
 = 
  
 new 
  
 LatLng 
 ( 
 - 
 24.6980 
 , 
  
 133.8807 
 ); 
  
 /** Demonstrates customizing the info window and/or its contents. */ 
  
 class 
 CustomInfoWindowAdapter 
  
 implements 
  
 InfoWindowAdapter 
  
 { 
  
 // These are both viewgroups containing an ImageView with id "badge" and two TextViews with id 
  
 // "title" and "snippet". 
  
 private 
  
 final 
  
 View 
  
 mWindow 
 ; 
  
 private 
  
 final 
  
 View 
  
 mContents 
 ; 
  
 CustomInfoWindowAdapter 
 () 
  
 { 
  
 mWindow 
  
 = 
  
 getLayoutInflater 
 (). 
 inflate 
 ( 
 R 
 . 
 layout 
 . 
 custom_info_window 
 , 
  
 null 
 ); 
  
 mContents 
  
 = 
  
 getLayoutInflater 
 (). 
 inflate 
 ( 
 R 
 . 
 layout 
 . 
 custom_info_contents 
 , 
  
 null 
 ); 
  
 } 
  
 @Override 
  
 public 
  
 View 
  
 getInfoWindow 
 ( 
 Marker 
  
 marker 
 ) 
  
 { 
  
 if 
  
 ( 
 mOptions 
 . 
 getCheckedRadioButtonId 
 () 
  
 != 
  
 R 
 . 
 id 
 . 
 custom_info_window 
 ) 
  
 { 
  
 // This means that getInfoContents will be called. 
  
 return 
  
 null 
 ; 
  
 } 
  
 render 
 ( 
 marker 
 , 
  
 mWindow 
 ); 
  
 return 
  
 mWindow 
 ; 
  
 } 
  
 @Override 
  
 public 
  
 View 
  
 getInfoContents 
 ( 
 Marker 
  
 marker 
 ) 
  
 { 
  
 if 
  
 ( 
 mOptions 
 . 
 getCheckedRadioButtonId 
 () 
  
 != 
  
 R 
 . 
 id 
 . 
 custom_info_contents 
 ) 
  
 { 
  
 // This means that the default info contents will be used. 
  
 return 
  
 null 
 ; 
  
 } 
  
 render 
 ( 
 marker 
 , 
  
 mContents 
 ); 
  
 return 
  
 mContents 
 ; 
  
 } 
  
 private 
  
 void 
  
 render 
 ( 
 Marker 
  
 marker 
 , 
  
 View 
  
 view 
 ) 
  
 { 
  
 int 
  
 badge 
 ; 
  
 // Use the equals() method on a Marker to check for equals.  Do not use ==. 
  
 if 
  
 ( 
 marker 
 . 
 equals 
 ( 
 mBrisbane 
 )) 
  
 { 
  
 badge 
  
 = 
  
 R 
 . 
 drawable 
 . 
 badge_qld 
 ; 
  
 } 
  
 else 
  
 if 
  
 ( 
 marker 
 . 
 equals 
 ( 
 mAdelaide 
 )) 
  
 { 
  
 badge 
  
 = 
  
 R 
 . 
 drawable 
 . 
 badge_sa 
 ; 
  
 } 
  
 else 
  
 if 
  
 ( 
 marker 
 . 
 equals 
 ( 
 mSydney 
 )) 
  
 { 
  
 badge 
  
 = 
  
 R 
 . 
 drawable 
 . 
 badge_nsw 
 ; 
  
 } 
  
 else 
  
 if 
  
 ( 
 marker 
 . 
 equals 
 ( 
 mMelbourne 
 )) 
  
 { 
  
 badge 
  
 = 
  
 R 
 . 
 drawable 
 . 
 badge_victoria 
 ; 
  
 } 
  
 else 
  
 if 
  
 ( 
 marker 
 . 
 equals 
 ( 
 mPerth 
 )) 
  
 { 
  
 badge 
  
 = 
  
 R 
 . 
 drawable 
 . 
 badge_wa 
 ; 
  
 } 
  
 else 
  
 if 
  
 ( 
 marker 
 . 
 equals 
 ( 
 mDarwin1 
 )) 
  
 { 
  
 badge 
  
 = 
  
 R 
 . 
 drawable 
 . 
 badge_nt 
 ; 
  
 } 
  
 else 
  
 if 
  
 ( 
 marker 
 . 
 equals 
 ( 
 mDarwin2 
 )) 
  
 { 
  
 badge 
  
 = 
  
 R 
 . 
 drawable 
 . 
 badge_nt 
 ; 
  
 } 
  
 else 
  
 if 
  
 ( 
 marker 
 . 
 equals 
 ( 
 mDarwin3 
 )) 
  
 { 
  
 badge 
  
 = 
  
 R 
 . 
 drawable 
 . 
 badge_nt 
 ; 
  
 } 
  
 else 
  
 if 
  
 ( 
 marker 
 . 
 equals 
 ( 
 mDarwin4 
 )) 
  
 { 
  
 badge 
  
 = 
  
 R 
 . 
 drawable 
 . 
 badge_nt 
 ; 
  
 } 
  
 else 
  
 { 
  
 // Passing 0 to setImageResource will clear the image view. 
  
 badge 
  
 = 
  
 0 
 ; 
  
 } 
  
 (( 
 ImageView 
 ) 
  
 view 
 . 
 findViewById 
 ( 
 R 
 . 
 id 
 . 
 badge 
 )). 
 setImageResource 
 ( 
 badge 
 ); 
  
 String 
  
 title 
  
 = 
  
 marker 
 . 
 getTitle 
 (); 
  
 TextView 
  
 titleUi 
  
 = 
  
 view 
 . 
 findViewById 
 ( 
 R 
 . 
 id 
 . 
 title 
 ); 
  
 if 
  
 ( 
 title 
  
 != 
  
 null 
 ) 
  
 { 
  
 // Spannable string allows us to edit the formatting of the text. 
  
 SpannableString 
  
 titleText 
  
 = 
  
 new 
  
 SpannableString 
 ( 
 title 
 ); 
  
 titleText 
 . 
 setSpan 
 ( 
 new 
  
 ForegroundColorSpan 
 ( 
 Color 
 . 
 RED 
 ), 
  
 0 
 , 
  
 titleText 
 . 
 length 
 (), 
  
 0 
 ); 
  
 titleUi 
 . 
 setText 
 ( 
 titleText 
 ); 
  
 } 
  
 else 
  
 { 
  
 titleUi 
 . 
 setText 
 ( 
 "" 
 ); 
  
 } 
  
 String 
  
 snippet 
  
 = 
  
 marker 
 . 
 getSnippet 
 (); 
  
 TextView 
  
 snippetUi 
  
 = 
  
 view 
 . 
 findViewById 
 ( 
 R 
 . 
 id 
 . 
 snippet 
 ); 
  
 if 
  
 ( 
 snippet 
  
 != 
  
 null 
 && 
 snippet 
 . 
 length 
 () 
 > 
 12 
 ) 
  
 { 
  
 SpannableString 
  
 snippetText 
  
 = 
  
 new 
  
 SpannableString 
 ( 
 snippet 
 ); 
  
 snippetText 
 . 
 setSpan 
 ( 
 new 
  
 ForegroundColorSpan 
 ( 
 Color 
 . 
 MAGENTA 
 ), 
  
 0 
 , 
  
 10 
 , 
  
 0 
 ); 
  
 snippetText 
 . 
 setSpan 
 ( 
 new 
  
 ForegroundColorSpan 
 ( 
 Color 
 . 
 BLUE 
 ), 
  
 12 
 , 
  
 snippet 
 . 
 length 
 (), 
  
 0 
 ); 
  
 snippetUi 
 . 
 setText 
 ( 
 snippetText 
 ); 
  
 } 
  
 else 
  
 { 
  
 snippetUi 
 . 
 setText 
 ( 
 "" 
 ); 
  
 } 
  
 } 
  
 } 
  
 private 
  
 GoogleMap 
  
 mMap 
 ; 
  
 private 
  
 Marker 
  
 mPerth 
 ; 
  
 private 
  
 Marker 
  
 mSydney 
 ; 
  
 private 
  
 Marker 
  
 mBrisbane 
 ; 
  
 private 
  
 Marker 
  
 mAdelaide 
 ; 
  
 private 
  
 Marker 
  
 mMelbourne 
 ; 
  
 private 
  
 Marker 
  
 mDarwin1 
 ; 
  
 private 
  
 Marker 
  
 mDarwin2 
 ; 
  
 private 
  
 Marker 
  
 mDarwin3 
 ; 
  
 private 
  
 Marker 
  
 mDarwin4 
 ; 
  
 /** 
 * Keeps track of the last selected marker (though it may no longer be selected).  This is 
 * useful for refreshing the info window. 
 */ 
  
 private 
  
 Marker 
  
 mLastSelectedMarker 
 ; 
  
 private 
  
 final 
  
 List<Marker> 
  
 mMarkerRainbow 
  
 = 
  
 new 
  
 ArrayList<Marker> 
 (); 
  
 private 
  
 TextView 
  
 mTopText 
 ; 
  
 private 
  
 SeekBar 
  
 mRotationBar 
 ; 
  
 private 
  
 CheckBox 
  
 mFlatBox 
 ; 
  
 private 
  
 RadioGroup 
  
 mOptions 
 ; 
  
 private 
  
 final 
  
 Random 
  
 mRandom 
  
 = 
  
 new 
  
 Random 
 (); 
  
 @Override 
  
 protected 
  
 void 
  
 onCreate 
 ( 
 Bundle 
  
 savedInstanceState 
 ) 
  
 { 
  
 super 
 . 
 onCreate 
 ( 
 savedInstanceState 
 ); 
  
 setContentView 
 ( 
 R 
 . 
 layout 
 . 
 marker_demo 
 ); 
  
 mTopText 
  
 = 
  
 findViewById 
 ( 
 R 
 . 
 id 
 . 
 top_text 
 ); 
  
 mRotationBar 
  
 = 
  
 findViewById 
 ( 
 R 
 . 
 id 
 . 
 rotationSeekBar 
 ); 
  
 mRotationBar 
 . 
 setMax 
 ( 
 360 
 ); 
  
 mRotationBar 
 . 
 setOnSeekBarChangeListener 
 ( 
 this 
 ); 
  
 mFlatBox 
  
 = 
  
 findViewById 
 ( 
 R 
 . 
 id 
 . 
 flat 
 ); 
  
 mOptions 
  
 = 
  
 findViewById 
 ( 
 R 
 . 
 id 
 . 
 custom_info_window_options 
 ); 
  
 mOptions 
 . 
 setOnCheckedChangeListener 
 ( 
 new 
  
 OnCheckedChangeListener 
 () 
  
 { 
  
 @Override 
  
 public 
  
 void 
  
 onCheckedChanged 
 ( 
 RadioGroup 
  
 group 
 , 
  
 int 
  
 checkedId 
 ) 
  
 { 
  
 if 
  
 ( 
 mLastSelectedMarker 
  
 != 
  
 null 
 && 
 mLastSelectedMarker 
 . 
 isInfoWindowShown 
 ()) 
  
 { 
  
 // Refresh the info window when the info window's content has changed. 
  
 mLastSelectedMarker 
 . 
 showInfoWindow 
 (); 
  
 } 
  
 } 
  
 }); 
  
 SupportMapFragment 
  
 mapFragment 
  
 = 
  
 ( 
 SupportMapFragment 
 ) 
  
 getSupportFragmentManager 
 (). 
 findFragmentById 
 ( 
 R 
 . 
 id 
 . 
 map 
 ); 
  
 new 
  
 OnMapAndViewReadyListener 
 ( 
 mapFragment 
 , 
  
 this 
 ); 
  
 applyInsets 
 ( 
 findViewById 
 ( 
 R 
 . 
 id 
 . 
 map_container 
 )); 
  
 } 
  
 @Override 
  
 public 
  
 void 
  
 onMapReady 
 ( 
 GoogleMap 
  
 map 
 ) 
  
 { 
  
 mMap 
  
 = 
  
 map 
 ; 
  
 // Hide the zoom controls as the button panel will cover it. 
  
 mMap 
 . 
 getUiSettings 
 (). 
 setZoomControlsEnabled 
 ( 
 false 
 ); 
  
 // Add lots of markers to the map. 
  
 addMarkersToMap 
 (); 
  
 // Setting an info window adapter allows us to change the both the contents and look of the 
  
 // info window. 
  
 mMap 
 . 
 setInfoWindowAdapter 
 ( 
 new 
  
 CustomInfoWindowAdapter 
 ()); 
  
 // Set listeners for marker events.  See the bottom of this class for their behavior. 
  
 mMap 
 . 
 setOnMarkerClickListener 
 ( 
 this 
 ); 
  
 mMap 
 . 
 setOnInfoWindowClickListener 
 ( 
 this 
 ); 
  
 mMap 
 . 
 setOnMarkerDragListener 
 ( 
 this 
 ); 
  
 mMap 
 . 
 setOnInfoWindowCloseListener 
 ( 
 this 
 ); 
  
 mMap 
 . 
 setOnInfoWindowLongClickListener 
 ( 
 this 
 ); 
  
 // Override the default content description on the view, for accessibility mode. 
  
 // Ideally this string would be localised. 
  
 mMap 
 . 
 setContentDescription 
 ( 
 "Map with lots of markers." 
 ); 
  
 LatLngBounds 
  
 bounds 
  
 = 
  
 new 
  
 LatLngBounds 
 . 
 Builder 
 () 
  
 . 
 include 
 ( 
 PERTH 
 ) 
  
 . 
 include 
 ( 
 SYDNEY 
 ) 
  
 . 
 include 
 ( 
 ADELAIDE 
 ) 
  
 . 
 include 
 ( 
 BRISBANE 
 ) 
  
 . 
 include 
 ( 
 MELBOURNE 
 ) 
  
 . 
 include 
 ( 
 DARWIN 
 ) 
  
 . 
 build 
 (); 
  
 mMap 
 . 
 moveCamera 
 ( 
 CameraUpdateFactory 
 . 
 newLatLngBounds 
 ( 
 bounds 
 , 
  
 50 
 )); 
  
 } 
  
 private 
  
 void 
  
 addMarkersToMap 
 () 
  
 { 
  
 // Uses a colored icon. 
  
 mBrisbane 
  
 = 
  
 mMap 
 . 
 addMarker 
 ( 
 new 
  
 MarkerOptions 
 () 
  
 . 
 position 
 ( 
 BRISBANE 
 ) 
  
 . 
 title 
 ( 
 "Brisbane" 
 ) 
  
 . 
 snippet 
 ( 
 "Population: 2,074,200" 
 ) 
  
 . 
 icon 
 ( 
 BitmapDescriptorFactory 
 . 
 defaultMarker 
 ( 
 BitmapDescriptorFactory 
 . 
 HUE_AZURE 
 ))); 
  
 // Uses a custom icon with the info window popping out of the center of the icon. 
  
 mSydney 
  
 = 
  
 mMap 
 . 
 addMarker 
 ( 
 new 
  
 MarkerOptions 
 () 
  
 . 
 position 
 ( 
 SYDNEY 
 ) 
  
 . 
 title 
 ( 
 "Sydney" 
 ) 
  
 . 
 snippet 
 ( 
 "Population: 4,627,300" 
 ) 
  
 . 
 icon 
 ( 
 BitmapDescriptorFactory 
 . 
 fromResource 
 ( 
 R 
 . 
 drawable 
 . 
 arrow 
 )) 
  
 . 
 infoWindowAnchor 
 ( 
 0.5f 
 , 
  
 0.5f 
 )); 
  
 // Creates a draggable marker. Long press to drag. 
  
 mMelbourne 
  
 = 
  
 mMap 
 . 
 addMarker 
 ( 
 new 
  
 MarkerOptions 
 () 
  
 . 
 position 
 ( 
 MELBOURNE 
 ) 
  
 . 
 title 
 ( 
 "Melbourne" 
 ) 
  
 . 
 snippet 
 ( 
 "Population: 4,137,400" 
 ) 
  
 . 
 draggable 
 ( 
 true 
 )); 
  
 // Place four markers on top of each other with differing z-indexes. 
  
 mDarwin1 
  
 = 
  
 mMap 
 . 
 addMarker 
 ( 
 new 
  
 MarkerOptions 
 () 
  
 . 
 position 
 ( 
 DARWIN 
 ) 
  
 . 
 title 
 ( 
 "Darwin Marker 1" 
 ) 
  
 . 
 snippet 
 ( 
 "z-index 1" 
 ) 
  
 . 
 zIndex 
 ( 
 1 
 )); 
  
 mDarwin2 
  
 = 
  
 mMap 
 . 
 addMarker 
 ( 
 new 
  
 MarkerOptions 
 () 
  
 . 
 position 
 ( 
 DARWIN 
 ) 
  
 . 
 title 
 ( 
 "Darwin Marker 2" 
 ) 
  
 . 
 snippet 
 ( 
 "z-index 2" 
 ) 
  
 . 
 zIndex 
 ( 
 2 
 )); 
  
 mDarwin3 
  
 = 
  
 mMap 
 . 
 addMarker 
 ( 
 new 
  
 MarkerOptions 
 () 
  
 . 
 position 
 ( 
 DARWIN 
 ) 
  
 . 
 title 
 ( 
 "Darwin Marker 3" 
 ) 
  
 . 
 snippet 
 ( 
 "z-index 3" 
 ) 
  
 . 
 zIndex 
 ( 
 3 
 )); 
  
 mDarwin4 
  
 = 
  
 mMap 
 . 
 addMarker 
 ( 
 new 
  
 MarkerOptions 
 () 
  
 . 
 position 
 ( 
 DARWIN 
 ) 
  
 . 
 title 
 ( 
 "Darwin Marker 4" 
 ) 
  
 . 
 snippet 
 ( 
 "z-index 4" 
 ) 
  
 . 
 zIndex 
 ( 
 4 
 )); 
  
 // A few more markers for good measure. 
  
 mPerth 
  
 = 
  
 mMap 
 . 
 addMarker 
 ( 
 new 
  
 MarkerOptions 
 () 
  
 . 
 position 
 ( 
 PERTH 
 ) 
  
 . 
 title 
 ( 
 "Perth" 
 ) 
  
 . 
 snippet 
 ( 
 "Population: 1,738,800" 
 )); 
  
 mAdelaide 
  
 = 
  
 mMap 
 . 
 addMarker 
 ( 
 new 
  
 MarkerOptions 
 () 
  
 . 
 position 
 ( 
 ADELAIDE 
 ) 
  
 . 
 title 
 ( 
 "Adelaide" 
 ) 
  
 . 
 snippet 
 ( 
 "Population: 1,213,000" 
 )); 
  
 // Vector drawable resource as a marker icon. 
  
 mMap 
 . 
 addMarker 
 ( 
 new 
  
 MarkerOptions 
 () 
  
 . 
 position 
 ( 
 ALICE_SPRINGS 
 ) 
  
 . 
 icon 
 ( 
 vectorToBitmap 
 ( 
 R 
 . 
 drawable 
 . 
 ic_android 
 , 
  
 Color 
 . 
 parseColor 
 ( 
 "#A4C639" 
 ))) 
  
 . 
 title 
 ( 
 "Alice Springs" 
 )); 
  
 // Creates a marker rainbow demonstrating how to create default marker icons of different 
  
 // hues (colors). 
  
 float 
  
 rotation 
  
 = 
  
 mRotationBar 
 . 
 getProgress 
 (); 
  
 boolean 
  
 flat 
  
 = 
  
 mFlatBox 
 . 
 isChecked 
 (); 
  
 int 
  
 numMarkersInRainbow 
  
 = 
  
 12 
 ; 
  
 for 
  
 ( 
 int 
  
 i 
  
 = 
  
 0 
 ; 
  
 i 
 < 
 numMarkersInRainbow 
 ; 
  
 i 
 ++ 
 ) 
  
 { 
  
 Marker 
  
 marker 
  
 = 
  
 mMap 
 . 
 addMarker 
 ( 
 new 
  
 MarkerOptions 
 () 
  
 . 
 position 
 ( 
 new 
  
 LatLng 
 ( 
  
 - 
 30 
  
 + 
  
 10 
  
 * 
  
 Math 
 . 
 sin 
 ( 
 i 
  
 * 
  
 Math 
 . 
 PI 
  
 / 
  
 ( 
 numMarkersInRainbow 
  
 - 
  
 1 
 )), 
  
 135 
  
 - 
  
 10 
  
 * 
  
 Math 
 . 
 cos 
 ( 
 i 
  
 * 
  
 Math 
 . 
 PI 
  
 / 
  
 ( 
 numMarkersInRainbow 
  
 - 
  
 1 
 )))) 
  
 . 
 title 
 ( 
 "Marker " 
  
 + 
  
 i 
 ) 
  
 . 
 icon 
 ( 
 BitmapDescriptorFactory 
 . 
 defaultMarker 
 ( 
 i 
  
 * 
  
 360 
  
 / 
  
 numMarkersInRainbow 
 )) 
  
 . 
 flat 
 ( 
 flat 
 ) 
  
 . 
 rotation 
 ( 
 rotation 
 )); 
  
 mMarkerRainbow 
 . 
 add 
 ( 
 marker 
 ); 
  
 } 
  
 } 
  
 /** 
 * Demonstrates converting a {@link Drawable} to a {@link BitmapDescriptor}, 
 * for use as a marker icon. 
 */ 
  
 private 
  
 BitmapDescriptor 
  
 vectorToBitmap 
 ( 
 @DrawableRes 
  
 int 
  
 id 
 , 
  
 @ColorInt 
  
 int 
  
 color 
 ) 
  
 { 
  
 Drawable 
  
 vectorDrawable 
  
 = 
  
 ResourcesCompat 
 . 
 getDrawable 
 ( 
 getResources 
 (), 
  
 id 
 , 
  
 null 
 ); 
  
 Bitmap 
  
 bitmap 
  
 = 
  
 Bitmap 
 . 
 createBitmap 
 ( 
 vectorDrawable 
 . 
 getIntrinsicWidth 
 (), 
  
 vectorDrawable 
 . 
 getIntrinsicHeight 
 (), 
  
 Bitmap 
 . 
 Config 
 . 
 ARGB_8888 
 ); 
  
 Canvas 
  
 canvas 
  
 = 
  
 new 
  
 Canvas 
 ( 
 bitmap 
 ); 
  
 vectorDrawable 
 . 
 setBounds 
 ( 
 0 
 , 
  
 0 
 , 
  
 canvas 
 . 
 getWidth 
 (), 
  
 canvas 
 . 
 getHeight 
 ()); 
  
 DrawableCompat 
 . 
 setTint 
 ( 
 vectorDrawable 
 , 
  
 color 
 ); 
  
 vectorDrawable 
 . 
 draw 
 ( 
 canvas 
 ); 
  
 return 
  
 BitmapDescriptorFactory 
 . 
 fromBitmap 
 ( 
 bitmap 
 ); 
  
 } 
  
 private 
  
 boolean 
  
 checkReady 
 () 
  
 { 
  
 if 
  
 ( 
 mMap 
  
 == 
  
 null 
 ) 
  
 { 
  
 Toast 
 . 
 makeText 
 ( 
 this 
 , 
  
 R 
 . 
 string 
 . 
 map_not_ready 
 , 
  
 Toast 
 . 
 LENGTH_SHORT 
 ). 
 show 
 (); 
  
 return 
  
 false 
 ; 
  
 } 
  
 return 
  
 true 
 ; 
  
 } 
  
 /** Called when the Clear button is clicked. */ 
  
 public 
  
 void 
  
 onClearMap 
 ( 
 View 
  
 view 
 ) 
  
 { 
  
 if 
  
 ( 
 ! 
 checkReady 
 ()) 
  
 { 
  
 return 
 ; 
  
 } 
  
 mMap 
 . 
 clear 
 (); 
  
 } 
  
 /** Called when the Reset button is clicked. */ 
  
 public 
  
 void 
  
 onResetMap 
 ( 
 View 
  
 view 
 ) 
  
 { 
  
 if 
  
 ( 
 ! 
 checkReady 
 ()) 
  
 { 
  
 return 
 ; 
  
 } 
  
 // Clear the map because we don't want duplicates of the markers. 
  
 mMap 
 . 
 clear 
 (); 
  
 addMarkersToMap 
 (); 
  
 } 
  
 /** Called when the Reset button is clicked. */ 
  
 public 
  
 void 
  
 onToggleFlat 
 ( 
 View 
  
 view 
 ) 
  
 { 
  
 if 
  
 ( 
 ! 
 checkReady 
 ()) 
  
 { 
  
 return 
 ; 
  
 } 
  
 boolean 
  
 flat 
  
 = 
  
 mFlatBox 
 . 
 isChecked 
 (); 
  
 for 
  
 ( 
 Marker 
  
 marker 
  
 : 
  
 mMarkerRainbow 
 ) 
  
 { 
  
 marker 
 . 
 setFlat 
 ( 
 flat 
 ); 
  
 } 
  
 } 
  
 @Override 
  
 public 
  
 void 
  
 onProgressChanged 
 ( 
 SeekBar 
  
 seekBar 
 , 
  
 int 
  
 progress 
 , 
  
 boolean 
  
 fromUser 
 ) 
  
 { 
  
 if 
  
 ( 
 ! 
 checkReady 
 ()) 
  
 { 
  
 return 
 ; 
  
 } 
  
 float 
  
 rotation 
  
 = 
  
 seekBar 
 . 
 getProgress 
 (); 
  
 for 
  
 ( 
 Marker 
  
 marker 
  
 : 
  
 mMarkerRainbow 
 ) 
  
 { 
  
 marker 
 . 
 setRotation 
 ( 
 rotation 
 ); 
  
 } 
  
 } 
  
 @Override 
  
 public 
  
 void 
  
 onStartTrackingTouch 
 ( 
 SeekBar 
  
 seekBar 
 ) 
  
 { 
  
 // Do nothing. 
  
 } 
  
 @Override 
  
 public 
  
 void 
  
 onStopTrackingTouch 
 ( 
 SeekBar 
  
 seekBar 
 ) 
  
 { 
  
 // Do nothing. 
  
 } 
  
 // 
  
 // Marker related listeners. 
  
 // 
  
 @Override 
  
 public 
  
 boolean 
  
 onMarkerClick 
 ( 
 final 
  
 Marker 
  
 marker 
 ) 
  
 { 
  
 if 
  
 ( 
 marker 
 . 
 equals 
 ( 
 mPerth 
 )) 
  
 { 
  
 // This causes the marker at Perth to bounce into position when it is clicked. 
  
 final 
  
 Handler 
  
 handler 
  
 = 
  
 new 
  
 Handler 
 (); 
  
 final 
  
 long 
  
 start 
  
 = 
  
 SystemClock 
 . 
 uptimeMillis 
 (); 
  
 final 
  
 long 
  
 duration 
  
 = 
  
 1500 
 ; 
  
 final 
  
 Interpolator 
  
 interpolator 
  
 = 
  
 new 
  
 BounceInterpolator 
 (); 
  
 handler 
 . 
 post 
 ( 
 new 
  
 Runnable 
 () 
  
 { 
  
 @Override 
  
 public 
  
 void 
  
 run 
 () 
  
 { 
  
 long 
  
 elapsed 
  
 = 
  
 SystemClock 
 . 
 uptimeMillis 
 () 
  
 - 
  
 start 
 ; 
  
 float 
  
 t 
  
 = 
  
 Math 
 . 
 max 
 ( 
  
 1 
  
 - 
  
 interpolator 
 . 
 getInterpolation 
 (( 
 float 
 ) 
  
 elapsed 
  
 / 
  
 duration 
 ), 
  
 0 
 ); 
  
 marker 
 . 
 setAnchor 
 ( 
 0.5f 
 , 
  
 1.0f 
  
 + 
  
 2 
  
 * 
  
 t 
 ); 
  
 if 
  
 ( 
 t 
 > 
 0.0 
 ) 
  
 { 
  
 // Post again 16ms later. 
  
 handler 
 . 
 postDelayed 
 ( 
 this 
 , 
  
 16 
 ); 
  
 } 
  
 } 
  
 }); 
  
 } 
  
 else 
  
 if 
  
 ( 
 marker 
 . 
 equals 
 ( 
 mAdelaide 
 )) 
  
 { 
  
 // This causes the marker at Adelaide to change color and alpha. 
  
 marker 
 . 
 setIcon 
 ( 
 BitmapDescriptorFactory 
 . 
 defaultMarker 
 ( 
 mRandom 
 . 
 nextFloat 
 () 
  
 * 
  
 360 
 )); 
  
 marker 
 . 
 setAlpha 
 ( 
 mRandom 
 . 
 nextFloat 
 ()); 
  
 } 
  
 // Markers have a z-index that is settable and gettable. 
  
 float 
  
 zIndex 
  
 = 
  
 marker 
 . 
 getZIndex 
 () 
  
 + 
  
 1.0f 
 ; 
  
 marker 
 . 
 setZIndex 
 ( 
 zIndex 
 ); 
  
 Toast 
 . 
 makeText 
 ( 
 this 
 , 
  
 marker 
 . 
 getTitle 
 () 
  
 + 
  
 " z-index set to " 
  
 + 
  
 zIndex 
 , 
  
 Toast 
 . 
 LENGTH_SHORT 
 ). 
 show 
 (); 
  
 mLastSelectedMarker 
  
 = 
  
 marker 
 ; 
  
 // We return false to indicate that we have not consumed the event and that we wish 
  
 // for the default behavior to occur (which is for the camera to move such that the 
  
 // marker is centered and for the marker's info window to open, if it has one). 
  
 return 
  
 false 
 ; 
  
 } 
  
 @Override 
  
 public 
  
 void 
  
 onInfoWindowClick 
 ( 
 Marker 
  
 marker 
 ) 
  
 { 
  
 Toast 
 . 
 makeText 
 ( 
 this 
 , 
  
 "Click Info Window" 
 , 
  
 Toast 
 . 
 LENGTH_SHORT 
 ). 
 show 
 (); 
  
 } 
  
 @Override 
  
 public 
  
 void 
  
 onInfoWindowClose 
 ( 
 Marker 
  
 marker 
 ) 
  
 { 
  
 //Toast.makeText(this, "Close Info Window", Toast.LENGTH_SHORT).show(); 
  
 } 
  
 @Override 
  
 public 
  
 void 
  
 onInfoWindowLongClick 
 ( 
 Marker 
  
 marker 
 ) 
  
 { 
  
 Toast 
 . 
 makeText 
 ( 
 this 
 , 
  
 "Info Window long click" 
 , 
  
 Toast 
 . 
 LENGTH_SHORT 
 ). 
 show 
 (); 
  
 } 
  
 @Override 
  
 public 
  
 void 
  
 onMarkerDragStart 
 ( 
 Marker 
  
 marker 
 ) 
  
 { 
  
 mTopText 
 . 
 setText 
 ( 
 "onMarkerDragStart" 
 ); 
  
 } 
  
 @Override 
  
 public 
  
 void 
  
 onMarkerDragEnd 
 ( 
 Marker 
  
 marker 
 ) 
  
 { 
  
 mTopText 
 . 
 setText 
 ( 
 "onMarkerDragEnd" 
 ); 
  
 } 
  
 @Override 
  
 public 
  
 void 
  
 onMarkerDrag 
 ( 
 Marker 
  
 marker 
 ) 
  
 { 
  
 mTopText 
 . 
 setText 
 ( 
 "onMarkerDrag.  Current Position: " 
  
 + 
  
 marker 
 . 
 getPosition 
 ()); 
  
 } 
 } 
  
  

Clone and run the samples

Git is required to run this sample locally. The following command clones the sample application repository.

git clone git@github.com:googlemaps-samples/android-samples.git

Import the sample project into Android Studio:

  1. In Android Studio, select File > New > Import Project.
  2. Go to the location where you saved the repository and select the project directory for Kotlin or Java:

    • Kotlin: PATH-REPO /android-samples/ApiDemos/kotlin
    • Java: PATH-REPO /android-samples/ApiDemos/java
  3. Select Open. Android Studio builds your project, using the Gradle build tool.
  4. Create a blank secrets.properties file in the same directory as your project's local.properties file. For more information about this file, see Add your API key to the project .
  5. Get an API key from your project with the Maps SDK for Android enabled .
  6. Add the following string to secrets.properties , replacing YOUR_API_KEYwith the value of your API key:

    MAPS_API_KEY= YOUR_API_KEY 
    
  7. Run the app.
Create a Mobile Website
View Site in Mobile | Classic
Share by: