From e04aca2f793f4d4ff3e02116049b6a541fad8e8f Mon Sep 17 00:00:00 2001
From: Dale Hawkins <107309+dkhawk@users.noreply.github.com>
Date: Thu, 20 Aug 2026 12:01:52 -0600
Subject: [PATCH] feat(samples): add Cloud-Based Map Styling demo and visual
tests
---
.../res/layout/activity_cloud_styling.xml | 133 ++++++++++++++++++
.../layout/control_panel_cloud_styling.xml | 82 +++++++++++
.../maps3djava/CloudStylingVisualTest.java | 79 +++++++++++
.../cloudstyling/CloudStylingActivity.java | 85 ++++++++++-
.../maps3dkotlin/CloudStylingVisualTest.kt | 82 +++++++++++
.../cloudstyling/CloudStylingActivity.kt | 73 +++++++++-
.../ComposeDemos/app/build.gradle.kts | 8 +-
.../com/example/composedemos/MainActivity.kt | 5 +
.../cloudstyling/CloudStylingActivity.kt | 81 ++++++++---
maps3d-compose-demo/build.gradle.kts | 8 +-
maps3d-compose/build.gradle.kts | 8 +-
.../maps/android/compose3d/Map3DState.kt | 24 +++-
.../maps/android/compose3d/utils/Units.kt | 8 +-
.../maps/android/compose3d/utils/Utilities.kt | 5 +-
snippets/build.gradle.kts | 8 +-
.../example/snippets/kotlin/MapActivity.kt | 10 +-
.../snippets/kotlin/SnippetRegistry.kt | 27 +++-
.../example/snippets/kotlin/TrackedMap3D.kt | 5 +-
.../kotlin/annotations/SnippetGroup.kt | 5 +-
.../kotlin/annotations/SnippetItem.kt | 5 +-
20 files changed, 678 insertions(+), 63 deletions(-)
create mode 100644 Maps3DSamples/ApiDemos/common/src/main/res/layout/activity_cloud_styling.xml
create mode 100644 Maps3DSamples/ApiDemos/common/src/main/res/layout/control_panel_cloud_styling.xml
create mode 100644 Maps3DSamples/ApiDemos/java-app/src/androidTest/java/com/example/maps3djava/CloudStylingVisualTest.java
create mode 100644 Maps3DSamples/ApiDemos/kotlin-app/src/androidTest/java/com/example/maps3dkotlin/CloudStylingVisualTest.kt
diff --git a/Maps3DSamples/ApiDemos/common/src/main/res/layout/activity_cloud_styling.xml b/Maps3DSamples/ApiDemos/common/src/main/res/layout/activity_cloud_styling.xml
new file mode 100644
index 00000000..61ebe477
--- /dev/null
+++ b/Maps3DSamples/ApiDemos/common/src/main/res/layout/activity_cloud_styling.xml
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Maps3DSamples/ApiDemos/common/src/main/res/layout/control_panel_cloud_styling.xml b/Maps3DSamples/ApiDemos/common/src/main/res/layout/control_panel_cloud_styling.xml
new file mode 100644
index 00000000..ec83a2bd
--- /dev/null
+++ b/Maps3DSamples/ApiDemos/common/src/main/res/layout/control_panel_cloud_styling.xml
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Maps3DSamples/ApiDemos/java-app/src/androidTest/java/com/example/maps3djava/CloudStylingVisualTest.java b/Maps3DSamples/ApiDemos/java-app/src/androidTest/java/com/example/maps3djava/CloudStylingVisualTest.java
new file mode 100644
index 00000000..c20904d3
--- /dev/null
+++ b/Maps3DSamples/ApiDemos/java-app/src/androidTest/java/com/example/maps3djava/CloudStylingVisualTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2026 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
+ *
+ * http://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.maps3djava;
+
+import static org.junit.Assert.assertTrue;
+
+import android.content.Intent;
+import android.graphics.Bitmap;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.Until;
+
+import com.example.maps3djava.cloudstyling.CloudStylingActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * A premium visual regression test for the View-based Java Cloud-Based Map Styling sample.
+ *
+ * Demonstrates robust programmatic testing of custom cloud-styled 3D map features by launching the Java-based
+ * [CloudStylingActivity], waiting for cloud-styled map tiles over San Francisco to load, capturing a screenshot of the
+ * active map scene, and verifying visual correctness using the Gemini API.
+ */
+@RunWith(AndroidJUnit4.class)
+public class CloudStylingVisualTest extends BaseVisualTest {
+
+ @Test
+ public void verifyCloudStylingRenders() {
+ // Launch CloudStylingActivity
+ Intent intent = new Intent(context, CloudStylingActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+
+ // Wait for the activity to be displayed in the foreground
+ uiDevice.wait(Until.hasObject(By.pkg(context.getPackageName()).depth(0)), 10000);
+
+ // Wait for Cloud-styled 3D map tiles to render and feature styling to settle
+ waitForMapRendering(15);
+
+ // Capture high-resolution screenshot of the active 3D map scene
+ Bitmap screenshotBitmap = captureScreenshot("cloud_styling_screenshot.png");
+
+ // Define the verification prompt for the visual testing agent
+ String prompt = "Please act as a UI tester and analyze this screenshot.\n" +
+ "1. Confirm that a 3D map view is visible over San Francisco.\n" +
+ "2. Confirm that custom cloud-based stylized map tiles / elements are displayed on the 3D map scene.\n" +
+ "3. Confirm that the Map Mode selector card (with radio options for Roadmap, Hybrid, and Satellite) is visible at the bottom of the screen.\n" +
+ "\n" +
+ "If and ONLY IF you can clearly see the 3D Cloud-styled map view and bottom Map Mode selection card, reply with \"PASSED\".\n" +
+ "If you cannot see the 3D map scene or control card, reply with \"FAILED: 3D map scene or Map Mode controls not visible\".\n" +
+ "Report what you see in detail.";
+
+ // Analyze the image using Gemini (using blocking wrapper)
+ String geminiResponse = helper.analyzeImageBlocking(screenshotBitmap, prompt, geminiApiKey);
+ System.out.println("Gemini's analysis: " + geminiResponse);
+
+ // Assert on Gemini's response
+ assertTrue(
+ "Visual verification failed. Gemini response: " + geminiResponse,
+ geminiResponse != null && geminiResponse.toUpperCase().contains("PASSED")
+ );
+ }
+}
diff --git a/Maps3DSamples/ApiDemos/java-app/src/main/java/com/example/maps3djava/cloudstyling/CloudStylingActivity.java b/Maps3DSamples/ApiDemos/java-app/src/main/java/com/example/maps3djava/cloudstyling/CloudStylingActivity.java
index 6997460a..a8599bed 100644
--- a/Maps3DSamples/ApiDemos/java-app/src/main/java/com/example/maps3djava/cloudstyling/CloudStylingActivity.java
+++ b/Maps3DSamples/ApiDemos/java-app/src/main/java/com/example/maps3djava/cloudstyling/CloudStylingActivity.java
@@ -16,15 +16,88 @@
package com.example.maps3djava.cloudstyling;
+import static com.example.maps3d.common.UtilitiesKt.toValidCamera;
+
+import android.os.Bundle;
+import android.widget.RadioGroup;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.example.maps3dcommon.R;
-import com.example.maps3djava.common.BaseSkeletonActivity;
+import com.example.maps3djava.sampleactivity.SampleBaseActivity;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps3d.GoogleMap3D;
+import com.google.android.gms.maps3d.model.Camera;
+import com.google.android.gms.maps3d.model.LatLngAltitude;
+import com.google.android.gms.maps3d.model.Map3DMode;
+import com.google.android.material.appbar.MaterialToolbar;
/**
- * Skeleton activity for CloudStylingActivity.
+ * Showcases **Cloud-Based Map Styling** in Google Maps 3D SDK (Java implementation). Uses
+ * standalone layout [R.layout.activity_cloud_styling] with declarative custom Map ID.
*/
-public class CloudStylingActivity extends BaseSkeletonActivity {
- @Override
- protected int getTitleResId() {
- return R.string.feature_title_cloud_styling;
+public class CloudStylingActivity extends SampleBaseActivity {
+
+ public static final LatLng SF_LOCATION = new LatLng(37.7915, -122.4010);
+
+ private int currentMapMode = Map3DMode.ROADMAP;
+
+ @NonNull
+ @Override
+ public String getTAG() {
+ return getClass().getSimpleName();
+ }
+
+ @NonNull
+ @Override
+ public Camera getInitialCamera() {
+ return toValidCamera(new Camera(
+ new LatLngAltitude(SF_LOCATION.latitude, SF_LOCATION.longitude, 250.0),
+ 45.0,
+ 65.0,
+ 0.0,
+ 800.0
+ ));
+ }
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Set dedicated standalone layout with declarative mapId="9a35234a36da44d2c47bf626"
+ setContentView(R.layout.activity_cloud_styling);
+
+ MaterialToolbar topBar = findViewById(R.id.top_bar);
+ if (topBar != null) {
+ topBar.setTitle(R.string.feature_title_cloud_styling);
+ topBar.setNavigationOnClickListener(v -> finish());
+ }
+
+ map3DView = findViewById(R.id.map3dView);
+ if (map3DView != null) {
+ map3DView.onCreate(savedInstanceState);
+ map3DView.getMap3DViewAsync(this);
}
+
+ RadioGroup rgMapMode = findViewById(R.id.rg_map_mode);
+ if (rgMapMode != null) {
+ rgMapMode.setOnCheckedChangeListener((group, checkedId) -> {
+ int newMode = Map3DMode.ROADMAP;
+ if (checkedId == R.id.rb_hybrid) {
+ newMode = Map3DMode.HYBRID;
+ } else if (checkedId == R.id.rb_satellite) {
+ newMode = Map3DMode.SATELLITE;
+ }
+ currentMapMode = newMode;
+ if (googleMap3D != null) {
+ googleMap3D.setMapMode(newMode);
+ }
+ });
+ }
+ }
+
+ @Override
+ public void onMap3DViewReady(@NonNull GoogleMap3D googleMap3D) {
+ super.onMap3DViewReady(googleMap3D);
+ googleMap3D.setMapMode(currentMapMode);
+ }
}
diff --git a/Maps3DSamples/ApiDemos/kotlin-app/src/androidTest/java/com/example/maps3dkotlin/CloudStylingVisualTest.kt b/Maps3DSamples/ApiDemos/kotlin-app/src/androidTest/java/com/example/maps3dkotlin/CloudStylingVisualTest.kt
new file mode 100644
index 00000000..e83306ce
--- /dev/null
+++ b/Maps3DSamples/ApiDemos/kotlin-app/src/androidTest/java/com/example/maps3dkotlin/CloudStylingVisualTest.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2026 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
+ *
+ * http://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.maps3dkotlin
+
+import android.content.Intent
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.Until
+import com.example.maps3dkotlin.cloudstyling.CloudStylingActivity
+import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * A premium visual regression test for the View-based Kotlin Cloud-Based Map Styling sample.
+ *
+ * This test automates launching the [CloudStylingActivity], waiting for cloud-styled 3D map tiles configured via custom
+ * Map ID over San Francisco to initialize, capturing a screenshot of the live rendering scene, and verifying visual
+ * correctness using the Gemini API.
+ */
+@RunWith(AndroidJUnit4::class)
+class CloudStylingVisualTest : BaseVisualTest() {
+
+ @Test
+ fun verifyCloudStylingRenders() {
+ runBlocking {
+ // Launch CloudStylingActivity
+ val intent = Intent(context, CloudStylingActivity::class.java).apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ }
+ context.startActivity(intent)
+
+ // Wait for the activity to be displayed in the foreground
+ uiDevice.wait(Until.hasObject(By.pkg(context.packageName).depth(0)), 10000)
+
+ // Wait for Cloud-styled 3D map tiles to render and feature styling to settle
+ waitForMapRendering(15)
+
+ // Capture high-resolution screenshot of the active 3D map scene
+ val screenshotBitmap = captureScreenshot("cloud_styling_screenshot.png")
+
+ // Define the verification prompt for the visual testing agent
+ val prompt = """
+ Please act as a UI tester and analyze this screenshot.
+ 1. Confirm that a 3D map view is visible over San Francisco.
+ 2. Confirm that custom cloud-based stylized map tiles / elements are displayed on the 3D map scene.
+ 3. Confirm that the Map Mode selector card (with radio options for Roadmap, Hybrid, and Satellite) is visible at the bottom of the screen.
+
+ If and ONLY IF you can clearly see the 3D Cloud-styled map view and bottom Map Mode selection card, reply with "PASSED".
+ If you cannot see the 3D map scene or control card, reply with "FAILED: 3D map scene or Map Mode controls not visible".
+ Report what you see in detail.
+ """.trimIndent()
+
+ // Analyze the image using Gemini
+ val geminiResponse = helper.analyzeImage(screenshotBitmap, prompt, geminiApiKey)
+ println("Gemini's analysis: ${'$'}geminiResponse")
+
+ // Assert on Gemini's response
+ assertTrue(
+ "Visual verification failed. Gemini response: ${'$'}geminiResponse",
+ geminiResponse?.contains("PASSED", ignoreCase = true) == true
+ )
+ }
+ }
+}
diff --git a/Maps3DSamples/ApiDemos/kotlin-app/src/main/java/com/example/maps3dkotlin/cloudstyling/CloudStylingActivity.kt b/Maps3DSamples/ApiDemos/kotlin-app/src/main/java/com/example/maps3dkotlin/cloudstyling/CloudStylingActivity.kt
index 4584108f..7c713ceb 100644
--- a/Maps3DSamples/ApiDemos/kotlin-app/src/main/java/com/example/maps3dkotlin/cloudstyling/CloudStylingActivity.kt
+++ b/Maps3DSamples/ApiDemos/kotlin-app/src/main/java/com/example/maps3dkotlin/cloudstyling/CloudStylingActivity.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2025 Google LLC
+ * Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,14 +16,75 @@
package com.example.maps3dkotlin.cloudstyling
+import android.os.Bundle
+import android.widget.RadioGroup
+import androidx.activity.enableEdgeToEdge
+import com.example.maps3d.common.toValidCamera
import com.example.maps3dcommon.R
-import com.example.maps3dkotlin.common.BaseSkeletonActivity
+import com.example.maps3dkotlin.sampleactivity.SampleBaseActivity
+import com.google.android.gms.maps.model.LatLng
+import com.google.android.gms.maps3d.GoogleMap3D
+import com.google.android.gms.maps3d.Map3DView
+import com.google.android.gms.maps3d.model.Camera
+import com.google.android.gms.maps3d.model.Map3DMode
+import com.google.android.gms.maps3d.model.camera
+import com.google.android.gms.maps3d.model.latLngAltitude
+import com.google.android.material.appbar.MaterialToolbar
/**
- * Skeleton activity for CloudStylingActivity.
+ * Showcases **Cloud-Based Map Styling** in Google Maps 3D SDK.
+ * Uses standalone layout [R.layout.activity_cloud_styling] with declarative custom Map ID.
*/
-class CloudStylingActivity : BaseSkeletonActivity() {
- override fun getTitleResId(): Int {
- return R.string.feature_title_cloud_styling
+class CloudStylingActivity : SampleBaseActivity() {
+
+ override val TAG: String = this::class.java.simpleName
+
+ override val initialCamera: Camera = camera {
+ center = latLngAltitude {
+ latitude = SF_LOCATION.latitude
+ longitude = SF_LOCATION.longitude
+ altitude = 250.0
+ }
+ heading = 45.0
+ tilt = 65.0
+ range = 800.0
+ }.toValidCamera()
+
+ @Map3DMode
+ private var currentMapMode: Int = Map3DMode.ROADMAP
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ enableEdgeToEdge()
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_cloud_styling)
+
+ findViewById(R.id.top_bar)?.apply {
+ title = getString(R.string.feature_title_cloud_styling)
+ setNavigationOnClickListener { finish() }
+ }
+
+ map3DView = findViewById(R.id.map3dView).apply {
+ onCreate(savedInstanceState)
+ getMap3DViewAsync(this@CloudStylingActivity)
+ }
+
+ findViewById(R.id.rg_map_mode)?.setOnCheckedChangeListener { _, checkedId ->
+ val newMode = when (checkedId) {
+ R.id.rb_hybrid -> Map3DMode.HYBRID
+ R.id.rb_satellite -> Map3DMode.SATELLITE
+ else -> Map3DMode.ROADMAP
+ }
+ currentMapMode = newMode
+ googleMap3D?.setMapMode(newMode)
+ }
+ }
+
+ override fun onMapReady(googleMap3D: GoogleMap3D) {
+ super.onMapReady(googleMap3D)
+ googleMap3D.setMapMode(currentMapMode)
+ }
+
+ companion object {
+ val SF_LOCATION = LatLng(37.7915, -122.4010)
}
}
diff --git a/Maps3DSamples/ComposeDemos/app/build.gradle.kts b/Maps3DSamples/ComposeDemos/app/build.gradle.kts
index 0aa16053..e552bfde 100644
--- a/Maps3DSamples/ComposeDemos/app/build.gradle.kts
+++ b/Maps3DSamples/ComposeDemos/app/build.gradle.kts
@@ -25,7 +25,13 @@ plugins {
configure {
kotlin {
target("**/*.kt")
- ktlint().editorConfigOverride(mapOf("indent_size" to "4", "ktlint_function_naming_ignore_when_annotated_with" to "Composable"))
+ ktlint().editorConfigOverride(
+ mapOf(
+ "indent_size" to "4",
+ "ktlint_function_naming_ignore_when_annotated_with" to "Composable",
+ "ktlint_standard_max-line-length" to "disabled",
+ ),
+ )
trimTrailingWhitespace()
endWithNewline()
}
diff --git a/Maps3DSamples/ComposeDemos/app/src/main/java/com/example/composedemos/MainActivity.kt b/Maps3DSamples/ComposeDemos/app/src/main/java/com/example/composedemos/MainActivity.kt
index 5e475d91..b9705841 100644
--- a/Maps3DSamples/ComposeDemos/app/src/main/java/com/example/composedemos/MainActivity.kt
+++ b/Maps3DSamples/ComposeDemos/app/src/main/java/com/example/composedemos/MainActivity.kt
@@ -207,6 +207,11 @@ fun CatalogScreen() {
context.startActivity(Intent(context, FieldOfViewActivity::class.java))
}
}
+ item {
+ SampleItem("Cloud Map Styling") {
+ context.startActivity(Intent(context, CloudStylingActivity::class.java))
+ }
+ }
}
}
diff --git a/Maps3DSamples/ComposeDemos/app/src/main/java/com/example/composedemos/cloudstyling/CloudStylingActivity.kt b/Maps3DSamples/ComposeDemos/app/src/main/java/com/example/composedemos/cloudstyling/CloudStylingActivity.kt
index 802b7f50..ac803e86 100644
--- a/Maps3DSamples/ComposeDemos/app/src/main/java/com/example/composedemos/cloudstyling/CloudStylingActivity.kt
+++ b/Maps3DSamples/ComposeDemos/app/src/main/java/com/example/composedemos/cloudstyling/CloudStylingActivity.kt
@@ -24,13 +24,18 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Scaffold
-import androidx.compose.material3.Text
-import androidx.compose.ui.Alignment
+import androidx.compose.material3.Surface
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
-import androidx.core.view.WindowCompat
-import androidx.core.view.WindowInsetsCompat
-import androidx.core.view.WindowInsetsControllerCompat
+import com.google.android.gms.maps.model.LatLng
+import com.google.android.gms.maps3d.Map3DInitConfig
+import com.google.android.gms.maps3d.model.Map3DMode
+import com.google.android.gms.maps3d.model.camera
+import com.google.android.gms.maps3d.model.latLngAltitude
+import com.google.maps.android.compose3d.GoogleMap3D
class CloudStylingActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
@@ -38,20 +43,60 @@ class CloudStylingActivity : ComponentActivity() {
enableEdgeToEdge()
setContent {
MaterialTheme {
- Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
- Box(
- modifier = Modifier
- .fillMaxSize()
- .padding(innerPadding),
- contentAlignment = Alignment.Center,
- ) {
- Text(
- text = "TODO: Cloud Map Styling sample will be implemented here.",
- style = MaterialTheme.typography.headlineSmall,
- )
- }
+ Surface(
+ modifier = Modifier.fillMaxSize(),
+ color = MaterialTheme.colorScheme.background,
+ ) {
+ CloudStylingScreen()
}
}
}
}
}
+
+@Composable
+fun CloudStylingScreen() {
+ val initialLocation = LatLng(37.7915, -122.4010)
+ val currentCameraState by remember {
+ mutableStateOf(
+ camera {
+ center = latLngAltitude {
+ latitude = initialLocation.latitude
+ longitude = initialLocation.longitude
+ altitude = 250.0
+ }
+ heading = 45.0
+ tilt = 65.0
+ range = 800.0
+ },
+ )
+ }
+
+ Box(modifier = Modifier.fillMaxSize()) {
+ GoogleMap3D(
+ camera = currentCameraState,
+ mapMode = Map3DMode.ROADMAP,
+ options = Map3DInitConfig.create(
+ centerLat = initialLocation.latitude,
+ centerLng = initialLocation.longitude,
+ centerAlt = 0.0,
+ heading = 45.0,
+ tilt = 65.0,
+ roll = 0.0,
+ range = 800.0,
+ minAltitude = 0.0,
+ maxAltitude = 1000000.0,
+ minHeading = 0.0,
+ maxHeading = 360.0,
+ minTilt = 0.0,
+ maxTilt = 90.0,
+ bounds = null,
+ mapMode = Map3DMode.ROADMAP,
+ mapId = "9a35234a36da44d2c47bf626",
+ language = java.util.Locale.getDefault().language,
+ region = java.util.Locale.getDefault().country,
+ ),
+ modifier = Modifier.fillMaxSize(),
+ )
+ }
+}
diff --git a/maps3d-compose-demo/build.gradle.kts b/maps3d-compose-demo/build.gradle.kts
index a1ee2461..f450ae7d 100644
--- a/maps3d-compose-demo/build.gradle.kts
+++ b/maps3d-compose-demo/build.gradle.kts
@@ -25,7 +25,13 @@ plugins {
configure {
kotlin {
target("**/*.kt")
- ktlint().editorConfigOverride(mapOf("indent_size" to "4", "ktlint_function_naming_ignore_when_annotated_with" to "Composable"))
+ ktlint().editorConfigOverride(
+ mapOf(
+ "indent_size" to "4",
+ "ktlint_function_naming_ignore_when_annotated_with" to "Composable",
+ "ktlint_standard_max-line-length" to "disabled",
+ ),
+ )
trimTrailingWhitespace()
endWithNewline()
}
diff --git a/maps3d-compose/build.gradle.kts b/maps3d-compose/build.gradle.kts
index 8db06bc1..84c6fdfb 100644
--- a/maps3d-compose/build.gradle.kts
+++ b/maps3d-compose/build.gradle.kts
@@ -24,7 +24,13 @@ plugins {
configure {
kotlin {
target("**/*.kt")
- ktlint().editorConfigOverride(mapOf("indent_size" to "4", "ktlint_function_naming_ignore_when_annotated_with" to "Composable"))
+ ktlint().editorConfigOverride(
+ mapOf(
+ "indent_size" to "4",
+ "ktlint_function_naming_ignore_when_annotated_with" to "Composable",
+ "ktlint_standard_max-line-length" to "disabled",
+ ),
+ )
trimTrailingWhitespace()
endWithNewline()
}
diff --git a/maps3d-compose/src/main/java/com/google/maps/android/compose3d/Map3DState.kt b/maps3d-compose/src/main/java/com/google/maps/android/compose3d/Map3DState.kt
index 11539222..85695a52 100644
--- a/maps3d-compose/src/main/java/com/google/maps/android/compose3d/Map3DState.kt
+++ b/maps3d-compose/src/main/java/com/google/maps/android/compose3d/Map3DState.kt
@@ -85,7 +85,11 @@ class Map3DState {
}
}
- private fun createMarker(map: GoogleMap3D, config: MarkerConfig, overrideId: String? = null): Marker? {
+ private fun createMarker(
+ map: GoogleMap3D,
+ config: MarkerConfig,
+ overrideId: String? = null,
+ ): Marker? {
val marker = map.addMarker(config.toMarkerOptions(overrideId))
config.onClick?.let { callback ->
marker?.setClickListener {
@@ -129,7 +133,11 @@ class Map3DState {
}
}
- private fun createPolyline(map: GoogleMap3D, config: PolylineConfig, overrideId: String? = null): Polyline {
+ private fun createPolyline(
+ map: GoogleMap3D,
+ config: PolylineConfig,
+ overrideId: String? = null,
+ ): Polyline {
val polyline = map.addPolyline(config.toPolylineOptions(overrideId))
config.onClick?.let { callback ->
polyline.setClickListener {
@@ -173,7 +181,11 @@ class Map3DState {
}
}
- private fun createPolygon(map: GoogleMap3D, config: PolygonConfig, overrideId: String? = null): Polygon {
+ private fun createPolygon(
+ map: GoogleMap3D,
+ config: PolygonConfig,
+ overrideId: String? = null,
+ ): Polygon {
val polygon = map.addPolygon(config.toPolygonOptions(overrideId))
config.onClick?.let { callback ->
polygon.setClickListener {
@@ -220,7 +232,11 @@ class Map3DState {
}
}
- private fun createModel(map: GoogleMap3D, config: ModelConfig, overrideId: String? = null): Model {
+ private fun createModel(
+ map: GoogleMap3D,
+ config: ModelConfig,
+ overrideId: String? = null,
+ ): Model {
val model = map.addModel(config.toModelOptions(overrideId))
config.onClick?.let { callback ->
model.setClickListener {
diff --git a/maps3d-compose/src/main/java/com/google/maps/android/compose3d/utils/Units.kt b/maps3d-compose/src/main/java/com/google/maps/android/compose3d/utils/Units.kt
index d0d96c02..6a114f5b 100644
--- a/maps3d-compose/src/main/java/com/google/maps/android/compose3d/utils/Units.kt
+++ b/maps3d-compose/src/main/java/com/google/maps/android/compose3d/utils/Units.kt
@@ -137,7 +137,9 @@ fun getUnitsConverter(countryCode: String?): UnitsConverter {
/** Class to render measurements in imperial units. */
object ImperialUnitsConverter : UnitsConverter() {
- override fun toDistanceUnits(meters: Meters): ValueWithUnitsTemplate = if (meters < 0.25.miles) {
+ override fun toDistanceUnits(meters: Meters): ValueWithUnitsTemplate = if (meters <
+ 0.25.miles
+ ) {
ValueWithUnitsTemplate(meters.toFeet, R.string.in_feet)
} else {
ValueWithUnitsTemplate(meters.toMiles, R.string.in_miles)
@@ -148,7 +150,9 @@ object ImperialUnitsConverter : UnitsConverter() {
/** Class to render measurements in metric units. */
object MetricUnitsConverter : UnitsConverter() {
- override fun toDistanceUnits(meters: Meters): ValueWithUnitsTemplate = if (meters < 1000.meters) {
+ override fun toDistanceUnits(meters: Meters): ValueWithUnitsTemplate = if (meters <
+ 1000.meters
+ ) {
ValueWithUnitsTemplate(meters.toMeters, R.string.in_meters)
} else {
ValueWithUnitsTemplate(meters.toKilometers, R.string.in_kilometers)
diff --git a/maps3d-compose/src/main/java/com/google/maps/android/compose3d/utils/Utilities.kt b/maps3d-compose/src/main/java/com/google/maps/android/compose3d/utils/Utilities.kt
index 951e8f1a..ea7c987a 100644
--- a/maps3d-compose/src/main/java/com/google/maps/android/compose3d/utils/Utilities.kt
+++ b/maps3d-compose/src/main/java/com/google/maps/android/compose3d/utils/Utilities.kt
@@ -319,10 +319,7 @@ fun FlyAroundOptions.copy(
}
}
-fun FlyToOptions.copy(
- endCamera: Camera? = null,
- durationInMillis: Long? = null,
-): FlyToOptions {
+fun FlyToOptions.copy(endCamera: Camera? = null, durationInMillis: Long? = null): FlyToOptions {
val objectToCopy = this
return flyToOptions {
diff --git a/snippets/build.gradle.kts b/snippets/build.gradle.kts
index f5ce5c09..e4a5d8a7 100644
--- a/snippets/build.gradle.kts
+++ b/snippets/build.gradle.kts
@@ -35,7 +35,13 @@ subprojects {
}
kotlin {
target("**/*.kt")
- ktlint().editorConfigOverride(mapOf("indent_size" to "4", "ktlint_function_naming_ignore_when_annotated_with" to "Composable"))
+ ktlint().editorConfigOverride(
+ mapOf(
+ "indent_size" to "4",
+ "ktlint_function_naming_ignore_when_annotated_with" to "Composable",
+ "ktlint_standard_max-line-length" to "disabled",
+ ),
+ )
trimTrailingWhitespace()
endWithNewline()
}
diff --git a/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/MapActivity.kt b/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/MapActivity.kt
index dfc6e489..55780874 100644
--- a/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/MapActivity.kt
+++ b/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/MapActivity.kt
@@ -54,7 +54,10 @@ class MapActivity : AppCompatActivity() {
val groupTitle = intent.getStringExtra("group_title")
val snippetTitle = intent.getStringExtra(EXTRA_SNIPPET_TITLE)
val snippetList = SnippetRegistry.getSnippetGroups().flatMap { it.items }
- var currentIndex = snippetList.indexOfFirst { it.title == snippetTitle && (groupTitle == null || it.groupTitle == groupTitle) }
+ var currentIndex = snippetList.indexOfFirst {
+ it.title == snippetTitle &&
+ (groupTitle == null || it.groupTitle == groupTitle)
+ }
findViewById(R.id.snapshot_button).apply {
setOnClickListener {
@@ -187,7 +190,10 @@ class MapActivity : AppCompatActivity() {
if (snippetTitle == null) return
val key = if (groupTitle != null) "$groupTitle - $snippetTitle" else snippetTitle
val snippet = SnippetRegistry.snippets[key]
- ?: SnippetRegistry.getSnippetGroups().flatMap { it.items }.find { it.title == snippetTitle }
+ ?: SnippetRegistry.getSnippetGroups().flatMap { it.items }.find {
+ it.title ==
+ snippetTitle
+ }
?: return
if (!::googleMap3D.isInitialized) return
diff --git a/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/SnippetRegistry.kt b/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/SnippetRegistry.kt
index e81504dd..f4cfecde 100644
--- a/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/SnippetRegistry.kt
+++ b/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/SnippetRegistry.kt
@@ -105,7 +105,9 @@ object SnippetRegistry {
// Most snippet methods take no args because they use initialized class fields
if (method.parameterCount == 0) {
method.invoke(instance)
- } else if (method.parameterCount == 1 && method.parameterTypes[0] == Context::class.java) {
+ } else if (method.parameterCount == 1 &&
+ method.parameterTypes[0] == Context::class.java
+ ) {
method.invoke(instance, context)
} else {
// Fallback or log error
@@ -132,14 +134,29 @@ object SnippetRegistry {
return groups
}
- private fun createInstance(clazz: Class<*>, context: Context, map: TrackedMap3D, scope: CoroutineScope): Any = try {
- clazz.getConstructor(Context::class.java, TrackedMap3D::class.java, CoroutineScope::class.java).newInstance(context, map, scope)
+ private fun createInstance(
+ clazz: Class<*>,
+ context: Context,
+ map: TrackedMap3D,
+ scope: CoroutineScope,
+ ): Any = try {
+ clazz.getConstructor(
+ Context::class.java,
+ TrackedMap3D::class.java,
+ CoroutineScope::class.java,
+ ).newInstance(context, map, scope)
} catch (e: Exception) {
try {
- clazz.getConstructor(TrackedMap3D::class.java, CoroutineScope::class.java).newInstance(map, scope)
+ clazz.getConstructor(
+ TrackedMap3D::class.java,
+ CoroutineScope::class.java,
+ ).newInstance(map, scope)
} catch (e: Exception) {
try {
- clazz.getConstructor(Context::class.java, TrackedMap3D::class.java).newInstance(context, map)
+ clazz.getConstructor(
+ Context::class.java,
+ TrackedMap3D::class.java,
+ ).newInstance(context, map)
} catch (e: Exception) {
try {
clazz.getConstructor(TrackedMap3D::class.java).newInstance(map)
diff --git a/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/TrackedMap3D.kt b/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/TrackedMap3D.kt
index d7637e0c..683d246a 100644
--- a/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/TrackedMap3D.kt
+++ b/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/TrackedMap3D.kt
@@ -23,10 +23,7 @@ import com.google.android.gms.maps3d.model.PopoverOptions
/**
* Decorator wrapper around GoogleMap3D to track elements added during a snippet session.
*/
-class TrackedMap3D(
- val delegate: GoogleMap3D,
- private val items: MutableList,
-) {
+class TrackedMap3D(val delegate: GoogleMap3D, private val items: MutableList) {
fun addMarker(options: MarkerOptions): Marker? {
val marker = delegate.addMarker(options)
diff --git a/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/annotations/SnippetGroup.kt b/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/annotations/SnippetGroup.kt
index 1558bc3d..7beb349f 100644
--- a/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/annotations/SnippetGroup.kt
+++ b/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/annotations/SnippetGroup.kt
@@ -8,7 +8,4 @@ package com.example.snippets.kotlin.annotations
*/
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
-annotation class SnippetGroup(
- val title: String,
- val description: String = "",
-)
+annotation class SnippetGroup(val title: String, val description: String = "")
diff --git a/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/annotations/SnippetItem.kt b/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/annotations/SnippetItem.kt
index d9aa6110..b1a22eee 100644
--- a/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/annotations/SnippetItem.kt
+++ b/snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/annotations/SnippetItem.kt
@@ -8,7 +8,4 @@ package com.example.snippets.kotlin.annotations
*/
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
-annotation class SnippetItem(
- val title: String,
- val description: String = "",
-)
+annotation class SnippetItem(val title: String, val description: String = "")