Skip to content

feat(UIControlsScreen): add dedicated UI controls sample and snippets across Kotlin, Java, and Compose - #80

Closed
LoyalAbbas wants to merge 1 commit into
feat/quick-settings-widget-with-app-sessionfrom
feat/dedicated_ui_control_screen
Closed

LoyalAbbas wants to merge 1 commit into
feat/quick-settings-widget-with-app-sessionfrom
feat/dedicated_ui_control_screen

Conversation

@LoyalAbbas

Copy link
Copy Markdown
Collaborator

Summary

Adds a dedicated UI Controls (UiControlsActivity) sample with 3-way parity across Kotlin Views, Java Views, and Jetpack Compose (defaulting to Map3DMode.ROADMAP), along with comprehensive Kotlin and Java documentation snippets (UiControlSnippets).

Key Changes

  • Shared :common UI Controls & Controller Support:
    • Added control_panel_ui_controls.xml and bindUiControlButtonsPanel(panelRootView: View) in Map3DSettingsController.kt to allow interactive configuration of built-in 3D camera controls (ZoomControl, TiltControl, RotateControl, PanVerticalControl, PanHorizontalControl, CompassControl) and edge placement (ControlPlacement.LEADING vs ControlPlacement.TRAILING).
    • Placed CompassControl with the secondary pan controls (PanVerticalControl, PanHorizontalControl) on the opposite edge from the primary camera controls (ZoomControl, TiltControl, RotateControl) to prevent screen edge overlap.
  • 3-Way Sample App Parity (UiControlsActivity):
    • Kotlin Views: Added UiControlsActivity.kt and registered it in MainActivity.kt and AndroidManifest.xml.
    • Java Views: Added UiControlsActivity.java and registered it in MainActivity.java and AndroidManifest.xml.
    • Jetpack Compose: Added UiControlsActivity.kt with UiControlsBottomSheet and registered it in MainActivity.kt and AndroidManifest.xml.
  • Snippets (:snippets:kotlin-app & :snippets:java-app):
    • Added UiControlSnippets.kt and UiControlSnippets.java covering:
      1. Standard vertical edge placement (ControlPlacement.TRAILING & ControlPlacement.LEADING)
      2. Swapping leading and trailing edges
      3. Horizontal control orientation (ControlOrientation.HORIZONTAL), Spacer(), and ControlPlacement.TOP / ControlPlacement.BOTTOM placement
      4. Hiding/clearing UI controls across all edges using an empty list
    • Updated TrackedMap3D and SnippetRegistry (Kotlin & Java) to automatically reset UI control placements across all edges when switching snippets.
  • Unit Tests:

Verification

  • Verified compilation across :Maps3DSamples:ApiDemos:kotlin-app, :Maps3DSamples:ApiDemos:java-app, :Maps3DSamples:ComposeDemos:app, :snippets:kotlin-app, and :snippets:java-app.
  • Verified unit tests in :Maps3DSamples:ApiDemos:common:testDebugUnitTest.

@LoyalAbbas
LoyalAbbas requested a review from dkhawk October 13, 2026 09:21

@kikoso kikoso left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @LoyalAbbas ! The snippets look good and are a nice addition for the docs. My main comment is about the activity going through the shared controller instead of calling the SDK. Since this is stacked on #79, let's merge it after that one.


chipZoom?.setOnCheckedChangeListener { _, isChecked ->
if (isSyncingUi) return@setOnCheckedChangeListener
val updated = Map3DSettingsController.shared.updateUiControl(zoom = isChecked)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Being this a dedicated UI controls sample, I would expect to see the SDK call here (getUiControlSettings()?.setUiControlsPlacement(...)). Right now everything goes through Map3DSettingsController.shared and applyTo, so the code the sample is about lives in common/Map3DSettings.kt. Could we call the SDK directly in the three activities, like the snippets do?

}

