mirror of
https://github.com/googlemaps/android-samples.git
synced 2025-12-08 18:02:20 +00:00
fix: support devices with cutouts for DataDrivenDatasetStylingActivity.java demo (#1979)
* fix: support devices with cutouts for DataDrivenDatasetStylingActivity.java demo * fix: remove unnecessary 'res/' from paths in README.md file * feat(apidemos): enhance DataDrivenBoundariesActivity UI and boundary selection This commit enhances the DataDrivenBoundariesActivity demo with UI and functionality improvements focusing on boundary type selection and visual enhancements. - Implements Material Design theming and UI elements. - Adds boundary type selection via PopupMenu (Locality, Admin Area, Country). - Refactors styling and implements persistent country selection. - Handles system UI insets for improved display. These changes improve the demo's user experience and code structure, better showcasing data-driven boundary styling. * feat(apidemos): configure dataset-specific zoom levels for datasets demo This commit introduces dataset-specific zoom levels to the DataDrivenDatasetStylingActivity, enhancing the user experience when switching between datasets. - Adds a `zoomLevel` field to the `DataSet` class to store the desired zoom level for each dataset. - Updates the `dataSets` array to include appropriate zoom levels for Boulder, New York, and Kyoto datasets. - Modifies the `centerMapOnLocation` method to accept a `zoomLevel` parameter, allowing it to be dynamically set. - Updates the `switchDataSet` method to utilize the `zoomLevel` from the selected `DataSet` when centering the map, ensuring the map zooms to the optimal level for each dataset. - Removes the previously hardcoded `ZOOM_LEVEL` constant, as the zoom level is now dataset-dependent. These changes ensure that when a user selects a dataset, the map automatically zooms to a relevant level for that specific dataset, improving clarity and usability of the demo. Also adds missing copyright header.
This commit is contained in:
parent
45d85ac59c
commit
683b21da11
@ -58,8 +58,9 @@ dependencies {
|
||||
implementation(libs.appcompat)
|
||||
implementation(libs.recyclerview)
|
||||
implementation(libs.volley)
|
||||
implementation(platform(libs.kotlinBom))
|
||||
implementation(libs.playServicesMaps)
|
||||
implementation(libs.material)
|
||||
implementation(libs.activity)
|
||||
|
||||
// Tests
|
||||
testImplementation(libs.junit)
|
||||
|
||||
@ -92,10 +92,12 @@ limitations under the License.
|
||||
android:label="@string/circle_demo_label" />
|
||||
<activity
|
||||
android:name=".DataDrivenBoundariesActivity"
|
||||
android:theme="@style/MaterialAppTheme"
|
||||
android:exported="true"
|
||||
android:label="@string/data_driven_boundaries_label" />
|
||||
<activity
|
||||
android:name=".DataDrivenDatasetStylingActivity"
|
||||
android:theme="@style/MaterialAppTheme"
|
||||
android:exported="true"
|
||||
android:label="@string/data_driven_styling_label" />
|
||||
<activity
|
||||
|
||||
@ -41,7 +41,6 @@ public class ApiDemoApplication extends Application {
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Log.d(TAG, "onCreate called");
|
||||
checkApiKey();
|
||||
}
|
||||
|
||||
|
||||
@ -13,13 +13,23 @@
|
||||
// limitations under the License.
|
||||
package com.example.mapdemo;
|
||||
|
||||
import static java.lang.Math.round;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import com.google.android.gms.maps.CameraUpdateFactory;
|
||||
import com.google.android.gms.maps.GoogleMap;
|
||||
@ -34,9 +44,12 @@ 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 com.google.android.material.button.MaterialButton;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This sample showcases how to use the Data-driven styling for boundaries. For more information
|
||||
@ -45,7 +58,11 @@ import java.util.List;
|
||||
*/
|
||||
// [START maps_android_data_driven_styling_boundaries]
|
||||
public class DataDrivenBoundariesActivity extends AppCompatActivity implements OnMapReadyCallback,
|
||||
FeatureLayer.OnFeatureClickListener {
|
||||
FeatureLayer.OnFeatureClickListener, PopupMenu.OnMenuItemClickListener {
|
||||
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
|
||||
|
||||
private GoogleMap map;
|
||||
|
||||
@ -53,73 +70,146 @@ public class DataDrivenBoundariesActivity extends AppCompatActivity implements O
|
||||
private FeatureLayer areaLevel1Layer = null;
|
||||
private FeatureLayer countryLayer = null;
|
||||
|
||||
private static final String TAG = DataDrivenBoundariesActivity.class.getName();
|
||||
private final FeatureLayer.StyleFactory localityStyleFactory = getLocalityStyleFactory();
|
||||
private final FeatureLayer.StyleFactory countryStyleFactory = getCountryStyleFactory();
|
||||
private final FeatureLayer.StyleFactory areaLevel1StyleFactory = getAreaLevel1StyleFactory();
|
||||
|
||||
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
|
||||
// Which layers are currently enabled
|
||||
private boolean localityEnabled = true;
|
||||
private boolean adminAreaEnabled = false;
|
||||
private boolean countryEnabled = false;
|
||||
|
||||
private final Set<String> selectedPlaceIds = new HashSet<>();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
setContentView(R.layout.data_driven_boundaries_demo);
|
||||
|
||||
// [START_EXCLUDE silent]
|
||||
if (getString(R.string.map_id).equals("DEMO_MAP_ID")) {
|
||||
// This demo will not work if the map id is not set.
|
||||
Toast.makeText(this, "Map ID is not set. See README for instructions.", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
// [END_EXCLUDE]
|
||||
|
||||
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_hawaii).setOnClickListener(view -> centerMapOnLocation(HANA_HAWAII, 11f));
|
||||
findViewById(R.id.button_us).setOnClickListener(view -> centerMapOnLocation(CENTER_US, 1f));
|
||||
|
||||
applyInsets(findViewById(R.id.map_container));
|
||||
|
||||
// [START_EXCLUDE silent]
|
||||
setupBoundarySelectorButton();
|
||||
// [END_EXCLUDE]
|
||||
}
|
||||
|
||||
// [START_EXCLUDE silent]
|
||||
private void setupBoundarySelectorButton() {
|
||||
MaterialButton stylingTypeButton = findViewById(R.id.button_feature_type);
|
||||
stylingTypeButton.setOnClickListener(v -> {
|
||||
PopupMenu popupMenu = new PopupMenu(this, v);
|
||||
MenuInflater inflater = popupMenu.getMenuInflater();
|
||||
inflater.inflate(R.menu.boundary_types_menu, popupMenu.getMenu());
|
||||
|
||||
popupMenu.setOnMenuItemClickListener(this);
|
||||
|
||||
popupMenu.getMenu().findItem(R.id.boundary_type_locality).setChecked(localityEnabled);
|
||||
popupMenu.getMenu().findItem(R.id.boundary_type_administrative_area_level_1).setChecked(adminAreaEnabled);
|
||||
popupMenu.getMenu().findItem(R.id.boundary_type_country).setChecked(countryEnabled);
|
||||
popupMenu.show();
|
||||
});
|
||||
}
|
||||
// [END_EXCLUDE]
|
||||
|
||||
private void centerMapOnLocation(LatLng location, float zoomLevel) {
|
||||
map.moveCamera(CameraUpdateFactory.newLatLngZoom(location, zoomLevel));
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
@Override
|
||||
public void onMapReady(GoogleMap googleMap) {
|
||||
public void onMapReady(@NonNull GoogleMap googleMap) {
|
||||
this.map = googleMap;
|
||||
MapCapabilities capabilities = map.getMapCapabilities();
|
||||
Log.d(TAG, "Data-driven Styling is available: " + capabilities.isDataDrivenStylingAvailable());
|
||||
|
||||
// Get the LOCALITY feature layer.
|
||||
if (!capabilities.isDataDrivenStylingAvailable()) {
|
||||
Toast.makeText(
|
||||
this,
|
||||
"Data-driven Styling is not available. See README.md for instructions.",
|
||||
Toast.LENGTH_LONG
|
||||
).show();
|
||||
}
|
||||
|
||||
// Gets 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.
|
||||
// Gets 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.
|
||||
// Gets 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();
|
||||
centerMapOnLocation(HANA_HAWAII, 11f);
|
||||
|
||||
// Apply the current set of styles.
|
||||
updateStyles();
|
||||
}
|
||||
|
||||
private void styleLocalityLayer() {
|
||||
// Create the style factory function.
|
||||
FeatureLayer.StyleFactory styleFactory = feature -> {
|
||||
/**
|
||||
* Updates the styles of the locality, area level 1, and country layers based on the current
|
||||
* state of the `localityEnabled`, `adminAreaEnabled`, and `countryEnabled` flags.
|
||||
* <p>
|
||||
* For each layer, if the corresponding flag is true, the layer's features will be styled using
|
||||
* the layer specific style factory function.
|
||||
*/
|
||||
private void updateStyles() {
|
||||
if (localityLayer != null && areaLevel1Layer != null && countryLayer != null) {
|
||||
localityLayer.setFeatureStyle(localityEnabled ? localityStyleFactory : null);
|
||||
areaLevel1Layer.setFeatureStyle(adminAreaEnabled ? areaLevel1StyleFactory : null);
|
||||
if (countryEnabled) {
|
||||
countryLayer.setFeatureStyle(countryStyleFactory);
|
||||
} else {
|
||||
countryLayer.setFeatureStyle(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a StyleFactory for a FeatureLayer that styles Hana, HI on its Place ID.
|
||||
* <p>
|
||||
* This method defines a style factory that checks if a given feature is a {@link PlaceFeature}.
|
||||
* and if that feature matches "ChIJ0zQtYiWsVHkRk8lRoB1RNPo" (Hana, HI) applies a specific style.
|
||||
* Otherwise, it returns null, indicating no specific styling is applied.
|
||||
*
|
||||
* @return A {@link FeatureLayer.StyleFactory} instance that can be used to style features in a FeatureLayer.
|
||||
* The factory returns a {@link FeatureStyle} for Hana, HI, and null for other features.
|
||||
*/
|
||||
private static FeatureLayer.StyleFactory getLocalityStyleFactory() {
|
||||
int purple = 0x810FCB;
|
||||
// Define a style with purple fill at 50% opacity and
|
||||
// solid purple border.
|
||||
int fillColor = setAlphaValueOnColor(purple, 0.5f);
|
||||
int strokeColor = setAlphaValueOnColor(purple, 1f);
|
||||
|
||||
return feature -> {
|
||||
// Check if the feature is an instance of PlaceFeature,
|
||||
// which contains a place ID.
|
||||
if (feature instanceof PlaceFeature placeFeature) {
|
||||
@ -129,24 +219,26 @@ public class DataDrivenBoundariesActivity extends AppCompatActivity implements O
|
||||
// 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)
|
||||
.fillColor(fillColor)
|
||||
.strokeColor(strokeColor)
|
||||
.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 -> {
|
||||
/**
|
||||
* Creates a StyleFactory for area level 1 features (e.g., states, provinces).
|
||||
* <p>
|
||||
* This factory provides a semi-transparent fill color for each area level 1 feature.
|
||||
* <p>
|
||||
* @return A StyleFactory that can be used to style area level 1 features on a map.
|
||||
*/
|
||||
private static FeatureLayer.StyleFactory getAreaLevel1StyleFactory() {
|
||||
int alpha = (int) (255 * 0.25);
|
||||
|
||||
return feature -> {
|
||||
if (feature instanceof PlaceFeature placeFeature) {
|
||||
|
||||
// Return a hueColor in the range [-299,299]. If the value is
|
||||
@ -157,64 +249,61 @@ public class DataDrivenBoundariesActivity extends AppCompatActivity implements O
|
||||
}
|
||||
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}))
|
||||
.fillColor(Color.HSVToColor(alpha, 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);
|
||||
}
|
||||
/**
|
||||
* Creates a StyleFactory for styling country features on a FeatureLayer highlighting selected
|
||||
* countries. Selection is determined via the selectedPlaceIds set.
|
||||
* <p>
|
||||
* *Note:* If the set of selected countries changes, this function must be called to update the
|
||||
* styling.
|
||||
* <p>
|
||||
* @return A FeatureLayer.StyleFactory that can be used to style country features.
|
||||
*/
|
||||
private FeatureLayer.StyleFactory getCountryStyleFactory() {
|
||||
int defaultFillColor = setAlphaValueOnColor(Color.BLACK, 0.1f);
|
||||
int selectedFillColor = setAlphaValueOnColor(Color.RED, 0.33f);
|
||||
return feature -> {
|
||||
if (feature instanceof PlaceFeature) {
|
||||
int fillColor = selectedPlaceIds.contains(((PlaceFeature) feature).getPlaceId()) ? selectedFillColor : defaultFillColor;
|
||||
FeatureStyle.Builder build = new FeatureStyle.Builder();
|
||||
return build.fillColor(fillColor).strokeColor(Color.BLACK).build();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
// Define the click event handler.
|
||||
/**
|
||||
* Called when a feature is clicked on the map. It is only applied to the country layer.
|
||||
* <p>
|
||||
* Each time a country is clicked, its place ID is added to the selectedPlaceIds set or removed
|
||||
* if it was already present. Each time the set is
|
||||
* <p>
|
||||
*/
|
||||
@Override
|
||||
public void onFeatureClick(FeatureClickEvent event) {
|
||||
public void onFeatureClick(@NonNull 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;
|
||||
};
|
||||
List<String> newSelectedPlaceIds = getPlaceIds(event.getFeatures());
|
||||
|
||||
// Apply the style factory function to the feature layer.
|
||||
if (countryLayer != null) {
|
||||
countryLayer.setFeatureStyle(styleFactory);
|
||||
for (String placeId : newSelectedPlaceIds) {
|
||||
if (selectedPlaceIds.contains(placeId)) {
|
||||
selectedPlaceIds.remove(placeId);
|
||||
} else {
|
||||
selectedPlaceIds.add(placeId);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the feature styling
|
||||
countryLayer.setFeatureStyle(countryStyleFactory);
|
||||
}
|
||||
|
||||
// Get a List of place IDs from the FeatureClickEvent object.
|
||||
// Gets 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) {
|
||||
@ -224,5 +313,59 @@ public class DataDrivenBoundariesActivity extends AppCompatActivity implements O
|
||||
}
|
||||
return placeIds;
|
||||
}
|
||||
|
||||
private static int setAlphaValueOnColor(int color, float alpha) {
|
||||
return (color & 0x00ffffff) | (round(alpha * 255) << 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies insets to the container view to properly handle window insets.
|
||||
*
|
||||
* @param container the container view to apply insets to
|
||||
*/
|
||||
private static void applyInsets(View container) {
|
||||
ViewCompat.setOnApplyWindowInsetsListener(container,
|
||||
(view, insets) -> {
|
||||
Insets innerPadding = insets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout());
|
||||
view.setPadding(innerPadding.left, innerPadding.top, innerPadding.right, innerPadding.bottom);
|
||||
return insets;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the click events for menu items in the boundary type selection menu.
|
||||
* This method is called when a user selects a boundary type (locality, administrative area, or country) from the menu.
|
||||
* It toggles the checked state of the selected menu item and updates the corresponding boolean flags (localityEnabled, adminAreaEnabled, countryEnabled).
|
||||
* Finally, it calls the {@link #updateStyles()} method to reflect the changes in the map's display.
|
||||
*
|
||||
* @param item The MenuItem that was clicked.
|
||||
* @return True if the event was handled, false otherwise. In this case it always return true if one of the correct items was selected.
|
||||
*/ // [START_EXCLUDE silent]
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
Log.d(TAG, "onMenuItemClick: " + item.getItemId());
|
||||
int id = item.getItemId();
|
||||
boolean result = false;
|
||||
|
||||
if (id == R.id.boundary_type_locality) {
|
||||
item.setChecked(!item.isChecked());
|
||||
localityEnabled = item.isChecked();
|
||||
result = true;
|
||||
} else if (id == R.id.boundary_type_administrative_area_level_1) {
|
||||
item.setChecked(!item.isChecked());
|
||||
adminAreaEnabled = item.isChecked();
|
||||
result = true;
|
||||
} else if (id == R.id.boundary_type_country) {
|
||||
item.setChecked(!item.isChecked());
|
||||
countryEnabled = item.isChecked();
|
||||
result = true;
|
||||
}
|
||||
|
||||
updateStyles();
|
||||
|
||||
return result;
|
||||
}
|
||||
// [END_EXCLUDE]
|
||||
}
|
||||
// [END maps_android_data_driven_styling_boundaries]
|
||||
@ -16,12 +16,17 @@ package com.example.mapdemo;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import com.google.android.gms.maps.CameraUpdateFactory;
|
||||
import com.google.android.gms.maps.GoogleMap;
|
||||
@ -54,6 +59,7 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
|
||||
String label,
|
||||
String datasetId,
|
||||
LatLng location,
|
||||
float zoomLevel,
|
||||
DataDrivenDatasetStylingActivity.DataSet.StylingCallback callback) {
|
||||
public interface StylingCallback {
|
||||
void styleDatasetLayer();
|
||||
@ -81,9 +87,9 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
|
||||
* 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),
|
||||
new DataSet("Boulder", BuildConfig.BOULDER_DATASET_ID, new LatLng(40.0150, -105.2705), 11f, this::styleBoulderDatasetLayer),
|
||||
new DataSet("New York", BuildConfig.NEW_YORK_DATASET_ID, new LatLng(40.786244, -73.962684), 14f, this::styleNYCDatasetLayer),
|
||||
new DataSet("Kyoto", BuildConfig.KYOTO_DATASET_ID, new LatLng(35.005081, 135.764385), 13.5f, this::styleKyotoDatasetsLayer),
|
||||
};
|
||||
|
||||
private DataSet findDataSetByLabel(String label) {
|
||||
@ -95,7 +101,6 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
|
||||
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;
|
||||
@ -104,8 +109,16 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
setContentView(R.layout.data_driven_styling_demo);
|
||||
|
||||
// [START_EXCLUDE silent]
|
||||
if (getString(R.string.map_id).equals("DEMO_MAP_ID")) {
|
||||
// This demo will not work if the map id is not set.
|
||||
Toast.makeText(this, "Map ID is not set. See README for instructions.", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
// [END_EXCLUDE]
|
||||
|
||||
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
|
||||
if (mapFragment != null) {
|
||||
mapFragment.getMapAsync(this);
|
||||
@ -115,6 +128,18 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
|
||||
for (int buttonId : buttonIds) {
|
||||
findViewById(buttonId).setOnClickListener(view -> switchDataSet(((Button) view).getText().toString()));
|
||||
}
|
||||
|
||||
applyInsets(findViewById(R.id.map_container));
|
||||
}
|
||||
|
||||
private static void applyInsets(View container) {
|
||||
ViewCompat.setOnApplyWindowInsetsListener(container,
|
||||
(view, insets) -> {
|
||||
Insets innerPadding = insets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout());
|
||||
view.setPadding(innerPadding.left, innerPadding.top, innerPadding.right, innerPadding.bottom);
|
||||
return insets;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -142,7 +167,7 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
|
||||
.build()
|
||||
);
|
||||
dataSet.callback.styleDatasetLayer();
|
||||
centerMapOnLocation(dataSet.location());
|
||||
centerMapOnLocation(dataSet.location(), dataSet.zoomLevel());
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,6 +177,13 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
|
||||
|
||||
MapCapabilities capabilities = map.getMapCapabilities();
|
||||
Log.d(TAG, "Data-driven Styling is available: " + capabilities.isDataDrivenStylingAvailable());
|
||||
if (!capabilities.isDataDrivenStylingAvailable()) {
|
||||
Toast.makeText(
|
||||
this,
|
||||
"Data-driven Styling is not available. See README.md for instructions.",
|
||||
Toast.LENGTH_LONG
|
||||
).show();
|
||||
}
|
||||
|
||||
// Switch to the default dataset which must happen before adding the feature click listener
|
||||
switchDataSet("Boulder");
|
||||
@ -270,8 +302,8 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
|
||||
// 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;
|
||||
int fillColor;
|
||||
int strokeColor;
|
||||
float pointRadius = 8F;
|
||||
float strokeWidth = 3F;
|
||||
|
||||
@ -323,8 +355,8 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
|
||||
}
|
||||
|
||||
|
||||
private void centerMapOnLocation(LatLng location) {
|
||||
map.moveCamera(CameraUpdateFactory.newLatLngZoom(location, ZOOM_LEVEL));
|
||||
private void centerMapOnLocation(LatLng location, float zoomLevel) {
|
||||
map.moveCamera(CameraUpdateFactory.newLatLngZoom(location, zoomLevel));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M7,10l5,5 5,-5z"/>
|
||||
|
||||
</vector>
|
||||
@ -14,18 +14,38 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<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">
|
||||
<!-- Map Fragment -->
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
>
|
||||
|
||||
<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/data_driven_boundaries_label"
|
||||
app:titleTextColor="?attr/colorOnPrimary"
|
||||
style="@style/Widget.MaterialComponents.Toolbar.Primary"
|
||||
/>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/map"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
map:backgroundColor="#fff0b2dd"
|
||||
map:mapId="@string/map_id"
|
||||
class="com.google.android.gms.maps.SupportMapFragment" />
|
||||
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" />
|
||||
|
||||
<!-- Buttons to center the map -->
|
||||
<LinearLayout
|
||||
@ -34,20 +54,33 @@
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<Button
|
||||
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_hawaii"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hawaii" />
|
||||
android:layout_margin="4dp"
|
||||
android:text="@string/hawaii" />
|
||||
|
||||
<Button
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_us"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="US" />
|
||||
android:layout_margin="4dp"
|
||||
android:text="@string/united_states" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_feature_type"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableEnd="@drawable/baseline_arrow_drop_down_24"
|
||||
android:layout_margin="4dp"
|
||||
android:text="@string/boundary_type" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@ -14,46 +14,68 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<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">
|
||||
<!-- Map Fragment -->
|
||||
|
||||
<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/data_driven_styling_label"
|
||||
app:titleTextColor="?attr/colorOnPrimary"
|
||||
style="@style/Widget.MaterialComponents.Toolbar.Primary"
|
||||
/>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/map"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
map:backgroundColor="#fff0b2dd"
|
||||
map:mapId="@string/map_id"
|
||||
class="com.google.android.gms.maps.SupportMapFragment" />
|
||||
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" />
|
||||
|
||||
<!-- Buttons to center the map -->
|
||||
<LinearLayout
|
||||
android:id="@+id/button_bar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
android:padding="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/top_bar">
|
||||
|
||||
<Button
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_boulder"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Boulder" />
|
||||
android:layout_margin="4dp"
|
||||
android:text="@string/boulder" />
|
||||
|
||||
<Button
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_ny"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="New York" />
|
||||
android:layout_margin="4dp"
|
||||
android:text="@string/new_york" />
|
||||
|
||||
<Button
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_kyoto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Kyoto" />
|
||||
android:layout_margin="4dp"
|
||||
android:text="@string/kyoto" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
46
ApiDemos/java/app/src/main/res/menu/boundary_types_menu.xml
Normal file
46
ApiDemos/java/app/src/main/res/menu/boundary_types_menu.xml
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<menu xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<group android:checkableBehavior="all">
|
||||
<item
|
||||
android:id="@+id/boundary_type_locality"
|
||||
android:title="@string/locality"
|
||||
app:showAsAction="never"
|
||||
android:checked="false"
|
||||
android:checkable="true"
|
||||
/>
|
||||
<item
|
||||
android:id="@+id/boundary_type_administrative_area_level_1"
|
||||
android:title="@string/administrative_area_level_1"
|
||||
android:titleCondensed="Admin1"
|
||||
app:showAsAction="never"
|
||||
android:checked="false"
|
||||
android:checkable="true"
|
||||
/>
|
||||
<item
|
||||
android:id="@+id/boundary_type_country"
|
||||
android:title="@string/country"
|
||||
app:showAsAction="never"
|
||||
android:checked="false"
|
||||
android:checkable="true"
|
||||
/>
|
||||
</group>
|
||||
|
||||
</menu>
|
||||
@ -301,4 +301,17 @@
|
||||
<!-- 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>
|
||||
|
||||
<!-- Data Driven Dataset Styling -->
|
||||
<string name="kyoto">Kyoto</string>
|
||||
<string name="new_york">New York</string>
|
||||
<string name="boulder">Boulder</string>
|
||||
|
||||
<!-- Data Driven Boundaries Styling -->
|
||||
<string name="hawaii">Hawaii</string>
|
||||
<string name="united_states">US</string>
|
||||
<string name="locality">Locality</string>
|
||||
<string name="administrative_area_level_1">Administrative Area Level 1</string>
|
||||
<string name="country">Country</string>
|
||||
<string name="boundary_type">Boundary</string>
|
||||
</resources>
|
||||
|
||||
@ -23,4 +23,9 @@
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
||||
|
||||
<style name="MaterialAppTheme" parent="Theme.Material3.DynamicColors.DayNight.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
@ -1,20 +1,21 @@
|
||||
[versions]
|
||||
activity = "1.10.0"
|
||||
androidxJunit = "1.2.1"
|
||||
appcompat = "1.7.0"
|
||||
espresso = "3.6.1"
|
||||
junit = "4.13.2"
|
||||
material = "1.12.0"
|
||||
playServicesMaps = "19.0.0"
|
||||
recyclerview = "1.4.0"
|
||||
volley = "1.2.1"
|
||||
kotlinBom = "2.0.21"
|
||||
playServicesMaps = "19.0.0"
|
||||
junit = "4.13.2"
|
||||
androidxJunit = "1.2.1"
|
||||
espresso = "3.6.1"
|
||||
|
||||
|
||||
[libraries]
|
||||
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
||||
recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" }
|
||||
volley = { group = "com.android.volley", name = "volley", version.ref = "volley" }
|
||||
kotlinBom = { group = "org.jetbrains.kotlin", name = "kotlin-bom", version.ref = "kotlinBom" }
|
||||
playServicesMaps = { group = "com.google.android.gms", name = "play-services-maps", version.ref = "playServicesMaps" }
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
activity = { module = "androidx.activity:activity", version.ref = "activity" }
|
||||
androidxJunit = { group = "androidx.test.ext", name = "junit", version.ref = "androidxJunit" }
|
||||
espressoCore = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso" }
|
||||
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
||||
espressoCore = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso" }
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||
playServicesMaps = { group = "com.google.android.gms", name = "play-services-maps", version.ref = "playServicesMaps" }
|
||||
recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" }
|
||||
volley = { group = "com.android.volley", name = "volley", version.ref = "volley" }
|
||||
@ -28,7 +28,7 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:title="@string/app_name"
|
||||
app:title="@string/data_driven_styling_label"
|
||||
app:titleTextColor="?attr/colorOnPrimary"
|
||||
style="@style/Widget.MaterialComponents.Toolbar.Primary"
|
||||
/>
|
||||
|
||||
@ -10,110 +10,43 @@ polygons) based on the data associated with those features.
|
||||
|
||||
* **`boulder_polylines.geojson`:** This GeoJSON file contains data about trails in Boulder,
|
||||
Colorado. Each feature in the file represents a trail, and the geometry is likely a polyline (a
|
||||
series of connected points). The file might also include attributes like trail name, difficulty,
|
||||
series of connected points). The file also includes attributes like trail name, difficulty,
|
||||
and length. This data can be used to create a map where trails are displayed as lines, and the
|
||||
appearance of the lines (color, thickness, pattern) can be customized based on the trail's
|
||||
attributes.
|
||||
|
||||
* **`kyoto_polygons.geojson`:** This GeoJSON file contains data about temples in Kyoto, Japan. Each
|
||||
feature in the file represents a temple, and the geometry is likely a polygon (an enclosed area).
|
||||
The file might also include attributes like temple name, founding date, and architectural style.
|
||||
This data can be used to create a map where temples are displayed as polygons, and the appearance
|
||||
of the polygons (fill color, border color) can be customized based on the temple's attributes."
|
||||
feature in the file represents a temple, and the geometry is a polygon (an enclosed area).
|
||||
|
||||
**Uploading Data to Google Cloud Console and Using it with Google Maps:**
|
||||
|
||||
To use this data with data-driven styling in Google Maps, you'll need to upload it to the Google
|
||||
Cloud Console and create a dataset. Here's a general outline of the process:
|
||||
|
||||
1. **Go to the Google Cloud Console:** Open the Google Cloud Console in your web browser.
|
||||
## 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 Project (If Needed):** If you don't already have a project, create one.
|
||||
## 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. **Enable the Maps Platform:** Make sure the Maps Platform is enabled for your project.
|
||||
## 3. Upload a Dataset
|
||||
To include data-driven styling in your map:
|
||||
|
||||
4. **Go to the "Datasets" page:** In the Cloud Console, navigate to the "Datasets" page (you can
|
||||
search for it).
|
||||
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).
|
||||
|
||||
5. **Create a Dataset:** Click "Create Dataset" and choose the appropriate type based on your data (
|
||||
e.g., "Point dataset" for `new_york_points.csv`, "Polyline dataset" for
|
||||
`boulder_polylines.geojson`, "Polygon dataset" for `kyoto_polygons.geojson`).
|
||||
## 4. Link the Dataset to the Map Style
|
||||
To enable data-driven styling:
|
||||
|
||||
6. **Upload Your Data:** Follow the instructions to upload your data file. You might need to specify
|
||||
the data format (CSV or GeoJSON) and how to interpret the columns (e.g., which column contains
|
||||
latitude and longitude).
|
||||
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
|
||||
|
||||
7. **Create a Dataset ID:** Once the data is uploaded, you'll get a Dataset ID. This is a unique
|
||||
identifier for your dataset.
|
||||
|
||||
8. **Use the Dataset ID in Your Code:** In your Android code, when you create a
|
||||
`FeatureLayerOptions` object, use the `datasetId()` method to set the Dataset ID. This will link
|
||||
your map layer to the dataset you uploaded.
|
||||
|
||||
9. **Apply Data-Driven Styling:** Use the `StyleFactory` to define how to style the features in your
|
||||
layer based on their attributes. The `StyleFactory` provides access to the feature's properties,
|
||||
which you can use to determine the appropriate styling.
|
||||
|
||||
**Important Notes:**
|
||||
|
||||
* **Data Preparation:** Make sure your data is properly formatted (CSV or GeoJSON) and that it
|
||||
includes the necessary columns (latitude, longitude, and any attributes you want to use for
|
||||
styling).
|
||||
* **Dataset Types:** Choose the correct dataset type when creating the dataset in the Cloud Console.
|
||||
This will ensure that the data is interpreted correctly.
|
||||
* **Dataset IDs:** Keep track of your Dataset IDs, as you'll need them to link your map layers to
|
||||
the correct datasets.
|
||||
* **Styling:** Data-driven styling is very powerful. You can create complex and dynamic map styles
|
||||
based on your data. Refer to the Google Maps documentation for more information and examples.
|
||||
|
||||
By following these steps, you can upload your data to the Google Cloud Console, create datasets, and
|
||||
use those datasets to create beautiful and informative maps with data-driven styling in your Android
|
||||
application.
|
||||
|
||||
|
||||
|
||||
## Using Dataset Styles in Android
|
||||
|
||||
This guide explains how to create and apply dataset styles in Android. You'll learn how to create a map style, associate it with a map ID, upload datasets, and link the datasets to the map style to enable data-driven styling.
|
||||
|
||||
### Sample Datasets
|
||||
|
||||
This directory contains sample datasets for demonstrating data-driven styling:
|
||||
|
||||
* **`new_york_points.csv`:** This CSV file contains data about squirrel sightings in New York City. Each row represents a sighting, and the columns likely include information like location (latitude and longitude), date, and other details about the squirrel (e.g., color, size). This data can be used to create a map where each squirrel sighting is represented by a point, and the appearance of the point (color, icon) can be customized based on the squirrel's attributes.
|
||||
|
||||
* **`boulder_polylines.geojson`:** This GeoJSON file contains data about trails in Boulder, Colorado. Each feature in the file represents a trail, and the geometry is likely a polyline (a series of connected points). The file might also include attributes like trail name, difficulty, and length. This data can be used to create a map where trails are displayed as lines, and the appearance of the lines (color, thickness, pattern) can be customized based on the trail's attributes.
|
||||
|
||||
* **`kyoto_polygons.geojson`:** This GeoJSON file contains data about temples in Kyoto, Japan. Each feature in the file represents a temple, and the geometry is likely a polygon (an enclosed area). The file might also include attributes like temple name, founding date, and architectural style. This data can be used to create a map where temples are displayed as polygons, and the appearance of the polygons (fill color, border color) can be customized based on the temple's attributes.
|
||||
|
||||
### Steps to Enable Data-Driven Styling
|
||||
|
||||
1. **Create a 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.
|
||||
* [Associate the new style 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:**
|
||||
|
||||
* Go to the [Google Maps Platform Datasets](https://console.cloud.google.com/google/maps-apis/datasets) page in the Google Cloud Console.
|
||||
* Click "Create Dataset" and choose the appropriate type based on your data (e.g., "Point dataset" for `new_york_points.csv`, "Polyline dataset" for `boulder_polylines.geojson`, "Polygon dataset" for `kyoto_polygons.geojson`).
|
||||
* Upload your data file, specifying the data format (CSV or GeoJSON) and how to interpret the columns.
|
||||
* Confirm that the dataset upload is successful.
|
||||
|
||||
4. **Link the Dataset to the Map Style:**
|
||||
|
||||
* On the [Datasets](https://console.cloud.google.com/google/maps-apis/datasets) page, click on the **Preview** of your dataset.
|
||||
* Associate the dataset with one of the map styles you created.
|
||||
|
||||
**Important Notes:**
|
||||
|
||||
* **Data Preparation:** Ensure your data is properly formatted (CSV or GeoJSON) and includes the necessary columns (latitude, longitude, and any attributes you want to use for styling).
|
||||
* **Dataset Types:** Choose the correct dataset type when creating the dataset.
|
||||
* **Dataset IDs:** You'll need the Dataset ID to link your map layers to the correct datasets in your Android code.
|
||||
* **Styling:** Use the `StyleFactory` in your Android code to define how to style features based on their attributes.
|
||||
|
||||
By following these steps, you can upload your data, create datasets, and use them to create informative maps with data-driven styling in your Android application.
|
||||
## 5. Set the Dataset ID in the secrets.properties file
|
||||
```
|
||||
BOULDER_DATASET_ID=<BOULDER_DATASET_ID>
|
||||
NEW_YORK_DATASET_ID=<NEW_YORK_DATASET_ID>
|
||||
KYOTO_DATASET_ID=<KYOTO_DATASET_ID>
|
||||
```
|
||||
** Important: ** the map ID set in the strings.xml file must match the maps ID associated with the style.
|
||||
Loading…
x
Reference in New Issue
Block a user