Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/white" />
<stroke
android:width="2dp"
android:color="#3DDC84" />
<size
android:width="44dp"
android:height="44dp" />
</shape>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2023 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.
Expand All @@ -17,10 +17,13 @@
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import com.example.common_ui.R;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
Expand All @@ -33,6 +36,7 @@
import com.google.android.gms.maps.model.AdvancedMarkerOptions;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.MapCapabilities;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.PinConfig;
Expand Down Expand Up @@ -114,17 +118,33 @@ protected void onCreate(Bundle savedInstanceState) {

@Override
public void onMapReady(GoogleMap map) {
map.moveCamera(CameraUpdateFactory.newLatLngZoom(SINGAPORE, ZOOM_LEVEL));
LatLngBounds bounds = new LatLngBounds.Builder()
.include(SINGAPORE)
.include(KUALA_LUMPUR)
.include(JAKARTA)
.include(BANGKOK)
.include(MANILA)
.include(HO_CHI_MINH_CITY)
.build();
map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 120));

MapCapabilities capabilities = map.getMapCapabilities();
Log.d(TAG, "Are advanced markers enabled? " + capabilities.isAdvancedMarkersAvailable());

// This sample sets a view as the iconView for the Advanced Marker
TextView textView = new TextView(this);
textView.setText("Hello!");
Marker advancedMarkerView = map.addMarker(new AdvancedMarkerOptions()
// 1. Custom View as iconView (Framed circular badge with Android logo)
ImageView iconImageView = new ImageView(this);
iconImageView.setImageResource(R.drawable.ic_android);
iconImageView.setColorFilter(Color.parseColor("#3DDC84")); // Android Green
iconImageView.setBackgroundResource(R.drawable.bg_marker_badge);
int padding = (int) (8 * getResources().getDisplayMetrics().density);
iconImageView.setPadding(padding, padding, padding, padding);
int size = (int) (44 * getResources().getDisplayMetrics().density);
iconImageView.setLayoutParams(new ViewGroup.LayoutParams(size, size));

map.addMarker(new AdvancedMarkerOptions()
.position(SINGAPORE)
.iconView(textView)
.iconView(iconImageView)
.title("Singapore (Custom Framed Badge)")
.zIndex(1f));

// This uses PinConfig.Builder to create an instance of PinConfig.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// 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.
Expand Down Expand Up @@ -40,6 +40,7 @@
import com.google.android.gms.maps.model.FeatureStyle;
import com.google.android.gms.maps.model.FeatureType;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.MapCapabilities;

import java.util.List;
Expand All @@ -58,8 +59,7 @@ public class DataDrivenDatasetStylingActivity extends SamplesBaseActivity implem
private record DataSet(
String label,
String datasetId,
LatLng location,
float zoomLevel,
LatLngBounds bounds,
DataDrivenDatasetStylingActivity.DataSet.StylingCallback callback) {
public interface StylingCallback {
void styleDatasetLayer();
Expand All @@ -71,25 +71,19 @@ public interface StylingCallback {
* Each DataSet contains:
* - A human-readable name (e.g., "Boulder", "New York").
* - A unique Dataset ID, which should correspond to a dataset id in the Datasets console tab.
* - The central latitude and longitude coordinates (LatLng) of the location.
* - The LatLngBounds of the dataset area.
* - A styling function (method reference) that defines how to style the data from that dataset on a map.
* <p>
* This array is used to configure which datasets are available for display and how they should be presented.
* Each element of the array should be a new DataSet object.
* Modify the constructor arguments of each DataSet to define your specific data and styles.
* The styling function will receive a `Layer` to which it can add elements.
* <p>
* Example:
* - `new DataSet("Boulder", "Boulder-DataSet-Id", new LatLng(40.0150, -105.2705), this::styleBoulderDatasetLayer)`
* This creates a DataSet for Boulder, identified by "Boulder-DataSet-Id", centered on the given coordinates,
* and styled using the `styleBoulderDatasetLayer` method.
* <p>
* Note: We have use the secrets plugin to allow us to configure the Dataset IDs in our secrets.properties file.
*/
private final DataSet[] dataSets = new DataSet[] {
new DataSet("Boulder", BuildConfig.BOULDER_DATASET_ID, new LatLng(40.0150, -105.2705), 11f, this::styleBoulderDatasetLayer),
new DataSet("New York", BuildConfig.NEW_YORK_DATASET_ID, new LatLng(40.786244, -73.962684), 14f, this::styleNYCDatasetLayer),
new DataSet("Kyoto", BuildConfig.KYOTO_DATASET_ID, new LatLng(35.005081, 135.764385), 13.5f, this::styleKyotoDatasetsLayer),
new DataSet("Boulder", BuildConfig.BOULDER_DATASET_ID,
new LatLngBounds(new LatLng(39.920, -105.340), new LatLng(40.090, -105.210)),
this::styleBoulderDatasetLayer),
new DataSet("New York", BuildConfig.NEW_YORK_DATASET_ID,
new LatLngBounds(new LatLng(40.7640, -73.9820), new LatLng(40.8000, -73.9490)),
this::styleNYCDatasetLayer),
new DataSet("Kyoto", BuildConfig.KYOTO_DATASET_ID,
new LatLngBounds(new LatLng(34.9700, 135.7200), new LatLng(35.0400, 135.8000)),
this::styleKyotoDatasetsLayer),
};

private DataSet findDataSetByLabel(String label) {
Expand Down Expand Up @@ -176,14 +170,19 @@ private void switchDataSet(String label) {
.build()
);
dataSet.callback.styleDatasetLayer();
centerMapOnLocation(dataSet.location(), dataSet.zoomLevel());
centerMapOnBounds(dataSet.bounds());
}
}

@Override
public void onMapReady(@NonNull GoogleMap googleMap) {
this.map = googleMap;

googleMap.setOnCameraIdleListener(() -> {
com.google.android.gms.maps.model.CameraPosition cp = googleMap.getCameraPosition();
Log.i(TAG, "CAMERA_PARAMS: target=LatLng(" + cp.target.latitude + ", " + cp.target.longitude + "), zoom=" + cp.zoom + "f, tilt=" + cp.tilt + "f, bearing=" + cp.bearing + "f");
});

MapCapabilities capabilities = map.getMapCapabilities();
Log.d(TAG, "Data-driven Styling is available: " + capabilities.isDataDrivenStylingAvailable());
if (!capabilities.isDataDrivenStylingAvailable()) {
Expand Down Expand Up @@ -364,8 +363,8 @@ private void styleBoulderDatasetLayer() {
}


private void centerMapOnLocation(LatLng location, float zoomLevel) {
map.moveCamera(CameraUpdateFactory.newLatLngZoom(location, zoomLevel));
private void centerMapOnBounds(LatLngBounds bounds) {
map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 80));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2020 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.
Expand All @@ -23,6 +23,7 @@
import com.google.android.gms.maps.model.GroundOverlay;
import com.google.android.gms.maps.model.GroundOverlayOptions;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;

import android.graphics.Point;
import android.os.Bundle;
Expand Down Expand Up @@ -51,6 +52,10 @@ public class GroundOverlayDemoActivity extends SamplesBaseActivity
private static final LatLng NEWARK = new LatLng(40.714086, -74.228697);
private static final LatLng NEAR_NEWARK =
new LatLng(NEWARK.latitude - 0.001, NEWARK.longitude - 0.025);
static final LatLngBounds OVERLAY_BOUNDS = new LatLngBounds(
new LatLng(40.7050, -74.2600),
new LatLng(40.7800, -74.1200)
);

private final List<BitmapDescriptor> images = new ArrayList<>();

Expand Down Expand Up @@ -84,7 +89,7 @@ protected void onCreate(Bundle savedInstanceState) {
setContentView(binding.getRoot());

binding.transparencySeekBar.setMax(TRANSPARENCY_MAX);
binding.transparencySeekBar.setProgress(0);
binding.transparencySeekBar.setProgress(25);

// Set up programmatic click listeners for the buttons.
binding.switchImage.setOnClickListener(v -> switchImage());
Expand All @@ -106,10 +111,8 @@ public void onMapReady(GoogleMap map) {
// Register a listener to respond to clicks on GroundOverlays.
map.setOnGroundOverlayClickListener(this);

// Move the camera to the Newark area.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(NEWARK, 11));

map.moveCamera(CameraUpdateFactory.scrollBy(100f, 100f));
// Move the camera to frame the Newark overlays with padding.
map.moveCamera(CameraUpdateFactory.newLatLngBounds(OVERLAY_BOUNDS, 80));

map.setOnMapClickListener(ll -> {
Point point = mMap.getProjection().toScreenLocation(ll);
Expand Down Expand Up @@ -141,7 +144,8 @@ public void onMapReady(GoogleMap map) {
// Add a large overlay at Newark on top of the smaller overlay.
groundOverlay = map.addGroundOverlay(new GroundOverlayOptions()
.image(images.get(currentEntry)).anchor(0, 1)
.position(NEWARK, 8600f, 6500f));
.position(NEWARK, 8600f, 6500f)
.transparency((float) binding.transparencySeekBar.getProgress() / (float) TRANSPARENCY_MAX));
groundOverlay.setTag(images.get(currentEntry));

binding.transparencySeekBar.setOnSeekBarChangeListener(this);
Expand Down
Loading