diff --git a/ApiDemos/kotlin/app/build.gradle b/ApiDemos/kotlin/app/build.gradle
index d7aba0ca..f4ea3374 100644
--- a/ApiDemos/kotlin/app/build.gradle
+++ b/ApiDemos/kotlin/app/build.gradle
@@ -27,8 +27,16 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:27.0.2'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
+ // This dependency is needed to use RecyclerView, for the LiteListDemoActivity
+ implementation "com.android.support:recyclerview-v7:27.0.2"
+ // CardView is used in the LiteListDemoActivity
+ implementation 'com.android.support:cardview-v7:27.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
+ implementation 'com.google.android.gms:play-services-maps:11.8.0'
+ compile 'com.google.android.gms:play-services-location:11.8.0'
+ // EasyPermissions is needed to help us request for permission to access location
+ implementation 'pub.devrel:easypermissions:1.1.1'
}
\ No newline at end of file
diff --git a/ApiDemos/kotlin/app/src/debug/res/values/google_maps_api.xml b/ApiDemos/kotlin/app/src/debug/res/values/google_maps_api.xml
new file mode 100644
index 00000000..e2924af4
--- /dev/null
+++ b/ApiDemos/kotlin/app/src/debug/res/values/google_maps_api.xml
@@ -0,0 +1,17 @@
+
+
+
+ ADD_YOUR_KEY_HERE
+
+
diff --git a/ApiDemos/kotlin/app/src/main/AndroidManifest.xml b/ApiDemos/kotlin/app/src/main/AndroidManifest.xml
index 2d16c4c9..5ee57a1b 100644
--- a/ApiDemos/kotlin/app/src/main/AndroidManifest.xml
+++ b/ApiDemos/kotlin/app/src/main/AndroidManifest.xml
@@ -16,6 +16,9 @@
+
+
+
+
+
+
@@ -30,6 +38,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/BasicMapDemoActivity.kt b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/BasicMapDemoActivity.kt
new file mode 100644
index 00000000..fda018cf
--- /dev/null
+++ b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/BasicMapDemoActivity.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2018 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.kotlindemos
+
+import android.support.v7.app.AppCompatActivity
+import android.os.Bundle
+
+import com.google.android.gms.maps.CameraUpdateFactory
+import com.google.android.gms.maps.GoogleMap
+import com.google.android.gms.maps.OnMapReadyCallback
+import com.google.android.gms.maps.SupportMapFragment
+import com.google.android.gms.maps.model.LatLng
+import com.google.android.gms.maps.model.MarkerOptions
+
+/**
+ * This shows how to create a simple activity with a map and a marker on the map.
+ */
+class BasicMapDemoActivity :
+ AppCompatActivity(),
+ OnMapReadyCallback {
+
+ val SYDNEY = LatLng(-33.862, 151.21)
+ val ZOOM_LEVEL = 13f
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_basic_map_demo)
+ val mapFragment : SupportMapFragment? =
+ supportFragmentManager.findFragmentById(R.id.map) as? SupportMapFragment
+ mapFragment?.getMapAsync(this)
+ }
+
+ /**
+ * This is where we can add markers or lines, add listeners or move the camera. In this case,
+ * we just move the camera to Sydney and add a marker in Sydney.
+ */
+ override fun onMapReady(googleMap: GoogleMap) {
+ with(googleMap) {
+ moveCamera(CameraUpdateFactory.newLatLngZoom(SYDNEY, ZOOM_LEVEL))
+ addMarker(MarkerOptions().position(SYDNEY))
+ }
+ }
+}
diff --git a/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/CircleDemoActivity.kt b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/CircleDemoActivity.kt
new file mode 100644
index 00000000..d89851e8
--- /dev/null
+++ b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/CircleDemoActivity.kt
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2018 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.kotlindemos
+
+import android.graphics.Color
+import android.graphics.Point
+import android.location.Location
+import android.support.v7.app.AppCompatActivity
+import android.os.Bundle
+import android.view.View
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import android.widget.CheckBox
+import android.widget.SeekBar
+import android.widget.Spinner
+
+import com.google.android.gms.maps.CameraUpdateFactory
+import com.google.android.gms.maps.GoogleMap
+import com.google.android.gms.maps.OnMapReadyCallback
+import com.google.android.gms.maps.SupportMapFragment
+import com.google.android.gms.maps.model.BitmapDescriptorFactory
+import com.google.android.gms.maps.model.Circle
+import com.google.android.gms.maps.model.CircleOptions
+import com.google.android.gms.maps.model.Dash
+import com.google.android.gms.maps.model.Dot
+import com.google.android.gms.maps.model.Gap
+import com.google.android.gms.maps.model.LatLng
+import com.google.android.gms.maps.model.Marker
+import com.google.android.gms.maps.model.MarkerOptions
+import com.google.android.gms.maps.model.PatternItem
+
+import java.util.ArrayList
+import java.util.Arrays
+
+/**
+ * This shows how to draw circles on a map.
+ */
+class CircleDemoActivity :
+ AppCompatActivity(),
+ SeekBar.OnSeekBarChangeListener,
+ AdapterView.OnItemSelectedListener,
+ OnMapReadyCallback {
+
+ private val DEFAULT_RADIUS_METERS = 1000000.0
+
+ private val MAX_WIDTH_PX = 50
+ private val MAX_HUE_DEGREE = 360
+
+ private val MAX_ALPHA = 255
+ private val PATTERN_DASH_LENGTH = 100
+ private val PATTERN_GAP_LENGTH = 200
+
+ private val sydney = LatLng(-33.87365, 151.20689)
+
+ private val dot = Dot()
+ private val dash = Dash(PATTERN_DASH_LENGTH.toFloat())
+ private val gap = Gap(PATTERN_GAP_LENGTH.toFloat())
+ private val patternDotted = Arrays.asList(dot, gap)
+ private val patternDashed = Arrays.asList(dash, gap)
+ private val patternMixed = Arrays.asList(dot, gap, dot, dash, gap)
+
+ // These are the options for stroke patterns
+ private val patterns: List?>> = listOf(
+ Pair(R.string.pattern_solid, null),
+ Pair(R.string.pattern_dashed, patternDashed),
+ Pair(R.string.pattern_dotted, patternDotted),
+ Pair(R.string.pattern_mixed, patternMixed)
+ )
+
+ private lateinit var map: GoogleMap
+
+ private val circles = ArrayList(1)
+
+ private var fillColorArgb : Int = 0
+ private var strokeColorArgb: Int = 0
+
+ private lateinit var fillHueBar: SeekBar
+ private lateinit var fillAlphaBar: SeekBar
+ private lateinit var strokeWidthBar: SeekBar
+ private lateinit var strokeHueBar: SeekBar
+ private lateinit var strokeAlphaBar: SeekBar
+ private lateinit var strokePatternSpinner: Spinner
+ private lateinit var clickabilityCheckbox: CheckBox
+
+ /**
+ * This class contains information about a circle, including its markers
+ */
+ private inner class DraggableCircle(center: LatLng, private var radiusMeters: Double) {
+ private val centerMarker: Marker = map.addMarker(MarkerOptions().apply {
+ position(center)
+ draggable(true)
+ })
+
+ private val radiusMarker: Marker = map.addMarker(
+ MarkerOptions().apply {
+ position(center.getPointAtDistance(radiusMeters))
+ icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE))
+ draggable(true)
+ })
+
+ private val circle: Circle = map.addCircle(
+ CircleOptions().apply {
+ center(center)
+ radius(radiusMeters)
+ strokeWidth(strokeWidthBar.progress.toFloat())
+ strokeColor(strokeColorArgb)
+ fillColor(fillColorArgb)
+ clickable(clickabilityCheckbox.isChecked)
+ strokePattern(getSelectedPattern(strokePatternSpinner.selectedItemPosition))
+ })
+
+ fun onMarkerMoved(marker: Marker): Boolean {
+ when (marker) {
+ centerMarker -> {
+ circle.center = marker.position
+ radiusMarker.position = marker.position.getPointAtDistance(radiusMeters)
+ }
+ radiusMarker -> {
+ radiusMeters = centerMarker.position.distanceFrom(radiusMarker.position)
+ circle.radius = radiusMeters
+ }
+ else -> return false
+ }
+ return true
+ }
+
+ fun onStyleChange() {
+ with(circle) {
+ strokeWidth = strokeWidthBar.progress.toFloat()
+ strokeColor = strokeColorArgb
+ fillColor = fillColorArgb
+ }
+ }
+
+ fun setStrokePattern(pattern: List?) {
+ circle.strokePattern = pattern
+ }
+
+ fun setClickable(clickable: Boolean) {
+ circle.isClickable = clickable
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_circle_demo)
+
+ // Set all the SeekBars
+ fillHueBar = findViewById(R.id.fillHueSeekBar).apply {
+ max = MAX_HUE_DEGREE
+ progress = MAX_HUE_DEGREE / 2
+ }
+ fillAlphaBar = findViewById(R.id.fillAlphaSeekBar).apply {
+ max = MAX_ALPHA
+ progress = MAX_ALPHA / 2
+ }
+ strokeWidthBar = findViewById(R.id.strokeWidthSeekBar).apply {
+ max = MAX_WIDTH_PX
+ progress = MAX_WIDTH_PX / 3
+ }
+ strokeHueBar = findViewById(R.id.strokeHueSeekBar).apply {
+ max = MAX_HUE_DEGREE
+ progress = 0
+ }
+ strokeAlphaBar = findViewById(R.id.strokeAlphaSeekBar).apply {
+ max = MAX_ALPHA
+ progress = MAX_ALPHA
+ }
+
+ strokePatternSpinner = findViewById(R.id.strokePatternSpinner).apply {
+ adapter = ArrayAdapter(this@CircleDemoActivity,
+ android.R.layout.simple_spinner_item,
+ getResourceStrings())
+ }
+
+ clickabilityCheckbox = findViewById(R.id.toggleClickability)
+
+ val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
+ mapFragment.getMapAsync(this)
+ }
+
+ /** Get all the strings of patterns and return them as Array. */
+ private fun getResourceStrings() = (patterns).map { getString(it.first) }.toTypedArray()
+
+ /**
+ * When the map is ready, move the camera to put the Circle in the middle of the screen,
+ * create a circle in Sydney, and set the listeners for the map, circles, and SeekBars.
+ */
+ override fun onMapReady(googleMap: GoogleMap?) {
+ map = googleMap ?: return
+ // we need to initialise map before creating a circle
+ with(map) {
+ moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 4.0f))
+ setContentDescription(getString(R.string.circle_demo_details))
+ setOnMapLongClickListener { point ->
+ // We know the center, let's place the outline at a point 3/4 along the view.
+ val view: View = supportFragmentManager.findFragmentById(R.id.map).view as View
+ val radiusLatLng = map.projection.fromScreenLocation(
+ Point(view.height * 3 / 4, view.width * 3 / 4))
+ // Create the circle.
+ val newCircle = DraggableCircle(point, point.distanceFrom(radiusLatLng))
+ circles.add(newCircle)
+ }
+
+ setOnMarkerDragListener(object : GoogleMap.OnMarkerDragListener {
+ override fun onMarkerDragStart(marker: Marker) {
+ onMarkerMoved(marker)
+ }
+
+ override fun onMarkerDragEnd(marker: Marker) {
+ onMarkerMoved(marker)
+ }
+
+ override fun onMarkerDrag(marker: Marker) {
+ onMarkerMoved(marker)
+ }
+ })
+
+ // Flip the red, green and blue components of the circle's stroke color.
+ setOnCircleClickListener { c -> c.strokeColor = c.strokeColor xor 0x00ffffff }
+ }
+
+ fillColorArgb = Color.HSVToColor(fillAlphaBar.progress,
+ floatArrayOf(fillHueBar.progress.toFloat(), 1f, 1f))
+ strokeColorArgb = Color.HSVToColor(strokeAlphaBar.progress,
+ floatArrayOf(strokeHueBar.progress.toFloat(), 1f, 1f))
+
+ val circle = DraggableCircle(sydney, DEFAULT_RADIUS_METERS)
+ circles.add(circle)
+
+ // Set listeners for all the SeekBar
+ fillHueBar.setOnSeekBarChangeListener(this)
+ fillAlphaBar.setOnSeekBarChangeListener(this)
+
+ strokeWidthBar.setOnSeekBarChangeListener(this)
+ strokeHueBar.setOnSeekBarChangeListener(this)
+ strokeAlphaBar.setOnSeekBarChangeListener(this)
+
+ strokePatternSpinner.onItemSelectedListener = this
+ }
+
+ private fun getSelectedPattern(pos: Int): List? = patterns[pos].second
+
+ override fun onItemSelected(parent: AdapterView<*>, view: View, pos: Int, id: Long) {
+ if (parent.id == R.id.strokePatternSpinner) {
+ circles.map { it.setStrokePattern(getSelectedPattern(pos)) }
+ }
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>) {
+ // Don't do anything here.
+ }
+
+ override fun onStopTrackingTouch(seekBar: SeekBar) {
+ // Don't do anything here.
+ }
+
+ override fun onStartTrackingTouch(seekBar: SeekBar) {
+ // Don't do anything here.
+ }
+
+ override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
+ // Update the fillColorArgb if the SeekBars for it is changed, otherwise keep the old value
+ fillColorArgb = when (seekBar) {
+ fillHueBar -> Color.HSVToColor(Color.alpha(fillColorArgb),
+ floatArrayOf(progress.toFloat(), 1f, 1f))
+ fillAlphaBar -> Color.argb(progress, Color.red(fillColorArgb),
+ Color.green(fillColorArgb), Color.blue(fillColorArgb))
+ else -> fillColorArgb
+ }
+
+ // Set the strokeColorArgb if the SeekBars for it is changed, otherwise keep the old value
+ strokeColorArgb = when (seekBar) {
+ strokeHueBar -> Color.HSVToColor(Color.alpha(strokeColorArgb),
+ floatArrayOf(progress.toFloat(), 1f, 1f))
+ strokeAlphaBar -> Color.argb(progress, Color.red(strokeColorArgb),
+ Color.green(strokeColorArgb), Color.blue(strokeColorArgb))
+ else -> strokeColorArgb
+ }
+
+ circles.map { it.onStyleChange() }
+ }
+
+ private fun onMarkerMoved(marker: Marker) {
+ circles.forEach { if (it.onMarkerMoved(marker)) return }
+ }
+
+ /** Listener for the Clickable CheckBox, to set if all the circles can be click */
+ fun toggleClickability(view: View) {
+ circles.map { it.setClickable((view as CheckBox).isChecked) }
+ }
+}
+
+/**
+ * Extension function to find the distance from this to another LatLng object
+ */
+private fun LatLng.distanceFrom(other: LatLng): Double {
+ val result = FloatArray(1)
+ Location.distanceBetween(latitude, longitude, other.latitude, other.longitude, result)
+ return result[0].toDouble()
+}
+
+private fun LatLng.getPointAtDistance(distance: Double): LatLng {
+ val radiusOfEarth = 6371009.0
+ val radiusAngle = (Math.toDegrees(distance / radiusOfEarth)
+ / Math.cos(Math.toRadians(latitude)))
+ return LatLng(latitude, longitude + radiusAngle)
+}
\ No newline at end of file
diff --git a/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/CloseInfoWindowDemoActivity.kt b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/CloseInfoWindowDemoActivity.kt
new file mode 100644
index 00000000..f957d110
--- /dev/null
+++ b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/CloseInfoWindowDemoActivity.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2018 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.kotlindemos
+
+import android.support.v7.app.AppCompatActivity
+import android.os.Bundle
+import com.example.kotlindemos.OnMapAndViewReadyListener.OnGlobalLayoutAndMapReadyListener
+import com.google.android.gms.maps.CameraUpdateFactory
+import com.google.android.gms.maps.GoogleMap
+import com.google.android.gms.maps.SupportMapFragment
+import com.google.android.gms.maps.model.LatLng
+import com.google.android.gms.maps.model.LatLngBounds
+import com.google.android.gms.maps.model.Marker
+import com.google.android.gms.maps.model.MarkerOptions
+
+
+/**
+ * This shows how to close the info window when the currently selected marker is re-tapped.
+ */
+class CloseInfoWindowDemoActivity :
+ AppCompatActivity(),
+ OnGlobalLayoutAndMapReadyListener {
+
+ private lateinit var map: GoogleMap
+
+ /** Keeps track of the selected marker. It will be set to null if no marker is selected. */
+ private var selectedMarker: Marker? = null
+
+ /**
+ * If user tapped on the the marker which was already showing info window,
+ * the showing info window will be closed. Otherwise will show a different window.
+ */
+ private val markerClickListener = object : GoogleMap.OnMarkerClickListener {
+ override fun onMarkerClick(marker: Marker?): Boolean {
+ if (marker == selectedMarker) {
+ selectedMarker = null
+ // Return true to indicate we have consumed the event and that we do not
+ // want the 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 true
+ }
+
+ selectedMarker = marker
+ // Return false to indicate that we have not consumed the event and that
+ // we wish for the default behavior to occur.
+ return false
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_marker_close_info_window_on_retap_demo)
+
+ val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
+ OnMapAndViewReadyListener(mapFragment, this)
+ }
+
+ override fun onMapReady(googleMap: GoogleMap?) {
+ // Return if googleMap was null
+ map = googleMap ?: return
+
+ with(map) {
+ uiSettings.isZoomControlsEnabled = false
+
+ setOnMarkerClickListener(markerClickListener)
+
+ // Set listener for map click event. Any showing info window closes
+ // when the map is clicked. Clear the currently selected marker.
+ setOnMapClickListener { selectedMarker = null }
+
+ setContentDescription(getString(R.string.close_info_window_demo_details))
+
+ // Add markers to different cities in Australia and include it in bounds
+ val bounds = LatLngBounds.Builder()
+ cities.map { city ->
+ addMarker(MarkerOptions().apply {
+ position(city.latLng)
+ title(city.title)
+ snippet(city.snippet)
+ })
+ bounds.include(city.latLng)
+ }
+
+ moveCamera(CameraUpdateFactory.newLatLngBounds(bounds.build(), 50))
+ }
+ }
+
+ /**
+ * Class to contain information about a marker.
+ *
+ * @property latLng latitude and longitude of the marker
+ * @property title a string containing the city name
+ * @property snippet a string containing the population of the city
+ */
+ class MarkerInfo(val latLng: LatLng, val title: String, val snippet: String)
+
+ private val cities = listOf(
+ MarkerInfo(LatLng(-27.47093, 153.0235),
+ "Brisbane", "Population: 2,074,200"),
+ MarkerInfo(LatLng(-37.81319, 144.96298),
+ "Melbourne", "Population: 4,137,400"),
+ MarkerInfo(LatLng(-33.87365, 151.20689),
+ "Sydney", "Population: 4,627,300"),
+ MarkerInfo(LatLng(-34.92873, 138.59995),
+ "Adelaide", "Population: 1,213,000"),
+ MarkerInfo(LatLng(-31.952854, 115.857342),
+ "Perth", "Population: 1,738,800")
+ )
+}
diff --git a/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/DemoDetailsList.kt b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/DemoDetailsList.kt
index 901f7f4e..225a27ed 100644
--- a/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/DemoDetailsList.kt
+++ b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/DemoDetailsList.kt
@@ -21,6 +21,22 @@ package com.example.kotlindemos
*/
class DemoDetailsList {
companion object {
- val DEMOS = listOf()
+ val DEMOS = listOf(
+ DemoDetails(R.string.basic_demo_label, R.string.basic_demo_details,
+ BasicMapDemoActivity::class.java),
+ DemoDetails(R.string.close_info_window_demo_label,
+ R.string.close_info_window_demo_details,
+ CloseInfoWindowDemoActivity::class.java),
+ DemoDetails(R.string.circle_demo_label, R.string.circle_demo_details,
+ CircleDemoActivity::class.java),
+ DemoDetails(R.string.lite_list_demo_label, R.string.lite_list_demo_details,
+ LiteListDemoActivity::class.java),
+ DemoDetails(
+ R.string.street_view_panorama_navigation_demo_label,
+ R.string.street_view_panorama_navigation_demo_details,
+ StreetViewPanoramaNavigationDemoActivity::class.java),
+ DemoDetails(R.string.ui_settings_demo_label, R.string.ui_settings_demo_details,
+ UiSettingsDemoActivity::class.java)
+ )
}
}
\ No newline at end of file
diff --git a/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/LiteListDemoActivity.kt b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/LiteListDemoActivity.kt
new file mode 100644
index 00000000..a9f02e49
--- /dev/null
+++ b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/LiteListDemoActivity.kt
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2018 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.kotlindemos
+
+import android.os.Bundle
+import android.support.v7.app.AppCompatActivity
+import android.support.v7.widget.GridLayoutManager
+import android.support.v7.widget.LinearLayoutManager
+import android.support.v7.widget.RecyclerView
+import android.view.LayoutInflater
+import android.view.Menu
+import android.view.MenuItem
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import android.widget.Toast
+import com.google.android.gms.maps.CameraUpdateFactory
+import com.google.android.gms.maps.GoogleMap
+import com.google.android.gms.maps.MapsInitializer
+import com.google.android.gms.maps.MapView
+import com.google.android.gms.maps.OnMapReadyCallback
+import com.google.android.gms.maps.model.LatLng
+import com.google.android.gms.maps.model.MarkerOptions
+
+/**
+ * This shows to include a map in lite mode in a RecyclerView.
+ * Note the use of the view holder pattern with the
+ * [com.google.android.gms.maps.OnMapReadyCallback].
+ */
+class LiteListDemoActivity : AppCompatActivity() {
+
+ private val linearLayoutManager: LinearLayoutManager by lazy {
+ LinearLayoutManager(this)
+ }
+
+ private val gridLayoutManager: GridLayoutManager by lazy {
+ GridLayoutManager(this, 2)
+ }
+
+ private lateinit var recyclerView: RecyclerView
+ private lateinit var mapAdapter: RecyclerView.Adapter
+
+ /**
+ * RecycleListener that completely clears the [com.google.android.gms.maps.GoogleMap]
+ * attached to a row in the RecyclerView.
+ * Sets the map type to [com.google.android.gms.maps.GoogleMap.MAP_TYPE_NONE] and clears
+ * the map.
+ */
+ private val recycleListener = RecyclerView.RecyclerListener { holder ->
+ val mapHolder = holder as MapAdapter.ViewHolder
+ mapHolder.clearView()
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_lite_list_demo)
+
+ mapAdapter = MapAdapter()
+
+ // Initialise the RecyclerView.
+ recyclerView = findViewById(R.id.recycler_view).apply {
+ setHasFixedSize(true)
+ layoutManager = linearLayoutManager
+ adapter = mapAdapter
+ setRecyclerListener(recycleListener)
+ }
+ }
+
+ /** Create options menu to switch between the linear and grid layout managers. */
+ override fun onCreateOptionsMenu(menu: Menu?): Boolean {
+ menuInflater.inflate(R.menu.lite_list_menu, menu)
+ return true
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem?): Boolean {
+ recyclerView.layoutManager = when (item?.itemId) {
+ R.id.layout_linear -> linearLayoutManager
+ R.id.layout_grid -> gridLayoutManager
+ else -> return false
+ }
+ return true
+ }
+
+ /**
+ * Adapter that displays a title and [com.google.android.gms.maps.MapView] for each item.
+ * The layout is defined in `lite_list_demo_row.xml`. It contains a MapView
+ * that is programatically initialised when onCreateViewHolder is called.
+ */
+ inner class MapAdapter : RecyclerView.Adapter() {
+
+ override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
+ holder?.bindView(position) ?: return
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val inflated = LayoutInflater.from(parent.context)
+ .inflate(R.layout.lite_list_demo_row, parent, false)
+ return ViewHolder(inflated)
+ }
+
+ override fun getItemCount() = listLocations.size
+
+ /** A view holder for the map and title. */
+ inner class ViewHolder(view: View) :
+ RecyclerView.ViewHolder(view),
+ OnMapReadyCallback {
+
+ private val layout: View = view
+ private val mapView: MapView = layout.findViewById(R.id.lite_listrow_map)
+ private val title: TextView = layout.findViewById(R.id.lite_listrow_text)
+ private lateinit var map: GoogleMap
+ private lateinit var latLng: LatLng
+
+ /** Initialises the MapView by calling its lifecycle methods */
+ init {
+ with(mapView) {
+ // Initialise the MapView
+ onCreate(null)
+ // Set the map ready callback to receive the GoogleMap object
+ getMapAsync(this@ViewHolder)
+ }
+ }
+
+ private fun setMapLocation() {
+ if (!::map.isInitialized) return
+ with(map) {
+ moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 13f))
+ addMarker(MarkerOptions().position(latLng))
+ mapType = GoogleMap.MAP_TYPE_NORMAL
+ setOnMapClickListener {
+ Toast.makeText(this@LiteListDemoActivity, "Clicked on ${title.text}",
+ Toast.LENGTH_SHORT).show()
+ }
+ }
+ }
+
+ override fun onMapReady(googleMap: GoogleMap?) {
+ MapsInitializer.initialize(applicationContext)
+ // If map is not initialised properly
+ map = googleMap ?: return
+ setMapLocation()
+ }
+
+ /** This function is called when the RecyclerView wants to bind the ViewHolder. */
+ fun bindView(position: Int) {
+ listLocations[position].let {
+ latLng = it.second
+ mapView.tag = this
+ title.text = it.first
+ // We need to call setMapLocation from here because RecyclerView might use the
+ // previously loaded maps
+ setMapLocation()
+ }
+ }
+
+ /** This function is called by the recycleListener, when we need to clear the map. */
+ fun clearView() {
+ with(map) {
+ // Clear the map and free up resources by changing the map type to none
+ clear()
+ mapType = GoogleMap.MAP_TYPE_NONE
+ }
+ }
+ }
+ }
+
+ /** A list of locations of to show in the RecyclerView */
+ private val listLocations: List> = listOf(
+ Pair("Cape Town", LatLng(-33.920455, 18.466941)),
+ Pair("Beijing", LatLng(39.937795, 116.387224)),
+ Pair("Bern", LatLng(46.948020, 7.448206)),
+ Pair("Breda", LatLng(51.589256, 4.774396)),
+ Pair("Brussels", LatLng(50.854509, 4.376678)),
+ Pair("Copenhagen", LatLng(55.679423, 12.577114)),
+ Pair("Hannover", LatLng(52.372026, 9.735672)),
+ Pair("Helsinki", LatLng(60.169653, 24.939480)),
+ Pair("Hong Kong", LatLng(22.325862, 114.165532)),
+ Pair("Istanbul", LatLng(41.034435, 28.977556)),
+ Pair("Johannesburg", LatLng(-26.202886, 28.039753)),
+ Pair("Lisbon", LatLng(38.707163, -9.135517)),
+ Pair("London", LatLng(51.500208, -0.126729)),
+ Pair("Madrid", LatLng(40.420006, -3.709924)),
+ Pair("Mexico City", LatLng(19.427050, -99.127571)),
+ Pair("Moscow", LatLng(55.750449, 37.621136)),
+ Pair("New York", LatLng(40.750580, -73.993584)),
+ Pair("Oslo", LatLng(59.910761, 10.749092)),
+ Pair("Paris", LatLng(48.859972, 2.340260)),
+ Pair("Prague", LatLng(50.087811, 14.420460)),
+ Pair("Rio de Janeiro", LatLng(-22.90187, -43.232437)),
+ Pair("Rome", LatLng(41.889998, 12.500162)),
+ Pair("Sao Paolo", LatLng(-22.863878, -43.244097)),
+ Pair("Seoul", LatLng(37.560908, 126.987705)),
+ Pair("Stockholm", LatLng(59.330650, 18.067360)),
+ Pair("Sydney", LatLng(-33.873651, 151.2068896)),
+ Pair("Taipei", LatLng(25.022112, 121.478019)),
+ Pair("Tokyo", LatLng(35.670267, 139.769955)),
+ Pair("Tulsa Oklahoma", LatLng(36.149777, -95.993398)),
+ Pair("Vaduz", LatLng(47.141076, 9.521482)),
+ Pair("Vienna", LatLng(48.209206, 16.372778)),
+ Pair("Warsaw", LatLng(52.235474, 21.004057)),
+ Pair("Wellington", LatLng(-41.286480, 174.776217)),
+ Pair("Winnipeg", LatLng(49.875832, -97.150726))
+ )
+}
diff --git a/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/MainActivity.kt b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/MainActivity.kt
index 4ead271d..ad93c28a 100644
--- a/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/MainActivity.kt
+++ b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/MainActivity.kt
@@ -61,8 +61,8 @@ class MainActivity : AppCompatActivity(), AdapterView.OnItemClickListener {
class CustomArrayAdapter(context: Context, demos: List) :
ArrayAdapter(context, R.id.title, demos) {
- override fun getView(position: Int, convertView: View?, parent: ViewGroup) : View {
- val demo : DemoDetails = getItem(position)
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ val demo: DemoDetails = getItem(position)
return (convertView as? FeatureView ?: FeatureView(context)).apply {
setTitleId(demo.titleId)
setDescriptionId(demo.descriptionId)
diff --git a/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/StreetViewPanoramaNavigationDemoActivity.kt b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/StreetViewPanoramaNavigationDemoActivity.kt
new file mode 100644
index 00000000..f66e5418
--- /dev/null
+++ b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/StreetViewPanoramaNavigationDemoActivity.kt
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2018 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.kotlindemos
+
+import android.support.v7.app.AppCompatActivity
+import android.os.Bundle
+import android.view.View
+import android.widget.SeekBar
+import android.widget.Toast
+import com.google.android.gms.maps.StreetViewPanorama
+import com.google.android.gms.maps.SupportStreetViewPanoramaFragment
+import com.google.android.gms.maps.model.LatLng
+import com.google.android.gms.maps.model.StreetViewPanoramaCamera
+import com.google.android.gms.maps.model.StreetViewPanoramaLink
+
+/**
+ * This shows how to create an activity with access to all the options in Panorama
+ * which can be adjusted dynamically.
+ */
+class StreetViewPanoramaNavigationDemoActivity : AppCompatActivity() {
+
+ // George St, Sydney
+ private val sydney = LatLng(-33.87365, 151.20689)
+ // Cole St, San Francisco
+ private val sanFrancisco = LatLng(37.769263, -122.450727)
+ // Santorini, Greece using the Pano ID of the location instead of a LatLng object
+ private val santoriniPanoId = "WddsUw1geEoAAAQIt9RnsQ"
+ // LatLng with no panorama
+ private val invalid = LatLng(-45.125783, 151.276417)
+
+ // The amount in degrees by which to scroll the camera
+ private val PAN_BY_DEGREES = 30
+ // The amount of zoom
+ private val ZOOM_BY = 0.5f
+
+ private lateinit var streetViewPanorama: StreetViewPanorama
+ private lateinit var customDurationBar: SeekBar
+
+ private val duration: Long
+ get() = customDurationBar.progress.toLong()
+
+ override fun onCreate(savedInstanceState:Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_street_view_panorama_navigation_demo)
+
+ val streetViewPanoramaFragment = supportFragmentManager
+ .findFragmentById(R.id.streetviewpanorama) as SupportStreetViewPanoramaFragment
+ streetViewPanoramaFragment.getStreetViewPanoramaAsync { panorama ->
+ streetViewPanorama = panorama
+ // Only set the panorama to sydney on startup (when no panoramas have been
+ // loaded which is when the savedInstanceState is null).
+ if (savedInstanceState == null) {
+ streetViewPanorama.setPosition(sydney)
+ }
+ }
+
+ customDurationBar = findViewById(R.id.duration_bar)
+ }
+
+ /**
+ * Checks if the map is ready, the executes the provided lamdba function
+ *
+ * @param stuffToDo the code to be executed if [streetViewPanorama] is ready
+ */
+ private fun checkReadyThen(stuffToDo : () -> Unit) {
+ if (!::streetViewPanorama.isInitialized) {
+ Toast.makeText(this, R.string.map_not_ready, Toast.LENGTH_SHORT).show()
+ } else {
+ stuffToDo()
+ }
+ }
+
+ /**
+ * Called when the Go To Location button is pressed
+ */
+ fun onGoToLocation(view: View) {
+ when (view.id) {
+ R.id.sydney -> streetViewPanorama.setPosition(sydney)
+ R.id.sanfrancisco -> streetViewPanorama.setPosition(sanFrancisco)
+ R.id.santorini -> streetViewPanorama.setPosition(santoriniPanoId)
+ R.id.invalid -> streetViewPanorama.setPosition(invalid)
+ }
+ }
+
+ /**
+ * This function is called from the listeners, and builds the street view panorama with the
+ * specified arguments.
+ */
+ private fun updateStreetViewPanorama(zoom: Float, tilt: Float, bearing: Float) {
+ streetViewPanorama.animateTo(StreetViewPanoramaCamera.Builder().apply {
+ zoom(zoom)
+ tilt(tilt)
+ bearing(bearing)
+ } .build(), duration)
+ }
+
+ fun onButtonClicked(view: View) {
+ checkReadyThen {
+ with(streetViewPanorama.panoramaCamera) {
+ when (view.id) {
+ R.id.zoom_in -> updateStreetViewPanorama(zoom + ZOOM_BY, tilt, bearing)
+ R.id.zoom_out -> updateStreetViewPanorama(zoom - ZOOM_BY, tilt, bearing)
+ R.id.pan_left -> updateStreetViewPanorama(zoom, tilt, bearing - PAN_BY_DEGREES)
+ R.id.pan_right -> updateStreetViewPanorama(zoom, tilt, bearing + PAN_BY_DEGREES)
+ R.id.pan_up -> {
+ var newTilt = tilt + PAN_BY_DEGREES
+ if (newTilt > 90) newTilt = 90f
+ updateStreetViewPanorama(zoom, newTilt, bearing)
+ }
+ R.id.pan_down -> {
+ var newTilt = tilt - PAN_BY_DEGREES
+ if (newTilt < -90) newTilt = -90f
+ updateStreetViewPanorama(zoom, newTilt, bearing)
+ }
+ }
+ }
+ }
+ }
+
+ fun onRequestPosition(view: View) {
+ checkReadyThen {
+ streetViewPanorama.location?.let {
+ Toast.makeText(view.context, streetViewPanorama.location.position.toString(),
+ Toast.LENGTH_SHORT).show()
+ }
+ }
+ }
+
+ @Suppress("UNUSED_PARAMETER")
+ fun onMovePosition(view: View) {
+ val location = streetViewPanorama.location
+ val camera = streetViewPanorama.panoramaCamera
+ location?.links?.let {
+ val link = location.links.findClosestLinkToBearing(camera.bearing)
+ streetViewPanorama.setPosition(link.panoId)
+ }
+ }
+
+ /** Extension function to find the closest link from a point. */
+ private fun Array.findClosestLinkToBearing(
+ bearing: Float
+ ): StreetViewPanoramaLink {
+
+ // Find the difference between angle a and b as a value between 0 and 180.
+ val findNormalizedDifference = fun (a: Float, b: Float): Float {
+ val diff = a - b
+ val normalizedDiff = diff - (360 * Math.floor((diff / 360.0f).toDouble())).toFloat()
+ return if ((normalizedDiff < 180.0f)) normalizedDiff else 360.0f - normalizedDiff
+ }
+
+ var minBearingDiff = 360f
+ var closestLink = this[0]
+ for (link in this) {
+ if (minBearingDiff > findNormalizedDifference(bearing, link.bearing)) {
+ minBearingDiff = findNormalizedDifference(bearing, link.bearing)
+ closestLink = link
+ }
+ }
+ return closestLink
+ }
+}
diff --git a/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/UiSettingsDemoActivity.kt b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/UiSettingsDemoActivity.kt
new file mode 100644
index 00000000..1f272fea
--- /dev/null
+++ b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/UiSettingsDemoActivity.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2018 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.kotlindemos
+
+import android.Manifest
+import android.annotation.SuppressLint
+import android.support.v7.app.AppCompatActivity
+import android.os.Bundle
+import android.view.View
+import android.widget.CheckBox
+import com.google.android.gms.maps.GoogleMap
+import com.google.android.gms.maps.OnMapReadyCallback
+import com.google.android.gms.maps.SupportMapFragment
+import pub.devrel.easypermissions.AfterPermissionGranted
+import pub.devrel.easypermissions.EasyPermissions
+
+const val REQUEST_CODE_LOCATION = 123
+
+class UiSettingsDemoActivity :
+ AppCompatActivity(),
+ OnMapReadyCallback {
+
+ private lateinit var map: GoogleMap
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_ui_settings_demo)
+ val mapFragment: SupportMapFragment =
+ supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
+ mapFragment.getMapAsync(this)
+ }
+
+ override fun onMapReady(googleMap: GoogleMap?) {
+ // Return early if map is not initialised properly
+ map = googleMap ?: return
+ enableMyLocation()
+ // Set all the settings of the map to match the current state of the checkboxes
+ with(map.uiSettings) {
+ isZoomControlsEnabled = isChecked(R.id.zoom_button)
+ isCompassEnabled = isChecked(R.id.compass_button)
+ isMyLocationButtonEnabled = isChecked(R.id.myloc_button)
+ isIndoorLevelPickerEnabled = isChecked(R.id.level_button)
+ isMapToolbarEnabled = isChecked(R.id.maptoolbar_button)
+ isZoomGesturesEnabled = isChecked(R.id.zoomgest_button)
+ isScrollGesturesEnabled = isChecked(R.id.scrollgest_button)
+ isTiltGesturesEnabled = isChecked(R.id.tiltgest_button)
+ isRotateGesturesEnabled = isChecked(R.id.rotategest_button)
+ }
+ }
+
+ /** On click listener for checkboxes */
+ fun onClick(view: View) {
+ if (view !is CheckBox) {
+ return
+ }
+ val isChecked: Boolean = view.isChecked
+ with(map.uiSettings) {
+ when (view.id) {
+ R.id.zoom_button -> isZoomControlsEnabled = isChecked
+ R.id.compass_button -> isCompassEnabled = isChecked
+ R.id.myloc_button -> isMyLocationButtonEnabled = isChecked
+ R.id.level_button -> isIndoorLevelPickerEnabled = isChecked
+ R.id.maptoolbar_button -> isMapToolbarEnabled = isChecked
+ R.id.zoomgest_button -> isZoomGesturesEnabled = isChecked
+ R.id.scrollgest_button -> isScrollGesturesEnabled = isChecked
+ R.id.tiltgest_button -> isTiltGesturesEnabled = isChecked
+ R.id.rotategest_button -> isRotateGesturesEnabled = isChecked
+ }
+ }
+ }
+
+ /** Returns whether the checkbox with the given id is checked */
+ private fun isChecked(id: Int) = findViewById(id)?.isChecked ?: false
+
+ /** Override the onRequestPermissionResult to use EasyPermissions */
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array,
+ grantResults: IntArray
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this)
+ }
+
+ /**
+ * enableMyLocation() will enable the location of the map if the user has given permission
+ * for the app to access their device location.
+ * Android Studio requires an explicit check before setting map.isMyLocationEnabled to true
+ * but we are using EasyPermissions to handle it so we can suppress the "MissingPermission"
+ * check.
+ */
+ @SuppressLint("MissingPermission")
+ @AfterPermissionGranted(REQUEST_CODE_LOCATION)
+ private fun enableMyLocation() {
+ if (hasLocationPermission()) {
+ map.isMyLocationEnabled = true
+ } else {
+ EasyPermissions.requestPermissions(
+ this,
+ getString(R.string.location),
+ REQUEST_CODE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION
+ )
+ }
+ }
+
+ private fun hasLocationPermission(): Boolean {
+ return EasyPermissions.hasPermissions(this, Manifest.permission.ACCESS_FINE_LOCATION)
+ }
+}
diff --git a/ApiDemos/kotlin/app/src/main/res/layout/activity_basic_map_demo.xml b/ApiDemos/kotlin/app/src/main/res/layout/activity_basic_map_demo.xml
new file mode 100644
index 00000000..17225bd4
--- /dev/null
+++ b/ApiDemos/kotlin/app/src/main/res/layout/activity_basic_map_demo.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
diff --git a/ApiDemos/kotlin/app/src/main/res/layout/activity_circle_demo.xml b/ApiDemos/kotlin/app/src/main/res/layout/activity_circle_demo.xml
new file mode 100644
index 00000000..6b7c3c91
--- /dev/null
+++ b/ApiDemos/kotlin/app/src/main/res/layout/activity_circle_demo.xml
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ApiDemos/kotlin/app/src/main/res/layout/activity_lite_list_demo.xml b/ApiDemos/kotlin/app/src/main/res/layout/activity_lite_list_demo.xml
new file mode 100644
index 00000000..949d8ebf
--- /dev/null
+++ b/ApiDemos/kotlin/app/src/main/res/layout/activity_lite_list_demo.xml
@@ -0,0 +1,22 @@
+
+
+
diff --git a/ApiDemos/kotlin/app/src/main/res/layout/activity_marker_close_info_window_on_retap_demo.xml b/ApiDemos/kotlin/app/src/main/res/layout/activity_marker_close_info_window_on_retap_demo.xml
new file mode 100644
index 00000000..027d9c8f
--- /dev/null
+++ b/ApiDemos/kotlin/app/src/main/res/layout/activity_marker_close_info_window_on_retap_demo.xml
@@ -0,0 +1,25 @@
+
+
+
+
diff --git a/ApiDemos/kotlin/app/src/main/res/layout/activity_street_view_panorama_navigation_demo.xml b/ApiDemos/kotlin/app/src/main/res/layout/activity_street_view_panorama_navigation_demo.xml
new file mode 100644
index 00000000..58f7425b
--- /dev/null
+++ b/ApiDemos/kotlin/app/src/main/res/layout/activity_street_view_panorama_navigation_demo.xml
@@ -0,0 +1,191 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ApiDemos/kotlin/app/src/main/res/layout/activity_ui_settings_demo.xml b/ApiDemos/kotlin/app/src/main/res/layout/activity_ui_settings_demo.xml
new file mode 100644
index 00000000..23bb84a6
--- /dev/null
+++ b/ApiDemos/kotlin/app/src/main/res/layout/activity_ui_settings_demo.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ApiDemos/kotlin/app/src/main/res/layout/lite_list_demo_row.xml b/ApiDemos/kotlin/app/src/main/res/layout/lite_list_demo_row.xml
new file mode 100644
index 00000000..bb4c56ab
--- /dev/null
+++ b/ApiDemos/kotlin/app/src/main/res/layout/lite_list_demo_row.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ApiDemos/kotlin/app/src/main/res/menu/lite_list_menu.xml b/ApiDemos/kotlin/app/src/main/res/menu/lite_list_menu.xml
new file mode 100644
index 00000000..8da00b94
--- /dev/null
+++ b/ApiDemos/kotlin/app/src/main/res/menu/lite_list_menu.xml
@@ -0,0 +1,30 @@
+
+
+
\ No newline at end of file
diff --git a/ApiDemos/kotlin/app/src/main/res/values/colors.xml b/ApiDemos/kotlin/app/src/main/res/values/colors.xml
index 3ab3e9cb..5169d545 100644
--- a/ApiDemos/kotlin/app/src/main/res/values/colors.xml
+++ b/ApiDemos/kotlin/app/src/main/res/values/colors.xml
@@ -3,4 +3,5 @@
#3F51B5#303F9F#FF4081
+ #D0FFFFFF
diff --git a/ApiDemos/kotlin/app/src/main/res/values/strings.xml b/ApiDemos/kotlin/app/src/main/res/values/strings.xml
index 22db8efe..ca224aeb 100644
--- a/ApiDemos/kotlin/app/src/main/res/values/strings.xml
+++ b/ApiDemos/kotlin/app/src/main/res/values/strings.xml
@@ -18,4 +18,67 @@
Google Maps API DemosNo demosGoogle Play services is not installed on this device.
+
+
+ Basic Map
+ Launches a map with marker pointing at Sydney.
+
+
+ Circle Demo
+ Demonstrate how to add circles to a map
+ Properties for Circle(s)
+
+
+ Lite List Demo
+ Show a list of Lite Map of different locations using RecyclerView with LinearLayoutManager and GridLayoutManager
+ Linear
+ Grid
+
+
+ Close Info Window Demo
+ Demonstrates how to close the info window when the currently selected marker is retapped.
+
+
+ Clickable
+ Fill Alpha
+ Fill Hue
+ Bevel
+ Default
+ Round
+ Dashed
+ Dotted
+ Mixed
+ Solid
+ Demonstrates how to add Polygons to a map.
+ Demonstrates how to add Polygons to a map
+ Polygons
+ Properties for Polygon over Australia
+ Stroke Alpha
+ Stroke Hue
+ Stroke Joint Type
+ Stroke Pattern
+ Stroke Width
+
+
+ Street View Panorama Navigation Demo
+ Street View Panorama with programmatic navigation
+ Position
+ Walk
+ Go to Invalid Point
+ Go to San Francisco
+ Go to Santorini
+
+
+ UI Settings Demo
+ Demonstrate how to toggle the UI of a map
+ Location permission is required to run the demo
+ Zoom
+ Compass
+ My Location
+ Level Picker
+ Map Toolbar
+ Zoom Gestures
+ Scroll Gestures
+ Tilt Gestures
+ Rotate Gestures
\ No newline at end of file