btnHideAll?.setOnClickListener {
val updated = Map3DSettingsController.shared.setAllUiControls(false)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this writes to Map3DSettingsController.shared, tapping "Hide all" here also hides the controls in every other sample for the rest of the session. Is that intended? Also, the controller already notifies the quick settings button, which calls applyTo, so the map gets the settings applied twice (same as Dale's comment in the dialog).

* Visibility state for built-in 3D camera UI controls.
* Placement edge constant alias for [ControlPlacement] ([ControlPlacement.TRAILING] vs [ControlPlacement.LEADING]).
*/
typealias UiControlsPlacementPosition = ControlPlacement

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could we use ControlPlacement directly instead of the UiControlsPlacementPosition alias? It adds a second name for the same SDK type, and people reading the sample will look for it in the docs.


fun getUiControlSettings(): UiControlSettings? {
val settings = delegate.getUiControlSettings()
if (settings != null) items.add(settings)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: every call adds the same UiControlSettings instance to items, so the cleanup resets it several times.

Suggested change
if (settings != null) items.add(settings)
if (settings != null && settings !in items) items.add(settings)

// [START maps_android_3d_ui_controls_swap_edges_kt]
map.getUiControlSettings()?.let { uiSettings ->
val leadingControls = listOf(
ZoomControl(null),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: snippet 1 passes ControlOrientation.VERTICAL and this one passes null. Since both end up in the docs, could we use the same in both? The explicit VERTICAL reads better to me.

@LoyalAbbas
LoyalAbbas added this pull request to stack #82 October 14, 2026 12:55
dkhawk added a commit that referenced this pull request Oct 14, 2026
…ols showcase

Consolidates the stacked 3D Maps camera UI control improvements (PR #78,
PR #79, and PR #80) into a single cohesive branch with 100% 3-way parity
across Kotlin Views, Java Views, and Jetpack Compose.

- Quick Settings Overlay: Map3DQuickSettingsButton (Views) and
  Map3DQuickSettingsWidget (Compose) with session-scoped Map3DSettingsController.
- Dedicated UI Controls Showcase: Introduces UiControlsActivity across
  Kotlin, Java, and Compose calling the Maps 3D SDK directly
  (getUiControlSettings().setUiControlsPlacement(...)) with local UI state.
- SDK Standards: Removed internal reflection hacks into GoogleMap3D and
  LinearLayout layout mutations; standardized on ControlPlacement and
  ControlOrientation.VERTICAL.
- Stability & Robustness: Prevents Compose NoSuchFieldError on stripped
   fields, fixes top control clipping under toolbars, and adds
  comprehensive JVM unit tests in Map3DSettingsControllerTest.
dkhawk added a commit that referenced this pull request Oct 14, 2026
…ols showcase

Consolidates the stacked 3D Maps camera UI control improvements (PR #78,
PR #79, and PR #80) into a single cohesive branch with 100% 3-way parity
across Kotlin Views, Java Views, and Jetpack Compose.

- Quick Settings Overlay: Map3DQuickSettingsButton (Views) and
  Map3DQuickSettingsWidget (Compose) with session-scoped Map3DSettingsController.
- Dedicated UI Controls Showcase: Introduces UiControlsActivity across
  Kotlin, Java, and Compose calling the Maps 3D SDK directly
  (getUiControlSettings().setUiControlsPlacement(...)) with local UI state.
- SDK Standards: Removed internal reflection hacks into GoogleMap3D and
  LinearLayout layout mutations; standardized on ControlPlacement and
  ControlOrientation.VERTICAL.
- Stability & Robustness: Prevents Compose NoSuchFieldError on stripped
   fields, fixes top control clipping under toolbars, and adds
  comprehensive JVM unit tests in Map3DSettingsControllerTest.
@dkhawk

dkhawk commented Oct 14, 2026

Copy link
Copy Markdown
Collaborator

Closing as superseded: all changes and review comment resolutions from this PR have been consolidated directly into #78 on a rebased, single-branch history.

@dkhawk dkhawk closed this Oct 14, 2026
dkhawk added a commit that referenced this pull request Oct 14, 2026
…ols showcase (#78)

* feat(settings): add 3D map quick settings widget with camera controls toggle

- Introduce Map3DQuickSettingsButton for Kotlin and Java Views
- Introduce Map3DQuickSettingsWidget for Jetpack Compose
- Support live switching of Map Mode (Satellite, Hybrid, Roadmap)
- Support live switching of Color Scheme (System, Light, Dark)
- Support master and granular toggling of Maps 3D camera UI controls
- Protect top camera controls and settings FAB from status bar insets
- Add Map3DSettingsControllerTest with 100% passing JVM unit tests

* fix(compose): prevent Compose stability crash in Map3DQuickSettingsWidget and fix GoogleMap3D syntax

* fix(controls): ensure 3D map camera UI controls persist and attach reliably across Kotlin, Java, and Compose

* feat(settings): unify 3D quick settings widget and dedicated UI controls showcase

Consolidates the stacked 3D Maps camera UI control improvements (PR #78,
PR #79, and PR #80) into a single cohesive branch with 100% 3-way parity
across Kotlin Views, Java Views, and Jetpack Compose.

- Quick Settings Overlay: Map3DQuickSettingsButton (Views) and
  Map3DQuickSettingsWidget (Compose) with session-scoped Map3DSettingsController.
- Dedicated UI Controls Showcase: Introduces UiControlsActivity across
  Kotlin, Java, and Compose calling the Maps 3D SDK directly
  (getUiControlSettings().setUiControlsPlacement(...)) with local UI state.
- SDK Standards: Removed internal reflection hacks into GoogleMap3D and
  LinearLayout layout mutations; standardized on ControlPlacement and
  ControlOrientation.VERTICAL.
- Stability & Robustness: Prevents Compose NoSuchFieldError on stripped
   fields, fixes top control clipping under toolbars, and adds
  comprehensive JVM unit tests in Map3DSettingsControllerTest.

* fix(compose): add stability config for 3D SDK types to resolve NoSuchFieldError ()

- Add root compose_stability.conf treating com.google.android.gms.maps3d.** as stable
- Configure composeCompiler { stabilityConfigurationFiles } in ComposeDemos, common, and maps3d-compose
- Update DisposableEffect key in GoogleMap3D to boolean condition to avoid synthetic field lookups
- Apply spotless formatting across compose modules

* chore(java): defer Java Map3DControl sample and snippets pending SDK 16.0.1 fix

* feat(ui): enforce sticky immersive mode across 3D map samples and quick settings

* fix(snippets): specify valid mapMode and enable immersive mode for SDK 16.0.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants