mirror of
https://github.com/googlemaps/android-samples.git
synced 2025-12-08 18:02:20 +00:00
feat: Data-Driven styling samples (#1771)
* fix: import rememberMarkerState and use the marker state correctly * feat: dataset styling Kotlin samples * feat: added DataDrivenBoundariesActivity.kt * feat: added DataDrivenBoundariesActivity * feat: added documentation * feat: added header * chore: changed MY_MAP_ID to DEMO_MAP_ID * feat: moved data files to raw * feat: added DataDrivenBoundariesActivity * feat: removed unused files * feat: map id * chore: replace System.out.println with Log.d * feat: added region tags * feat: added different set of DDS * feat: added different set of DDS * feat: replacing files feat: replacing files * feat: replacing files * feat: compileSdk 35 * feat: compileSdk 35 * chore: updated README file * feat: trying to force different datasets * feat: updated samples * feat: Add data-driven styling for datasets This commit introduces data-driven styling for datasets in the ApiDemos application. The following changes were made: Added a custom Application class (ApiDemoApplication) to check for the presence and validity of the API key during startup. Added a new data structure (DataSet) to hold information about each dataset, including its label, dataset ID, location, and styling callback. Updated the DataDrivenDatasetStylingActivity to use the new data structure and styling callbacks. Rename the dataset input files to better reflect there contents. * fix: moves the dataset ids to the secrets.properties file * feat: significant rewrite to of DataDrivenDatasetStylingActivity * Makes the app look better on full screen with a cutout * Uses material elements * Switch to using secrets for the data set ids * more of a convenience to prevent having to remove the ids when submitting * moves dataset data files to common area since they are not used directly by the app * Detailed instructions for uploading the data to console (WIP) * fix: exports the data driven styling activities so they can be run directly * feat: added header * feat: change ubuntu-latest * feat: change ubuntu-latest * feat: change ubuntu-latest --------- Co-authored-by: dkhawk <107309+dkhawk@users.noreply.github.com>
This commit is contained in:
parent
95f70aafdd
commit
f4654e60a2
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@ -45,8 +45,12 @@ jobs:
|
||||
- name: Build and check
|
||||
run: |
|
||||
cd ApiDemos
|
||||
for dir in ./*/ ; do ( cd "$dir" && ./gradlew buildDebugPreBundle ); done
|
||||
|
||||
for dir in ./*/ ; do
|
||||
if [[ "$dir" != "./resources/" ]]; then
|
||||
( cd "$dir" && ./gradlew buildDebugPreBundle )
|
||||
fi
|
||||
done
|
||||
|
||||
build-WearOS:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -33,6 +33,7 @@ limitations under the License.
|
||||
android:maxSdkVersion="22" />
|
||||
|
||||
<application
|
||||
android:name=".ApiDemoApplication"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/demo_title"
|
||||
@ -89,6 +90,14 @@ limitations under the License.
|
||||
android:name=".CircleDemoActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/circle_demo_label" />
|
||||
<activity
|
||||
android:name=".DataDrivenBoundariesActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/data_driven_boundaries_label" />
|
||||
<activity
|
||||
android:name=".DataDrivenDatasetStylingActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/data_driven_styling_label" />
|
||||
<activity
|
||||
android:name=".EventsDemoActivity"
|
||||
android:exported="true"
|
||||
|
||||
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2025 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.mapdemo;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* {@code ApiDemoApplication} is a custom Application class for the API demo.
|
||||
*
|
||||
* <p>This class is responsible for application-wide initialization and setup,
|
||||
* such as checking for the presence and validity of the API key during the
|
||||
* application's startup.</p>
|
||||
*
|
||||
* <p>It extends the {@link Application} class and overrides the {@link #onCreate()}
|
||||
* method to perform these initialization tasks.</p>
|
||||
*/
|
||||
public class ApiDemoApplication extends Application {
|
||||
private static final String TAG = "ApiDemoApplication";
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Log.d(TAG, "onCreate called");
|
||||
checkApiKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the API key for Google Maps is properly configured in the application's metadata.
|
||||
* <p>
|
||||
* This method retrieves the API key from the application's metadata, specifically looking for
|
||||
* a string value associated with the key "com.google.android.geo.API_KEY".
|
||||
* The key must be present, not blank, and not set to the placeholder value "DEFAULT_API_KEY".
|
||||
* <p>
|
||||
* If any of these checks fail, a Toast message is displayed indicating that the API key is missing or
|
||||
* incorrectly configured, and a RuntimeException is thrown.
|
||||
* <p>
|
||||
*/
|
||||
private void checkApiKey() {
|
||||
try {
|
||||
ApplicationInfo appInfo = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
|
||||
Bundle bundle = Objects.requireNonNull(appInfo.metaData);
|
||||
|
||||
String apiKey = bundle.getString("com.google.android.geo.API_KEY"); // Key name is important!
|
||||
|
||||
if (apiKey == null || apiKey.isBlank() || apiKey.equals("DEFAULT_API_KEY")) {
|
||||
Toast.makeText(this, "API Key was not set in secrets.properties", Toast.LENGTH_LONG).show();
|
||||
throw new RuntimeException("API Key was not set in secrets.properties");
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.e(TAG, "Package name not found.", e);
|
||||
throw new RuntimeException("Error getting package info.", e);
|
||||
} catch (NullPointerException e) {
|
||||
Log.e(TAG, "Error accessing meta-data.", e); // Handle the case where meta-data is completely missing.
|
||||
throw new RuntimeException("Error accessing meta-data in manifest", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,228 @@
|
||||
// Copyright 2025 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.mapdemo;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
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.Feature;
|
||||
import com.google.android.gms.maps.model.FeatureClickEvent;
|
||||
import com.google.android.gms.maps.model.FeatureLayer;
|
||||
import com.google.android.gms.maps.model.FeatureLayerOptions;
|
||||
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.MapCapabilities;
|
||||
import com.google.android.gms.maps.model.PlaceFeature;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This sample showcases how to use the Data-driven styling for boundaries. For more information
|
||||
* on how the Data-driven styling for boundaries work, check out the following link:
|
||||
* https://developers.google.com/maps/documentation/android-sdk/dds-boundaries/overview
|
||||
*/
|
||||
// [START maps_android_data_driven_styling_boundaries]
|
||||
public class DataDrivenBoundariesActivity extends AppCompatActivity implements OnMapReadyCallback,
|
||||
FeatureLayer.OnFeatureClickListener {
|
||||
|
||||
private GoogleMap map;
|
||||
|
||||
private FeatureLayer localityLayer = null;
|
||||
private FeatureLayer areaLevel1Layer = null;
|
||||
private FeatureLayer countryLayer = null;
|
||||
|
||||
private static final String TAG = DataDrivenBoundariesActivity.class.getName();
|
||||
|
||||
private static final LatLng HANA_HAWAII = new LatLng(20.7522, -155.9877); // Hana, Hawaii
|
||||
private static final LatLng CENTER_US = new LatLng(39.8283, -98.5795); // Approximate geographical center of the contiguous US
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.data_driven_boundaries_demo);
|
||||
|
||||
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
|
||||
if (mapFragment != null) {
|
||||
mapFragment.getMapAsync(this);
|
||||
}
|
||||
|
||||
findViewById(R.id.button_hawaii).setOnClickListener(view -> centerMapOnLocation(HANA_HAWAII, 13.5f));
|
||||
findViewById(R.id.button_us).setOnClickListener(view -> centerMapOnLocation(CENTER_US, 1f));
|
||||
}
|
||||
|
||||
private void centerMapOnLocation(LatLng location, float zoomLevel) {
|
||||
map.moveCamera(CameraUpdateFactory.newLatLngZoom(location, zoomLevel));
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
@Override
|
||||
public void onMapReady(GoogleMap googleMap) {
|
||||
this.map = googleMap;
|
||||
MapCapabilities capabilities = map.getMapCapabilities();
|
||||
Log.d(TAG, "Data-driven Styling is available: " + capabilities.isDataDrivenStylingAvailable());
|
||||
|
||||
// Get the LOCALITY feature layer.
|
||||
localityLayer = googleMap.getFeatureLayer(
|
||||
new FeatureLayerOptions.Builder()
|
||||
.featureType(FeatureType.LOCALITY)
|
||||
.build()
|
||||
);
|
||||
|
||||
// Apply style factory function to LOCALITY layer.
|
||||
styleLocalityLayer();
|
||||
|
||||
// Get the ADMINISTRATIVE_AREA_LEVEL_1 feature layer.
|
||||
areaLevel1Layer = googleMap.getFeatureLayer(
|
||||
new FeatureLayerOptions.Builder()
|
||||
.featureType(FeatureType.ADMINISTRATIVE_AREA_LEVEL_1)
|
||||
.build()
|
||||
);
|
||||
|
||||
// Apply style factory function to ADMINISTRATIVE_AREA_LEVEL_1 layer.
|
||||
styleAreaLevel1Layer();
|
||||
|
||||
// Get the COUNTRY feature layer.
|
||||
countryLayer = googleMap.getFeatureLayer(
|
||||
new FeatureLayerOptions.Builder()
|
||||
.featureType(FeatureType.COUNTRY)
|
||||
.build()
|
||||
);
|
||||
|
||||
// Register the click event handler for the Country layer.
|
||||
countryLayer.addOnFeatureClickListener(this);
|
||||
|
||||
// Apply default style to all countries on load to enable clicking.
|
||||
styleCountryLayer();
|
||||
}
|
||||
|
||||
private void styleLocalityLayer() {
|
||||
// Create the style factory function.
|
||||
FeatureLayer.StyleFactory styleFactory = feature -> {
|
||||
// Check if the feature is an instance of PlaceFeature,
|
||||
// which contains a place ID.
|
||||
if (feature instanceof PlaceFeature placeFeature) {
|
||||
|
||||
// Determine if the place ID is for Hana, HI.
|
||||
if ("ChIJ0zQtYiWsVHkRk8lRoB1RNPo".equals(placeFeature.getPlaceId())) {
|
||||
// Use FeatureStyle.Builder to configure the FeatureStyle object
|
||||
// returned by the style factory function.
|
||||
return new FeatureStyle.Builder()
|
||||
// Define a style with purple fill at 50% opacity and
|
||||
// solid purple border.
|
||||
.fillColor(0x80810FCB)
|
||||
.strokeColor(0xFF810FCB)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// Apply the style factory function to the feature layer.
|
||||
if (localityLayer != null) {
|
||||
localityLayer.setFeatureStyle(styleFactory);
|
||||
}
|
||||
}
|
||||
|
||||
private void styleAreaLevel1Layer() {
|
||||
FeatureLayer.StyleFactory styleFactory = feature -> {
|
||||
if (feature instanceof PlaceFeature placeFeature) {
|
||||
|
||||
// Return a hueColor in the range [-299,299]. If the value is
|
||||
// negative, add 300 to make the value positive.
|
||||
int hueColor = placeFeature.getPlaceId().hashCode() % 300;
|
||||
if (hueColor < 0) {
|
||||
hueColor += 300;
|
||||
}
|
||||
return new FeatureStyle.Builder()
|
||||
// Set the fill color for the state based on the hashed hue color.
|
||||
.fillColor(Color.HSVToColor(150, new float[]{hueColor, 1f, 1f}))
|
||||
.build();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// Apply the style factory function to the feature layer.
|
||||
if (areaLevel1Layer != null) {
|
||||
areaLevel1Layer.setFeatureStyle(styleFactory);
|
||||
}
|
||||
}
|
||||
|
||||
// Set default fill and border for all countries to ensure that they respond
|
||||
// to click events.
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
private void styleCountryLayer() {
|
||||
FeatureLayer.StyleFactory styleFactory = feature -> new FeatureStyle.Builder()
|
||||
// Set the fill color for the country as white with a 10% opacity.
|
||||
// This requires minApi 26
|
||||
.fillColor(Color.argb(0.1f, 0f, 0f, 0f))
|
||||
// Set border color to solid black.
|
||||
.strokeColor(Color.BLACK)
|
||||
.build();
|
||||
|
||||
// Apply the style factory function to the country feature layer.
|
||||
if (countryLayer != null) {
|
||||
countryLayer.setFeatureStyle(styleFactory);
|
||||
}
|
||||
}
|
||||
|
||||
// Define the click event handler.
|
||||
@Override
|
||||
public void onFeatureClick(FeatureClickEvent event) {
|
||||
// Get the list of features affected by the click using
|
||||
// getPlaceIds() defined below.
|
||||
List<String> selectedPlaceIds = getPlaceIds(event.getFeatures());
|
||||
if (!selectedPlaceIds.isEmpty()) {
|
||||
FeatureLayer.StyleFactory styleFactory = feature -> {
|
||||
// Use PlaceFeature to get the placeID of the country.
|
||||
if (feature instanceof PlaceFeature) {
|
||||
if (selectedPlaceIds.contains(((PlaceFeature) feature).getPlaceId())) {
|
||||
return new FeatureStyle.Builder()
|
||||
// Set the fill color to red.
|
||||
.fillColor(Color.RED)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// Apply the style factory function to the feature layer.
|
||||
if (countryLayer != null) {
|
||||
countryLayer.setFeatureStyle(styleFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get a List of place IDs from the FeatureClickEvent object.
|
||||
private List<String> getPlaceIds(List<Feature> features) {
|
||||
List<String> placeIds = new ArrayList<>();
|
||||
for (Feature feature : features) {
|
||||
if (feature instanceof PlaceFeature) {
|
||||
placeIds.add(((PlaceFeature) feature).getPlaceId());
|
||||
}
|
||||
}
|
||||
return placeIds;
|
||||
}
|
||||
}
|
||||
// [END maps_android_data_driven_styling_boundaries]
|
||||
@ -0,0 +1,367 @@
|
||||
// Copyright 2025 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.mapdemo;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.widget.Button;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
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.DatasetFeature;
|
||||
import com.google.android.gms.maps.model.Feature;
|
||||
import com.google.android.gms.maps.model.FeatureClickEvent;
|
||||
import com.google.android.gms.maps.model.FeatureLayer;
|
||||
import com.google.android.gms.maps.model.FeatureLayerOptions;
|
||||
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.MapCapabilities;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* This sample showcases how to use the Data-driven styling for datasets. For more information
|
||||
* on how the Data-driven styling for boundaries work, check out the following link:
|
||||
* https://developers.google.com/maps/documentation/android-sdk/dds-datasets/overview
|
||||
* <p>
|
||||
* This is meant to work with the datasets in the res/raw directory.
|
||||
*/
|
||||
// [START maps_android_data_driven_styling_datasets]
|
||||
public class DataDrivenDatasetStylingActivity extends AppCompatActivity implements OnMapReadyCallback, FeatureLayer.OnFeatureClickListener {
|
||||
private record DataSet(
|
||||
String label,
|
||||
String datasetId,
|
||||
LatLng location,
|
||||
DataDrivenDatasetStylingActivity.DataSet.StylingCallback callback) {
|
||||
public interface StylingCallback {
|
||||
void styleDatasetLayer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of DataSet objects representing different geographic locations and their associated data.
|
||||
* 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.
|
||||
* - 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), this::styleBoulderDatasetLayer),
|
||||
new DataSet("New York", BuildConfig.NEW_YORK_DATASET_ID, new LatLng(40.786244, -73.962684), this::styleNYCDatasetLayer),
|
||||
new DataSet("Kyoto", BuildConfig.KYOTO_DATASET_ID, new LatLng(35.005081, 135.764385), this::styleKyotoDatasetsLayer),
|
||||
};
|
||||
|
||||
private DataSet findDataSetByLabel(String label) {
|
||||
for (DataSet dataSet : dataSets) {
|
||||
if (dataSet.label().equalsIgnoreCase(label)) { // Case-insensitive comparison
|
||||
return dataSet;
|
||||
}
|
||||
}
|
||||
return null; // Return null if no match is found
|
||||
}
|
||||
|
||||
private static final float ZOOM_LEVEL = 13.5f;
|
||||
private static final String TAG = DataDrivenDatasetStylingActivity.class.getName();
|
||||
private static FeatureLayer datasetLayer = null;
|
||||
private GoogleMap map;
|
||||
private String lastGlobalId = null;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.data_driven_styling_demo);
|
||||
|
||||
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
|
||||
if (mapFragment != null) {
|
||||
mapFragment.getMapAsync(this);
|
||||
}
|
||||
|
||||
int[] buttonIds = {R.id.button_boulder, R.id.button_ny, R.id.button_kyoto};
|
||||
for (int buttonId : buttonIds) {
|
||||
findViewById(buttonId).setOnClickListener(view -> switchDataSet(((Button) view).getText().toString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches the currently displayed dataset to the one specified by the provided label.
|
||||
* <p>
|
||||
* This method attempts to find a DataSet object associated with the given label.
|
||||
* If a matching DataSet is found, it updates the map's feature layer to display the
|
||||
* data from that dataset. It also applies styling to the new dataset layer and centers
|
||||
* the map on the dataset's specified location.
|
||||
* <p>
|
||||
* If no matching DataSet is found, a toast message is displayed indicating the failure.
|
||||
* <p>
|
||||
* @param label The label of the dataset to switch to. This label should correspond to a
|
||||
* dataset that has been previously added or loaded.
|
||||
*/
|
||||
private void switchDataSet(String label) {
|
||||
DataSet dataSet = findDataSetByLabel(label);
|
||||
if (dataSet == null) {
|
||||
Toast.makeText(this, "Failed to find dataset" + label, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
datasetLayer = map.getFeatureLayer(
|
||||
new FeatureLayerOptions.Builder()
|
||||
.featureType(FeatureType.DATASET)
|
||||
.datasetId(dataSet.datasetId())
|
||||
.build()
|
||||
);
|
||||
dataSet.callback.styleDatasetLayer();
|
||||
centerMapOnLocation(dataSet.location());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull GoogleMap googleMap) {
|
||||
this.map = googleMap;
|
||||
|
||||
MapCapabilities capabilities = map.getMapCapabilities();
|
||||
Log.d(TAG, "Data-driven Styling is available: " + capabilities.isDataDrivenStylingAvailable());
|
||||
|
||||
// Switch to the default dataset which must happen before adding the feature click listener
|
||||
switchDataSet("Boulder");
|
||||
|
||||
datasetLayer.addOnFeatureClickListener(this);
|
||||
}
|
||||
|
||||
private void styleNYCDatasetLayer() {
|
||||
FeatureLayer.StyleFactory styleFactory = feature -> {
|
||||
int fillColor = Color.GREEN;
|
||||
int strokeColor = Color.YELLOW;
|
||||
float pointRadius = 12F;
|
||||
|
||||
if (feature instanceof DatasetFeature) {
|
||||
Map<String, String> furColors = ((DatasetFeature) feature).getDatasetAttributes();
|
||||
String furColor = furColors.get("Color");
|
||||
|
||||
if (furColor != null) {
|
||||
switch (furColor) {
|
||||
case "Black+":
|
||||
fillColor = Color.BLACK;
|
||||
strokeColor = Color.BLACK;
|
||||
break;
|
||||
case "Cinnamon+":
|
||||
fillColor = 0xFF8B0000; // dark red color
|
||||
strokeColor = 0xFF8B0000;
|
||||
break;
|
||||
case "Cinnamon+Gray":
|
||||
fillColor = 0xFF8B0000; // dark red color
|
||||
strokeColor = 0xFF8B0000;
|
||||
pointRadius = 10F;
|
||||
break;
|
||||
case "Cinnamon+White":
|
||||
fillColor = 0xFF8B0000; // dark red color
|
||||
strokeColor = Color.WHITE;
|
||||
pointRadius = 10F;
|
||||
break;
|
||||
case "Gray+":
|
||||
fillColor = Color.GRAY;
|
||||
break;
|
||||
case "Gray+Cinnamon":
|
||||
fillColor = Color.GRAY;
|
||||
strokeColor = 0xFF8B0000; // dark red color
|
||||
pointRadius = 10F;
|
||||
break;
|
||||
case "Gray+Cinnamon, White":
|
||||
fillColor = Color.LTGRAY;
|
||||
strokeColor = 0xFF8B0000; // dark red color
|
||||
pointRadius = 10F;
|
||||
break;
|
||||
case "Gray+White":
|
||||
fillColor = Color.GRAY;
|
||||
strokeColor = Color.WHITE;
|
||||
pointRadius = 10F;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new FeatureStyle.Builder()
|
||||
.fillColor(fillColor)
|
||||
.strokeColor(strokeColor)
|
||||
.pointRadius(pointRadius)
|
||||
.build();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
if (datasetLayer != null) {
|
||||
datasetLayer.setFeatureStyle(styleFactory);
|
||||
}
|
||||
}
|
||||
|
||||
private void styleKyotoDatasetsLayer() {
|
||||
// Create the style factory function.
|
||||
FeatureLayer.StyleFactory styleFactory = feature -> {
|
||||
// Check if the feature is an instance of DatasetFeature.
|
||||
if (feature instanceof DatasetFeature datasetFeature) {
|
||||
// Determine the value of the typecategory attribute.
|
||||
Map<String, String> typeCategories = datasetFeature.getDatasetAttributes();
|
||||
String typeCategory = typeCategories.get("type");
|
||||
|
||||
// Set default colors to green.
|
||||
int fillColor;
|
||||
int strokeColor;
|
||||
|
||||
if ("temple".equals(typeCategory)) {
|
||||
// Color temples areas blue.
|
||||
fillColor = Color.BLUE;
|
||||
strokeColor = Color.BLUE;
|
||||
} else {
|
||||
// Color all other areas green.
|
||||
fillColor = Color.GREEN;
|
||||
strokeColor = Color.GREEN;
|
||||
}
|
||||
|
||||
return new FeatureStyle.Builder()
|
||||
.fillColor(fillColor)
|
||||
.strokeColor(strokeColor)
|
||||
.strokeWidth(2F)
|
||||
.build();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// Apply the style factory function to the feature layer.
|
||||
if (datasetLayer != null) {
|
||||
datasetLayer.setFeatureStyle(styleFactory);
|
||||
}
|
||||
}
|
||||
|
||||
private void styleBoulderDatasetLayer() {
|
||||
final int EASY = Color.GREEN;
|
||||
final int MODERATE = Color.BLUE;
|
||||
final int DIFFICULT = Color.RED;
|
||||
|
||||
// Create the style factory function.
|
||||
FeatureLayer.StyleFactory styleFactory = feature -> {
|
||||
// Set default colors to yellow and point radius to 8.
|
||||
int fillColor = Color.GREEN;
|
||||
int strokeColor = Color.YELLOW;
|
||||
float pointRadius = 8F;
|
||||
float strokeWidth = 3F;
|
||||
|
||||
// Check if the feature is an instance of DatasetFeature.
|
||||
if (feature instanceof DatasetFeature datasetFeature) {
|
||||
Map<String, String> attributes = datasetFeature.getDatasetAttributes();
|
||||
String difficulty = attributes.get("OSMPTrailsOSMPDIFFICULTY");
|
||||
String name = attributes.get("OSMPTrailsOSMPTRAILNAME");
|
||||
String dogsAllowed = attributes.get("OSMPTrailsOSMPDOGREGGEN");
|
||||
|
||||
if ("Easy".equals(difficulty)) {
|
||||
fillColor = EASY;
|
||||
} else if ("Moderate".equals(difficulty)) {
|
||||
fillColor = MODERATE;
|
||||
} else if ("Difficult".equals(difficulty)) {
|
||||
fillColor = DIFFICULT;
|
||||
} else {
|
||||
Log.w(TAG, name + " -> Unknown difficulty: " + difficulty);
|
||||
fillColor = Color.MAGENTA;
|
||||
}
|
||||
|
||||
if ("No Dogs".equals(dogsAllowed)) {
|
||||
fillColor = ColorUtils.setAlphaComponent(fillColor, 66);
|
||||
strokeWidth = 5f;
|
||||
} else if ("LVS".equals(dogsAllowed)) {
|
||||
// No change needed
|
||||
} else if ("LR".equals(dogsAllowed) || "RV".equals(dogsAllowed)) {
|
||||
fillColor = ColorUtils.setAlphaComponent(fillColor, 75);
|
||||
} else {
|
||||
Log.w(TAG, name + " -> Unknown dogs reg: " + dogsAllowed);
|
||||
}
|
||||
|
||||
strokeColor = fillColor;
|
||||
|
||||
return new FeatureStyle.Builder()
|
||||
.fillColor(fillColor)
|
||||
.strokeColor(strokeColor)
|
||||
.pointRadius(pointRadius)
|
||||
.strokeWidth(strokeWidth)
|
||||
.build();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// Apply the style factory function to the feature layer.
|
||||
if (datasetLayer != null) {
|
||||
datasetLayer.setFeatureStyle(styleFactory);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void centerMapOnLocation(LatLng location) {
|
||||
map.moveCamera(CameraUpdateFactory.newLatLngZoom(location, ZOOM_LEVEL));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFeatureClick(FeatureClickEvent event) {
|
||||
List<Feature> clickFeatures = event.getFeatures();
|
||||
lastGlobalId = null;
|
||||
if (clickFeatures.get(0) instanceof DatasetFeature) {
|
||||
lastGlobalId = ((DatasetFeature) clickFeatures.get(0)).getDatasetAttributes().get("globalid");
|
||||
styleDatasetsLayerClickEvent();
|
||||
}
|
||||
}
|
||||
|
||||
private void styleDatasetsLayerClickEvent() {
|
||||
FeatureLayer.StyleFactory styleFactory = feature -> {
|
||||
if (feature instanceof DatasetFeature) {
|
||||
Map<String, String> globalIDs = ((DatasetFeature) feature).getDatasetAttributes();
|
||||
String globalID = globalIDs.get("globalid");
|
||||
int fillColor = Color.GREEN;
|
||||
int strokeColor = Color.GREEN;
|
||||
|
||||
if (globalID != null && globalID.equals(lastGlobalId)) {
|
||||
fillColor = Color.BLUE;
|
||||
strokeColor = Color.BLUE;
|
||||
}
|
||||
|
||||
return new FeatureStyle.Builder()
|
||||
.fillColor(fillColor)
|
||||
.strokeColor(strokeColor)
|
||||
.build();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
if (datasetLayer != null) {
|
||||
datasetLayer.setFeatureStyle(styleFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
// [END maps_android_data_driven_styling_datasets]
|
||||
|
||||
@ -53,6 +53,12 @@ public final class DemoDetailsList {
|
||||
new DemoDetails(R.string.circle_demo_label,
|
||||
R.string.circle_demo_description,
|
||||
CircleDemoActivity.class),
|
||||
new DemoDetails(R.string.data_driven_styling_label,
|
||||
R.string.data_driven_styling_description,
|
||||
DataDrivenDatasetStylingActivity.class),
|
||||
new DemoDetails(R.string.data_driven_boundaries_label,
|
||||
R.string.data_driven_boundaries_description,
|
||||
DataDrivenBoundariesActivity.class),
|
||||
new DemoDetails(R.string.events_demo_label,
|
||||
R.string.events_demo_description,
|
||||
EventsDemoActivity.class),
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
<!--
|
||||
Copyright 2025 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.
|
||||
-->
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:map="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<!-- Map Fragment -->
|
||||
<fragment
|
||||
android:id="@+id/map"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
map:backgroundColor="#fff0b2dd"
|
||||
map:mapId="@string/map_id"
|
||||
class="com.google.android.gms.maps.SupportMapFragment" />
|
||||
|
||||
<!-- Buttons to center the map -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_hawaii"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hawaii" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_us"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="US" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
@ -0,0 +1,59 @@
|
||||
<!--
|
||||
Copyright 2025 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.
|
||||
-->
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:map="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<!-- Map Fragment -->
|
||||
<fragment
|
||||
android:id="@+id/map"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
map:backgroundColor="#fff0b2dd"
|
||||
map:mapId="@string/map_id"
|
||||
class="com.google.android.gms.maps.SupportMapFragment" />
|
||||
|
||||
<!-- Buttons to center the map -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_boulder"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Boulder" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_ny"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="New York" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_kyoto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Kyoto" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -208,7 +208,7 @@
|
||||
<!-- Advanced Markers Demo -->
|
||||
<string name="advanced_markers_demo_label">Advanced Markers</string>
|
||||
<string name="advanced_markers_demo_details">Showcases the usage of Advanced Markers.</string>
|
||||
<string name="map_id">MY_MAP_ID</string>
|
||||
<string name="map_id">DEMO_MAP_ID</string>
|
||||
|
||||
<!-- Styling -->
|
||||
<string name="styled_map_demo_label">Styled Map</string>
|
||||
@ -293,4 +293,12 @@
|
||||
<string name="map_color_light_mode">Light</string>
|
||||
<string name="map_color_dark_mode">Dark</string>
|
||||
<string name="map_color_follow_system_mode">Follow System\n</string>
|
||||
|
||||
<!-- Data Driven Styling Demo -->
|
||||
<string name="data_driven_styling_label">Data Driven Dataset Styling Demo</string>
|
||||
<string name="data_driven_styling_description">Demonstrates how to use Data Driven styling for datasets.</string>
|
||||
|
||||
<!-- Data Driven Boundaries Demo -->
|
||||
<string name="data_driven_boundaries_label">Data Driven Boundaries Demo</string>
|
||||
<string name="data_driven_boundaries_description">Demonstrates how to use Data Driven styling for boundaries.</string>
|
||||
</resources>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1 +1,5 @@
|
||||
MAPS_API_KEY=DEFAULT_API_KEY
|
||||
BOULDER_DATASET_ID=BOULDER_DATASET_ID
|
||||
NEW_YORK_DATASET_ID=NEW_YORK_DATASET_ID
|
||||
KYOTO_DATASET_ID=KYOTO_DATASET_ID
|
||||
MAP_ID=MAP_ID
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@ -36,6 +36,30 @@ Alternatively use the `gradlew build` command to build the project directly.
|
||||
|
||||
This demo app requires that you add your own Google Maps API key. See [Get an API key](https://developers.google.com/maps/documentation/android-sdk/get-api-key) for more instructions.
|
||||
|
||||
# Using Dataset Styles in Android
|
||||
|
||||
This guide explains how to create and apply dataset styles in Android by creating a map style, associating it with a map ID, uploading a dataset, and linking the dataset to the map style.
|
||||
|
||||
## 1. Create a Map ID
|
||||
To create a new map ID, follow the steps in [Create a map ID](https://developers.google.com/maps/documentation/get-map-id#create-a-map-id). Make sure to set the **Map type** to **Android**.
|
||||
|
||||
## 2. Create a New Map Style
|
||||
Follow the instructions in [Manage map styles](https://developers.google.com/maps/documentation/android-sdk/cloud-customization/map-styles) to create a new style and [associate it with the map ID you just created](https://developers.google.com/maps/documentation/android-sdk/cloud-customization/map-styles#associate-style-with-map-id).
|
||||
|
||||
## 3. Upload a Dataset
|
||||
To include data-driven styling in your map:
|
||||
|
||||
1. Upload the dataset on the [Google Maps Platform Datasets](https://console.cloud.google.com/google/maps-apis/datasets) page.
|
||||
2. Confirm that the dataset upload is successful (sometimes there can be issues due to an invalid structure).
|
||||
|
||||
## 4. Link the Dataset to the Map Style
|
||||
To enable data-driven styling:
|
||||
|
||||
1. Open your dataset in the [Google Maps Platform Datasets](https://console.cloud.google.com/google/maps-apis/datasets) page.
|
||||
2. Click on the **Preview** of the dataset.
|
||||
3. Associate the dataset with one of the previously created styles
|
||||
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -48,8 +48,6 @@ android {
|
||||
flavorDimensions.add("version")
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
lint {
|
||||
@ -58,11 +56,16 @@ android {
|
||||
|
||||
kotlinOptions {
|
||||
freeCompilerArgs = listOf("-Xopt-in=kotlin.RequiresOptIn")
|
||||
jvmTarget = JavaVersion.VERSION_21.toString()
|
||||
}
|
||||
|
||||
namespace = "com.example.kotlindemos"
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(21) // Specify the JVM toolchain version
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(libs.appcompat)
|
||||
implementation(libs.kotlinStdlib)
|
||||
@ -70,10 +73,13 @@ dependencies {
|
||||
implementation(libs.recyclerview)
|
||||
implementation(libs.multidex)
|
||||
implementation(libs.volley)
|
||||
implementation(libs.material)
|
||||
|
||||
implementation(libs.lifecycleRuntimeKtx)
|
||||
implementation(libs.mapsKtx)
|
||||
|
||||
implementation(libs.activityKtx)
|
||||
|
||||
// Below is used to run the easypermissions library to manage location permissions
|
||||
// EasyPermissions is needed to help us request for permission to access location
|
||||
implementation(libs.easypermissions)
|
||||
|
||||
@ -32,9 +32,11 @@
|
||||
android:theme="@style/AppTheme">
|
||||
<!--
|
||||
To add your Maps API key to this project:
|
||||
1. Open the root project'sl secrets.properties file
|
||||
1. Open the root project's secrets.properties file
|
||||
2. Add this line, where YOUR_API_KEY is your API key:
|
||||
MAPS_API_KEY=YOUR_API_KEY
|
||||
|
||||
Note: Do not check-in your API key!
|
||||
-->
|
||||
<meta-data
|
||||
android:name="com.google.android.geo.API_KEY"
|
||||
@ -48,7 +50,7 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
|
||||
<activity
|
||||
android:name=".AdvancedMarkersDemoActivity"
|
||||
android:exported="true" />
|
||||
@ -73,6 +75,13 @@
|
||||
<activity
|
||||
android:name=".CircleDemoActivity"
|
||||
android:exported="true" />
|
||||
<activity
|
||||
android:name=".DataDrivenDatasetStylingActivity"
|
||||
android:theme="@style/MaterialAppTheme"
|
||||
android:exported="true" />
|
||||
<activity
|
||||
android:name=".DataDrivenBoundariesActivity"
|
||||
android:exported="true" />
|
||||
<activity
|
||||
android:name=".MarkerCloseInfoWindowOnRetapDemoActivity"
|
||||
android:exported="true" />
|
||||
|
||||
@ -37,7 +37,7 @@ private val BANGKOK = LatLng(13.7563, 100.5018)
|
||||
private val MANILA = LatLng(14.5995, 120.9842)
|
||||
private val HO_CHI_MINH_CITY = LatLng(10.7769, 106.7009)
|
||||
|
||||
const val ZOOM_LEVEL = 3.5f
|
||||
private const val ZOOM_LEVEL = 3.5f
|
||||
|
||||
private val TAG = AdvancedMarkersDemoActivity::class.java.name
|
||||
|
||||
|
||||
@ -0,0 +1,225 @@
|
||||
// Copyright 2025 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.kotlindemos
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.widget.Button
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
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.Feature
|
||||
import com.google.android.gms.maps.model.FeatureClickEvent
|
||||
import com.google.android.gms.maps.model.FeatureLayer
|
||||
import com.google.android.gms.maps.model.FeatureLayerOptions
|
||||
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.MapCapabilities
|
||||
import com.google.android.gms.maps.model.PlaceFeature
|
||||
|
||||
/**
|
||||
* This sample showcases how to use the Data-driven styling for boundaries. For more information
|
||||
* on how the Data-driven styling for boundaries work, check out the following link:
|
||||
* https://developers.google.com/maps/documentation/android-sdk/dds-boundaries/overview
|
||||
*/
|
||||
class DataDrivenBoundariesActivity : AppCompatActivity(), OnMapReadyCallback,
|
||||
FeatureLayer.OnFeatureClickListener {
|
||||
|
||||
|
||||
private lateinit var map: GoogleMap
|
||||
|
||||
private var localityLayer: FeatureLayer? = null
|
||||
|
||||
private var areaLevel1Layer: FeatureLayer? = null
|
||||
|
||||
private var countryLayer: FeatureLayer? = null
|
||||
|
||||
private val HANA_HAWAII = LatLng(20.7522, -155.9877) // Hana, Hawaii
|
||||
private val CENTER_US = LatLng(39.8283, -98.5795) // Approximate geographical center of the contiguous US
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.data_driven_boundaries_demo)
|
||||
|
||||
val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?
|
||||
mapFragment?.getMapAsync(this)
|
||||
|
||||
findViewById<Button>(R.id.button_hawaii).setOnClickListener {
|
||||
centerMapOnLocation(HANA_HAWAII, 13.5f) // Seattle coordinates
|
||||
}
|
||||
|
||||
findViewById<Button>(R.id.button_us).setOnClickListener {
|
||||
centerMapOnLocation(CENTER_US, 1f) // New York coordinates
|
||||
}
|
||||
}
|
||||
|
||||
private fun centerMapOnLocation(location: LatLng, zoomLevel: Float) {
|
||||
map.moveCamera(CameraUpdateFactory.newLatLngZoom(location, zoomLevel))
|
||||
}
|
||||
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
override fun onMapReady(googleMap: GoogleMap) {
|
||||
|
||||
map = googleMap
|
||||
val capabilities: MapCapabilities = map.mapCapabilities
|
||||
println("Data-driven Styling is available: " + capabilities.isDataDrivenStylingAvailable)
|
||||
|
||||
// Get the LOCALITY feature layer.
|
||||
localityLayer = googleMap.getFeatureLayer(
|
||||
FeatureLayerOptions.Builder()
|
||||
.featureType(FeatureType.LOCALITY)
|
||||
.build()
|
||||
)
|
||||
|
||||
// Apply style factory function to LOCALITY layer.
|
||||
styleLocalityLayer()
|
||||
|
||||
// Get the ADMINISTRATIVE_AREA_LEVEL_1 feature layer.
|
||||
areaLevel1Layer = googleMap.getFeatureLayer(
|
||||
FeatureLayerOptions.Builder()
|
||||
.featureType(FeatureType.ADMINISTRATIVE_AREA_LEVEL_1)
|
||||
.build()
|
||||
)
|
||||
|
||||
// Apply style factory function to ADMINISTRATIVE_AREA_LEVEL_1 layer.
|
||||
styleAreaLevel1Layer()
|
||||
|
||||
// Get the COUNTRY feature layer.
|
||||
countryLayer = googleMap.getFeatureLayer(
|
||||
FeatureLayerOptions.Builder()
|
||||
.featureType(FeatureType.COUNTRY)
|
||||
.build()
|
||||
)
|
||||
|
||||
// Register the click event handler for the Country layer.
|
||||
countryLayer?.addOnFeatureClickListener(this)
|
||||
|
||||
// Apply default style to all countries on load to enable clicking.
|
||||
styleCountryLayer()
|
||||
}
|
||||
|
||||
|
||||
private fun styleLocalityLayer() {
|
||||
|
||||
// Create the style factory function.
|
||||
val styleFactory = FeatureLayer.StyleFactory { feature: Feature ->
|
||||
|
||||
// Check if the feature is an instance of PlaceFeature,
|
||||
// which contains a place ID.
|
||||
if (feature is PlaceFeature) {
|
||||
val placeFeature: PlaceFeature = feature
|
||||
|
||||
// Determine if the place ID is for Hana, HI.
|
||||
if (placeFeature.placeId == "ChIJ0zQtYiWsVHkRk8lRoB1RNPo") {
|
||||
// Use FeatureStyle.Builder to configure the FeatureStyle object
|
||||
// returned by the style factory function.
|
||||
return@StyleFactory FeatureStyle.Builder()
|
||||
// Define a style with purple fill at 50% opacity and
|
||||
// solid purple border.
|
||||
.fillColor(0x80810FCB.toInt())
|
||||
.strokeColor(0xFF810FCB.toInt())
|
||||
.build()
|
||||
}
|
||||
}
|
||||
return@StyleFactory null
|
||||
}
|
||||
|
||||
// Apply the style factory function to the feature layer.
|
||||
localityLayer?.featureStyle = styleFactory
|
||||
}
|
||||
|
||||
private fun styleAreaLevel1Layer() {
|
||||
val styleFactory = FeatureLayer.StyleFactory { feature: Feature ->
|
||||
if (feature is PlaceFeature) {
|
||||
val placeFeature: PlaceFeature = feature
|
||||
|
||||
// Return a hueColor in the range [-299,299]. If the value is
|
||||
// negative, add 300 to make the value positive.
|
||||
var hueColor: Int = placeFeature.placeId.hashCode() % 300
|
||||
if (hueColor < 0) {
|
||||
hueColor += 300
|
||||
}
|
||||
return@StyleFactory FeatureStyle.Builder()
|
||||
// Set the fill color for the state based on the hashed hue color.
|
||||
.fillColor(Color.HSVToColor(150, floatArrayOf(hueColor.toFloat(), 1f, 1f)))
|
||||
.build()
|
||||
}
|
||||
return@StyleFactory null
|
||||
}
|
||||
|
||||
// Apply the style factory function to the feature layer.
|
||||
areaLevel1Layer?.featureStyle = styleFactory
|
||||
}
|
||||
|
||||
// Set default fill and border for all countries to ensure that they respond
|
||||
// to click events.
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
private fun styleCountryLayer() {
|
||||
val styleFactory = FeatureLayer.StyleFactory { _: Feature ->
|
||||
return@StyleFactory FeatureStyle.Builder()
|
||||
// Set the fill color for the country as white with a 10% opacity.
|
||||
// This requires minApi 26
|
||||
.fillColor(Color.argb(0.1f, 0f, 0f, 0f))
|
||||
// Set border color to solid black.
|
||||
.strokeColor(Color.BLACK)
|
||||
.build()
|
||||
}
|
||||
|
||||
// Apply the style factory function to the country feature layer.
|
||||
countryLayer?.featureStyle = styleFactory
|
||||
}
|
||||
|
||||
// Define the click event handler.
|
||||
override fun onFeatureClick(event: FeatureClickEvent) {
|
||||
|
||||
// Get the list of features affected by the click using
|
||||
// getPlaceIds() defined below.
|
||||
val selectedPlaceIds = getPlaceIds(event.features)
|
||||
if (selectedPlaceIds.isNotEmpty()) {
|
||||
val styleFactory = FeatureLayer.StyleFactory { feature: Feature ->
|
||||
// Use PlaceFeature to get the placeID of the country.
|
||||
if (feature is PlaceFeature) {
|
||||
if (selectedPlaceIds.contains(feature.placeId)) {
|
||||
return@StyleFactory FeatureStyle.Builder()
|
||||
// Set the fill color to red.
|
||||
.fillColor(Color.RED)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
return@StyleFactory null
|
||||
}
|
||||
|
||||
// Apply the style factory function to the feature layer.
|
||||
countryLayer?.featureStyle = styleFactory
|
||||
}
|
||||
}
|
||||
|
||||
// Get a List of place IDs from the FeatureClickEvent object.
|
||||
private fun getPlaceIds(features: List<Feature>): List<String> {
|
||||
val placeIds: MutableList<String> = ArrayList()
|
||||
for (feature in features) {
|
||||
if (feature is PlaceFeature) {
|
||||
placeIds.add(feature.placeId)
|
||||
}
|
||||
}
|
||||
return placeIds
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,360 @@
|
||||
// Copyright 2025 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.kotlindemos
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.gms.maps.OnMapReadyCallback
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowInsets
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import com.google.android.gms.maps.SupportMapFragment
|
||||
import com.google.android.gms.maps.GoogleMap
|
||||
import com.google.android.gms.maps.CameraUpdateFactory
|
||||
import com.google.android.gms.maps.model.DatasetFeature
|
||||
import com.google.android.gms.maps.model.Feature
|
||||
import com.google.android.gms.maps.model.FeatureClickEvent
|
||||
import com.google.android.gms.maps.model.FeatureLayer
|
||||
import com.google.android.gms.maps.model.FeatureLayerOptions
|
||||
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.MapCapabilities
|
||||
import androidx.core.view.WindowCompat
|
||||
|
||||
|
||||
private val TAG = DataDrivenDatasetStylingActivity::class.java.name
|
||||
|
||||
/**
|
||||
* This sample showcases how to use the Data-driven styling for datasets. For more information
|
||||
* on how the Data-driven styling for boundaries work, check out the following link:
|
||||
* https://developers.google.com/maps/documentation/android-sdk/dds-datasets/overview
|
||||
*/
|
||||
class DataDrivenDatasetStylingActivity : AppCompatActivity(), OnMapReadyCallback, FeatureLayer.OnFeatureClickListener {
|
||||
private lateinit var mapContainer: ViewGroup
|
||||
|
||||
private lateinit var map: GoogleMap
|
||||
private val zoomLevel = 13.5f
|
||||
|
||||
private var datasetLayer: FeatureLayer? = null
|
||||
|
||||
// The global id of the clicked dataset feature.
|
||||
private var lastGlobalId: String? = null
|
||||
|
||||
private data class DataSet(
|
||||
val datasetId: String,
|
||||
val location: LatLng,
|
||||
val callback: DataDrivenDatasetStylingActivity.() -> Unit
|
||||
)
|
||||
|
||||
private val dataSets = mutableMapOf<String, DataSet>()
|
||||
|
||||
private lateinit var buttonLayout: LinearLayout
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
enableEdgeToEdge()
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
if (dataSets.isEmpty()) {
|
||||
with(dataSets) {
|
||||
put(getString(R.string.boulder), DataSet(BuildConfig.BOULDER_DATASET_ID, LatLng(40.0150, -105.2705)) { styleBoulderDataset() })
|
||||
put(getString(R.string.new_york), DataSet(BuildConfig.NEW_YORK_DATASET_ID, LatLng(40.786244, -73.962684)) { styleNYCDataset() })
|
||||
put(getString(R.string.kyoto), DataSet(BuildConfig.KYOTO_DATASET_ID, LatLng(35.005081, 135.764385)) { styleKyotoDataset() })
|
||||
}
|
||||
}
|
||||
|
||||
setContentView(R.layout.data_driven_styling_demo)
|
||||
|
||||
mapContainer = findViewById(R.id.map_container)
|
||||
|
||||
val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?
|
||||
mapFragment?.getMapAsync(this)
|
||||
|
||||
// Set the click listener for each of the buttons
|
||||
listOf(R.id.button_kyoto, R.id.button_ny, R.id.button_boulder).forEach { viewId ->
|
||||
findViewById<Button>(viewId).setOnClickListener { view ->
|
||||
switchToDataset((view as Button).text.toString())
|
||||
}
|
||||
}
|
||||
|
||||
buttonLayout = findViewById<View>(R.id.button_kyoto).parent as LinearLayout;
|
||||
|
||||
handleCutout()
|
||||
}
|
||||
|
||||
private fun handleCutout() {
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
window.decorView.setOnApplyWindowInsetsListener { _, windowInsets ->
|
||||
val insets = windowInsets.getInsets(WindowInsets.Type.systemBars())
|
||||
val topInset = insets.top
|
||||
mapContainer.setPadding(0, topInset, 0, 0)
|
||||
windowInsets
|
||||
}
|
||||
} else {
|
||||
window.decorView.setOnApplyWindowInsetsListener { view, windowInsets ->
|
||||
val topInset = windowInsets.systemWindowInsetTop
|
||||
mapContainer.setPadding(0, topInset, 0, 0)
|
||||
windowInsets
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches the currently displayed dataset on the map to the one identified by the given label.
|
||||
*
|
||||
* This function retrieves a DataSetInfo object from the `dataSets` map using the provided `label`.
|
||||
* If a dataset with the given label exists, it does the following:
|
||||
* 1. Creates a new FeatureLayer for the specified dataset.
|
||||
* 2. Sets the `datasetLayer` property to the newly created FeatureLayer.
|
||||
* 3. Executes the callback function associated with the dataset, passing the current activity instance (this).
|
||||
* 4. Centers the map on the location associated with the dataset.
|
||||
* If no dataset with the given label is found, it displays a Toast message indicating an unknown dataset.
|
||||
*
|
||||
* @param label The label identifying the dataset to switch to. This label should correspond to a key in the `dataSets` map.
|
||||
* @throws IllegalStateException if `map` is not initialized.
|
||||
*/
|
||||
private fun switchToDataset(label: String) {
|
||||
dataSets[label]?.let { dataSet ->
|
||||
datasetLayer = map.getFeatureLayer(
|
||||
with(FeatureLayerOptions.Builder()) {
|
||||
featureType(FeatureType.DATASET)
|
||||
// Specify the dataset ID.
|
||||
datasetId(dataSet.datasetId)
|
||||
}.build()
|
||||
)
|
||||
dataSet.callback(this)
|
||||
centerMapOnLocation(dataSet.location)
|
||||
} ?: run {
|
||||
Toast.makeText(this, "Unknown dataset: $label", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMapReady(googleMap: GoogleMap) {
|
||||
map = googleMap
|
||||
|
||||
val capabilities: MapCapabilities = map.mapCapabilities
|
||||
println("Data-driven Styling is available: " + capabilities.isDataDrivenStylingAvailable)
|
||||
|
||||
switchToDataset("Boulder")
|
||||
|
||||
// Register the click event handler for the Datasets layer.
|
||||
datasetLayer?.addOnFeatureClickListener(this)
|
||||
}
|
||||
|
||||
private fun styleNYCDataset() {
|
||||
data class Style(
|
||||
@ColorInt val fillColor: Int,
|
||||
@ColorInt val strokeColor: Int,
|
||||
val pointRadius: Float,
|
||||
)
|
||||
|
||||
val largePointRadius = 8F
|
||||
val smallPointRadius = 6F
|
||||
val darkRedBrown = resources.getColor(R.color.darkRedBrown)
|
||||
|
||||
val styleFactory = FeatureLayer.StyleFactory { feature: Feature ->
|
||||
if (feature is DatasetFeature) {
|
||||
val furColors: MutableMap<String, String> = feature.datasetAttributes
|
||||
val furColor = furColors["Color"]
|
||||
|
||||
val style = when (furColor) {
|
||||
"Black+" -> Style(Color.BLACK, Color.BLACK, largePointRadius)
|
||||
"Cinnamon+" -> Style(darkRedBrown, darkRedBrown, largePointRadius)
|
||||
"Cinnamon+Gray" -> Style(darkRedBrown, darkRedBrown, smallPointRadius)
|
||||
"Cinnamon+White" -> Style(darkRedBrown, Color.WHITE, smallPointRadius)
|
||||
"Gray+" -> Style(Color.GRAY, Color.YELLOW, largePointRadius) // Default stroke
|
||||
"Gray+Cinnamon" -> Style(Color.GRAY, darkRedBrown, smallPointRadius)
|
||||
"Gray+Cinnamon, White" -> Style(Color.LTGRAY, darkRedBrown, smallPointRadius)
|
||||
"Gray+White" -> Style(Color.GRAY, Color.WHITE, smallPointRadius)
|
||||
else -> Style(Color.GREEN, Color.YELLOW, largePointRadius) // Default style if furColor is null or doesn't match
|
||||
}
|
||||
|
||||
return@StyleFactory FeatureStyle.Builder()
|
||||
.fillColor(style.fillColor)
|
||||
.strokeColor(style.strokeColor)
|
||||
.pointRadius(style.pointRadius)
|
||||
.build()
|
||||
}
|
||||
return@StyleFactory null
|
||||
}
|
||||
|
||||
// Apply the style factory function to the feature layer.
|
||||
datasetLayer?.featureStyle = styleFactory
|
||||
}
|
||||
|
||||
private fun styleKyotoDataset() {
|
||||
|
||||
// Create the style factory function.
|
||||
val styleFactory = FeatureLayer.StyleFactory { feature: Feature ->
|
||||
|
||||
// Check if the feature is an instance of DatasetFeature.
|
||||
if (feature is DatasetFeature) {
|
||||
// Determine the value of the typecategory attribute.
|
||||
val typeCategories: MutableMap<String, String> = feature.datasetAttributes
|
||||
val typeCategory = typeCategories["type"]
|
||||
// Set default colors to green.
|
||||
val fillColor: Int
|
||||
val strokeColor: Int
|
||||
when (typeCategory) {
|
||||
"temple" -> {
|
||||
// Color temples areas blue.
|
||||
fillColor = Color.BLUE
|
||||
strokeColor = Color.BLUE
|
||||
}
|
||||
|
||||
else -> {
|
||||
// Color all other areas green.
|
||||
fillColor = Color.GREEN
|
||||
strokeColor = Color.GREEN
|
||||
}
|
||||
}
|
||||
return@StyleFactory FeatureStyle.Builder()
|
||||
.fillColor(fillColor)
|
||||
.strokeColor(strokeColor)
|
||||
.strokeWidth(2F)
|
||||
.build()
|
||||
}
|
||||
return@StyleFactory null
|
||||
}
|
||||
|
||||
// Apply the style factory function to the feature layer.
|
||||
datasetLayer?.featureStyle = styleFactory
|
||||
}
|
||||
|
||||
private fun styleBoulderDataset() {
|
||||
val EASY = Color.GREEN
|
||||
val MODERATE = Color.BLUE
|
||||
val DIFFICULT = Color.RED
|
||||
|
||||
// Create the style factory function.
|
||||
val styleFactory = FeatureLayer.StyleFactory { feature: Feature ->
|
||||
|
||||
// Set default colors to to yellow and point radius to 8.
|
||||
var fillColor = Color.GREEN
|
||||
var strokeColor = Color.YELLOW
|
||||
var pointRadius = 8F
|
||||
var strokeWidth = 3F
|
||||
// Check if the feature is an instance of DatasetFeature.
|
||||
if (feature is DatasetFeature) {
|
||||
|
||||
val attributes: MutableMap<String, String> = feature.datasetAttributes
|
||||
val difficulty = attributes["OSMPTrailsOSMPDIFFICULTY"]
|
||||
val name = attributes["OSMPTrailsOSMPTRAILNAME"]
|
||||
val dogsAllowed = attributes["OSMPTrailsOSMPDOGREGGEN"]
|
||||
|
||||
when (difficulty) {
|
||||
"Easy" -> {
|
||||
fillColor = EASY
|
||||
}
|
||||
"Moderate" -> {
|
||||
fillColor = MODERATE
|
||||
}
|
||||
"Difficult" -> {
|
||||
fillColor = DIFFICULT
|
||||
}
|
||||
else -> {
|
||||
Log.w(TAG, "$name -> Unknown difficulty: $difficulty")
|
||||
fillColor = Color.MAGENTA
|
||||
}
|
||||
}
|
||||
|
||||
when (dogsAllowed) {
|
||||
"No Dogs" -> {
|
||||
fillColor = ColorUtils.setAlphaComponent(fillColor, 66)
|
||||
strokeWidth = 5f
|
||||
}
|
||||
"LVS" -> {
|
||||
}
|
||||
"LR", "RV" -> {
|
||||
fillColor = ColorUtils.setAlphaComponent(fillColor, 75)
|
||||
}
|
||||
else -> {
|
||||
Log.w(TAG, "$name -> Unknown dogs reg: $dogsAllowed")
|
||||
}
|
||||
}
|
||||
|
||||
strokeColor = fillColor
|
||||
|
||||
return@StyleFactory FeatureStyle.Builder()
|
||||
.fillColor(fillColor)
|
||||
.strokeColor(strokeColor)
|
||||
.pointRadius(pointRadius)
|
||||
.strokeWidth(strokeWidth)
|
||||
.build()
|
||||
}
|
||||
return@StyleFactory null
|
||||
}
|
||||
|
||||
// Apply the style factory function to the feature layer.
|
||||
datasetLayer?.featureStyle = styleFactory
|
||||
}
|
||||
|
||||
|
||||
private fun centerMapOnLocation(location: LatLng) {
|
||||
map.moveCamera(CameraUpdateFactory.newLatLngZoom(location, zoomLevel))
|
||||
}
|
||||
|
||||
// Define the click event handler to set lastGlobalId to globalid of selected feature.
|
||||
override fun onFeatureClick(event: FeatureClickEvent) {
|
||||
// Get the dataset feature affected by the click.
|
||||
val clickFeatures: MutableList<Feature> = event.features
|
||||
lastGlobalId = null
|
||||
if (clickFeatures[0] is DatasetFeature) {
|
||||
lastGlobalId = ((clickFeatures[0] as DatasetFeature).datasetAttributes["globalid"])
|
||||
// Remember to reset the Style Factory.
|
||||
styleDatasetsLayerClickEvent()
|
||||
}
|
||||
}
|
||||
|
||||
// Set fill and border for all features.
|
||||
private fun styleDatasetsLayerClickEvent() {
|
||||
// Create the style factory function.
|
||||
val styleFactory = FeatureLayer.StyleFactory { feature: Feature ->
|
||||
|
||||
// Check if the feature is an instance of DatasetFeature.
|
||||
if (feature is DatasetFeature) {
|
||||
val globalIDs: MutableMap<String, String> = feature.datasetAttributes
|
||||
// Determine globalid attribute.
|
||||
val globalID = globalIDs["globalid"]
|
||||
// Set default colors to to green.
|
||||
var fillColor = Color.GREEN
|
||||
var strokeColor = Color.GREEN
|
||||
if (globalID == lastGlobalId) {
|
||||
// Color selected area blue.
|
||||
fillColor = Color.BLUE
|
||||
strokeColor = Color.BLUE
|
||||
}
|
||||
return@StyleFactory FeatureStyle.Builder()
|
||||
.fillColor(fillColor)
|
||||
.strokeColor(strokeColor)
|
||||
.build()
|
||||
}
|
||||
return@StyleFactory null
|
||||
}
|
||||
|
||||
// Apply the style factory function to the dataset feature layer.
|
||||
datasetLayer?.featureStyle = styleFactory
|
||||
}
|
||||
}
|
||||
@ -67,6 +67,16 @@ class DemoDetailsList {
|
||||
R.string.close_info_window_demo_details,
|
||||
MarkerCloseInfoWindowOnRetapDemoActivity::class.java
|
||||
),
|
||||
DemoDetails(
|
||||
R.string.data_driven_styling_label,
|
||||
R.string.data_driven_styling_details,
|
||||
DataDrivenDatasetStylingActivity::class.java
|
||||
),
|
||||
DemoDetails(
|
||||
R.string.data_driven_boundaries_label,
|
||||
R.string.data_driven_boundaries_details,
|
||||
DataDrivenBoundariesActivity::class.java
|
||||
),
|
||||
DemoDetails(
|
||||
R.string.events_demo_label,
|
||||
R.string.events_demo_details,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
<!--
|
||||
Copyright 2025 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.
|
||||
-->
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:map="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<!-- Map Fragment -->
|
||||
<fragment
|
||||
android:id="@+id/map"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
map:backgroundColor="#fff0b2dd"
|
||||
map:mapId="@string/map_id"
|
||||
class="com.google.android.gms.maps.SupportMapFragment" />
|
||||
|
||||
<!-- Buttons to center the map -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_hawaii"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hawaii" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_us"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="US" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
@ -0,0 +1,84 @@
|
||||
<!--
|
||||
Copyright 2025 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.
|
||||
-->
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:map="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/map_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/top_bar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:title="@string/app_name"
|
||||
app:titleTextColor="?attr/colorOnPrimary"
|
||||
style="@style/Widget.MaterialComponents.Toolbar.Primary"
|
||||
/>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/map"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
map:backgroundColor="#fff0b2dd"
|
||||
map:mapId="@string/map_id"
|
||||
class="com.google.android.gms.maps.SupportMapFragment"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/top_bar" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/button_bar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/top_bar">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_boulder"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="4dp"
|
||||
android:padding="8dp"
|
||||
android:text="@string/boulder" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_ny"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="4dp"
|
||||
android:padding="8dp"
|
||||
android:text="@string/new_york" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_kyoto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="4dp"
|
||||
android:padding="8dp"
|
||||
android:text="@string/kyoto" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Google LLC
|
||||
Copyright 2025 Google LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user