Skip to content
This repository was archived by the owner on Oct 7, 2024. It is now read-only.

Commit aea0eba

Browse files
langsmithLangston Smith
authored andcommitted
refactored MatrixApiActivity and XML
1 parent c3332c5 commit aea0eba

File tree

3 files changed

+100
-88
lines changed

3 files changed

+100
-88
lines changed

MapboxAndroidDemo/src/main/java/com/mapbox/mapboxandroiddemo/examples/javaservices/MatrixApiActivity.java

Lines changed: 98 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,8 @@
11
package com.mapbox.mapboxandroiddemo.examples.javaservices;
22

33
import android.content.Context;
4+
import android.graphics.BitmapFactory;
45
import android.os.Bundle;
5-
import androidx.annotation.NonNull;
6-
import androidx.appcompat.app.AppCompatActivity;
7-
import androidx.cardview.widget.CardView;
8-
import androidx.recyclerview.widget.DefaultItemAnimator;
9-
import androidx.recyclerview.widget.LinearLayoutManager;
10-
import androidx.recyclerview.widget.LinearSnapHelper;
11-
import androidx.recyclerview.widget.RecyclerView;
12-
import androidx.recyclerview.widget.SnapHelper;
136
import android.view.LayoutInflater;
147
import android.view.View;
158
import android.view.ViewGroup;
@@ -24,40 +17,52 @@
2417
import com.mapbox.geojson.Point;
2518
import com.mapbox.mapboxandroiddemo.R;
2619
import com.mapbox.mapboxsdk.Mapbox;
27-
import com.mapbox.mapboxsdk.annotations.Icon;
28-
import com.mapbox.mapboxsdk.annotations.IconFactory;
29-
import com.mapbox.mapboxsdk.annotations.Marker;
30-
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
3120
import com.mapbox.mapboxsdk.geometry.LatLng;
3221
import com.mapbox.mapboxsdk.maps.MapView;
3322
import com.mapbox.mapboxsdk.maps.MapboxMap;
3423
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
3524
import com.mapbox.mapboxsdk.maps.Style;
25+
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
26+
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
3627
import com.mapbox.turf.TurfConversion;
3728

3829
import java.io.InputStream;
3930
import java.text.DecimalFormat;
4031
import java.util.ArrayList;
4132
import java.util.List;
4233

34+
import androidx.annotation.NonNull;
35+
import androidx.appcompat.app.AppCompatActivity;
36+
import androidx.cardview.widget.CardView;
37+
import androidx.recyclerview.widget.DefaultItemAnimator;
38+
import androidx.recyclerview.widget.LinearLayoutManager;
39+
import androidx.recyclerview.widget.LinearSnapHelper;
40+
import androidx.recyclerview.widget.RecyclerView;
41+
import androidx.recyclerview.widget.SnapHelper;
4342
import retrofit2.Call;
4443
import retrofit2.Callback;
4544
import retrofit2.Response;
4645
import timber.log.Timber;
4746

47+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
48+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement;
49+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
4850

4951
/**
50-
* Use the Mapbox Java Services SDK's Matrix API to retrieve travel times between many points.
52+
* Use the Mapbox Java SDK's Matrix API to retrieve travel times between many points.
5153
*/
52-
public class MatrixApiActivity extends AppCompatActivity {
54+
public class MatrixApiActivity extends AppCompatActivity implements MapboxMap.OnMapClickListener {
5355

56+
private static final String ICON_ID = "ICON_ID";
57+
private static final String STATION_NAME_PROPERTY = "Station_Name";
58+
private static final String SOURCE_ID = "SOURCE_ID";
59+
private static final String LAYER_ID = "LAYER_ID";
60+
private List<Point> pointList;
61+
private List<SingleRecyclerViewMatrixLocation> matrixLocationList;
5462
private MapView mapView;
5563
private MapboxMap mapboxMap;
56-
private List<Point> pointList;
5764
private FeatureCollection featureCollection;
58-
private RecyclerView recyclerView;
5965
private MatrixApiLocationRecyclerViewAdapter matrixApiLocationRecyclerViewAdapter;
60-
private ArrayList<SingleRecyclerViewMatrixLocation> matrixLocationList;
6166

6267
@Override
6368
protected void onCreate(Bundle savedInstanceState) {
@@ -70,41 +75,41 @@ protected void onCreate(Bundle savedInstanceState) {
7075
// This contains the MapView in XML and needs to be called after the access token is configured.
7176
setContentView(R.layout.activity_matrix_api);
7277

73-
recyclerView = findViewById(R.id.matrix_api_recyclerview);
74-
75-
// Create list of positions from local GeoJSON file
76-
initPositionListFromGeoJsonFile();
78+
// Create a FeatureCollection via local GeoJSON file
79+
initFeatureCollection();
7780

7881
mapView = findViewById(R.id.mapView);
7982
mapView.onCreate(savedInstanceState);
8083
mapView.getMapAsync(new OnMapReadyCallback() {
8184
@Override
8285
public void onMapReady(@NonNull final MapboxMap mapboxMap) {
8386
MatrixApiActivity.this.mapboxMap = mapboxMap;
84-
85-
mapboxMap.setStyle(new Style.Builder().fromUri("mapbox://styles/mapbox/cj8gg22et19ot2rnz65958fkn"),
87+
mapboxMap.setStyle(new Style.Builder().fromUri("mapbox://styles/mapbox/cj8gg22et19ot2rnz65958fkn")
88+
// Add the SymbolLayer icon image to the map style
89+
.withImage(ICON_ID, BitmapFactory.decodeResource(
90+
MatrixApiActivity.this.getResources(), R.drawable.lightning_bolt))
91+
92+
// Adding a GeoJson source for the SymbolLayer icons.
93+
.withSource(new GeoJsonSource(SOURCE_ID, featureCollection))
94+
95+
// Adding the actual SymbolLayer to the map style.
96+
.withLayer(new SymbolLayer(LAYER_ID, SOURCE_ID)
97+
.withProperties(
98+
iconImage(ICON_ID),
99+
iconAllowOverlap(true),
100+
iconIgnorePlacement(true))
101+
),
86102
new Style.OnStyleLoaded() {
87103
@Override
88104
public void onStyleLoaded(@NonNull Style style) {
89-
// Add markers to the map
90-
addMarkers();
91105

92106
// Set up list of locations to pass to the recyclerview
93107
initMatrixLocationListForRecyclerView();
94108

95109
// Set up the recyclerview of charging station cards
96110
initRecyclerView();
97111

98-
mapboxMap.setOnMarkerClickListener(new MapboxMap.OnMarkerClickListener() {
99-
@Override
100-
public boolean onMarkerClick(@NonNull Marker marker) {
101-
102-
// Make a call to the Mapbox Matrix API
103-
makeMapboxMatrixApiCall(getClickedMarkerNumInPositionList(marker), Point.fromLngLat(
104-
marker.getPosition().getLongitude(), marker.getPosition().getLatitude()));
105-
return false;
106-
}
107-
});
112+
mapboxMap.addOnMapClickListener(MatrixApiActivity.this);
108113
Toast.makeText(MatrixApiActivity.this, R.string.click_on_marker_instruction_toast,
109114
Toast.LENGTH_SHORT).show();
110115
}
@@ -113,23 +118,32 @@ public boolean onMarkerClick(@NonNull Marker marker) {
113118
});
114119
}
115120

116-
private int getClickedMarkerNumInPositionList(Marker clickedMarker) {
117-
int clickedMarkerIndexPositionInList = -1;
118-
if (clickedMarker != null) {
119-
for (Marker singleMarker : mapboxMap.getMarkers()) {
120-
if (singleMarker == clickedMarker) {
121-
clickedMarkerIndexPositionInList = mapboxMap.getMarkers().indexOf(singleMarker);
121+
@Override
122+
public boolean onMapClick(@NonNull LatLng point) {
123+
List<Feature> renderedStationFeatures = mapboxMap.queryRenderedFeatures(
124+
mapboxMap.getProjection().toScreenLocation(point), LAYER_ID);
125+
if (!renderedStationFeatures.isEmpty()) {
126+
Point pointOfSelectedStation = (Point) renderedStationFeatures.get(0).geometry();
127+
if (pointOfSelectedStation != null) {
128+
String selectedBoltFeatureName = renderedStationFeatures.get(0).getStringProperty(STATION_NAME_PROPERTY);
129+
List<Feature> featureList = featureCollection.features();
130+
for (int i = 0; i < featureList.size(); i++) {
131+
if (featureList.get(i).getStringProperty(STATION_NAME_PROPERTY).equals(selectedBoltFeatureName)) {
132+
makeMapboxMatrixApiCall(i);
133+
}
122134
}
123135
}
124-
return clickedMarkerIndexPositionInList;
125-
} else {
126-
return 0;
127136
}
137+
return true;
128138
}
129139

140+
/**
141+
* Set up the RecyclerView, which will display the travel distances to each charge station.
142+
*/
130143
private void initRecyclerView() {
131144
matrixApiLocationRecyclerViewAdapter = new MatrixApiLocationRecyclerViewAdapter(this,
132145
matrixLocationList);
146+
RecyclerView recyclerView = findViewById(R.id.matrix_api_recyclerview);
133147
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext(),
134148
LinearLayoutManager.HORIZONTAL, true));
135149
recyclerView.setItemAnimator(new DefaultItemAnimator());
@@ -138,8 +152,12 @@ private void initRecyclerView() {
138152
snapHelper.attachToRecyclerView(recyclerView);
139153
}
140154

141-
private void makeMapboxMatrixApiCall(final int markerPositionInList, Point pointOfClickedMarker) {
142-
155+
/**
156+
* Make a call to the Mapbox Matrix API to get the travel distances to each charge station.
157+
*
158+
* @param markerPositionInList the position of the tapped bolt icon {@link Feature} in the FeatureCollection.
159+
*/
160+
private void makeMapboxMatrixApiCall(final int markerPositionInList) {
143161
// Build Mapbox Matrix API parameters
144162
MapboxMatrix directionsMatrixClient = MapboxMatrix.builder()
145163
.accessToken(getString(R.string.access_token))
@@ -152,18 +170,19 @@ private void makeMapboxMatrixApiCall(final int markerPositionInList, Point point
152170
@Override
153171
public void onResponse(Call<MatrixResponse> call,
154172
Response<MatrixResponse> response) {
155-
List<Double[]> durationsToAllOfTheLocationsFromTheOrigin = response.body().durations();
156-
for (int x = 0; x < durationsToAllOfTheLocationsFromTheOrigin.size(); x++) {
157-
String finalConvertedFormattedDistance = String.valueOf(new DecimalFormat("#.##")
158-
.format(TurfConversion.convertLength(
159-
durationsToAllOfTheLocationsFromTheOrigin.get(markerPositionInList)[x],
160-
"meters", "miles")));
161-
if (x == markerPositionInList) {
162-
matrixLocationList.get(x).setDistanceFromOrigin(finalConvertedFormattedDistance);
163-
}
164-
if (x != markerPositionInList) {
165-
matrixLocationList.get(x).setDistanceFromOrigin(finalConvertedFormattedDistance);
166-
matrixApiLocationRecyclerViewAdapter.notifyDataSetChanged();
173+
if (response.body() != null) {
174+
List<Double[]> durationsToAllOfTheLocationsFromTheOrigin = response.body().durations();
175+
if (durationsToAllOfTheLocationsFromTheOrigin != null) {
176+
for (int x = 0; x < durationsToAllOfTheLocationsFromTheOrigin.size(); x++) {
177+
String finalConvertedFormattedDistance = String.valueOf(new DecimalFormat("#.##").format(
178+
TurfConversion.convertLength(
179+
durationsToAllOfTheLocationsFromTheOrigin.get(markerPositionInList)[x],
180+
"meters", "miles")));
181+
matrixLocationList.get(x).setDistanceFromOrigin(finalConvertedFormattedDistance);
182+
if (x != markerPositionInList) {
183+
matrixApiLocationRecyclerViewAdapter.notifyDataSetChanged();
184+
}
185+
}
167186
}
168187
}
169188
}
@@ -172,23 +191,11 @@ public void onResponse(Call<MatrixResponse> call,
172191
public void onFailure(Call<MatrixResponse> call, Throwable throwable) {
173192
Toast.makeText(MatrixApiActivity.this, R.string.call_error,
174193
Toast.LENGTH_SHORT).show();
175-
Timber.d( "onResponse onFailure");
194+
Timber.d("onResponse onFailure");
176195
}
177196
});
178197
}
179198

180-
private void addMarkers() {
181-
Icon lightningBoltIcon = IconFactory.getInstance(MatrixApiActivity.this)
182-
.fromResource(R.drawable.lightning_bolt);
183-
for (Feature feature : featureCollection.features()) {
184-
mapboxMap.addMarker(new MarkerOptions()
185-
.position(new LatLng(feature.getProperty("Latitude").getAsDouble(),
186-
feature.getProperty("Longitude").getAsDouble()))
187-
.snippet(feature.getStringProperty("Station_Name"))
188-
.icon(lightningBoltIcon));
189-
}
190-
}
191-
192199
private String loadGeoJsonFromAsset(String filename) {
193200
try {
194201
// Load GeoJSON file from local asset folder
@@ -205,8 +212,10 @@ private String loadGeoJsonFromAsset(String filename) {
205212
}
206213
}
207214

208-
private void initPositionListFromGeoJsonFile() {
209-
215+
/**
216+
* Create a {@link FeatureCollection} from a locally stored asset file.
217+
*/
218+
private void initFeatureCollection() {
210219
// Get GeoJSON features from GeoJSON file in the assets folder
211220
featureCollection = FeatureCollection.fromJson(loadGeoJsonFromAsset("boston_charge_stations.geojson"));
212221

@@ -215,20 +224,24 @@ private void initPositionListFromGeoJsonFile() {
215224

216225
// Get the position of each GeoJSON feature and build the list of Position
217226
// objects for eventual use in the Matrix API call
218-
for (Feature singleLocation : featureCollection.features()) {
219-
pointList.add((Point) singleLocation.geometry());
227+
if (featureCollection != null && featureCollection.features() != null) {
228+
for (Feature singleLocation : featureCollection.features()) {
229+
pointList.add((Point) singleLocation.geometry());
230+
}
220231
}
221232
}
222233

234+
/**
235+
* Create a list of {@link SingleRecyclerViewMatrixLocation} objects to eventually use in the RecyclerView.
236+
*/
223237
private void initMatrixLocationListForRecyclerView() {
224238
matrixLocationList = new ArrayList<>();
225-
for (Feature feature : featureCollection.features()) {
226-
SingleRecyclerViewMatrixLocation singleRecyclerViewLocation = new SingleRecyclerViewMatrixLocation();
227-
singleRecyclerViewLocation.setName(feature.getStringProperty("Station_Name"));
228-
singleRecyclerViewLocation.setLocationLatLng(new LatLng(((Point)
229-
feature.geometry()).latitude(),
230-
((Point) feature.geometry()).longitude()));
231-
matrixLocationList.add(singleRecyclerViewLocation);
239+
if (featureCollection != null && featureCollection.features() != null) {
240+
for (Feature feature : featureCollection.features()) {
241+
SingleRecyclerViewMatrixLocation singleRecyclerViewLocation = new SingleRecyclerViewMatrixLocation();
242+
singleRecyclerViewLocation.setName(feature.getStringProperty(STATION_NAME_PROPERTY));
243+
matrixLocationList.add(singleRecyclerViewLocation);
244+
}
232245
}
233246
}
234247

@@ -281,7 +294,6 @@ protected void onSaveInstanceState(Bundle outState) {
281294
class SingleRecyclerViewMatrixLocation {
282295

283296
private String name;
284-
private LatLng locationLatLng;
285297
private String distanceFromOrigin;
286298

287299
public String getName() {
@@ -299,12 +311,11 @@ public String getDistanceFromOrigin() {
299311
public void setDistanceFromOrigin(String distanceFromOrigin) {
300312
this.distanceFromOrigin = distanceFromOrigin;
301313
}
302-
303-
public void setLocationLatLng(LatLng locationLatLng) {
304-
this.locationLatLng = locationLatLng;
305-
}
306314
}
307315

316+
/**
317+
* The adapter for this example's RecyclerView.
318+
*/
308319
static class MatrixApiLocationRecyclerViewAdapter extends
309320
RecyclerView.Adapter<MatrixApiLocationRecyclerViewAdapter.MyViewHolder> {
310321

MapboxAndroidDemo/src/main/res/layout/activity_matrix_api.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
mapbox:mapbox_cameraTargetLat="42.3600825"
1212
mapbox:mapbox_cameraTargetLng="-71.0588801"
1313
mapbox:mapbox_cameraZoom="11.193"
14+
mapbox:mapbox_uiCompassMarginTop="79dp"
1415
/>
1516

1617
<androidx.recyclerview.widget.RecyclerView

MapboxAndroidDemo/src/main/res/values/activity_strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@
242242
<!-- Matrix API -->
243243
<string name="call_error">Oh no! The call to the Directions Matrix API failed</string>
244244
<string name="miles_distance">%1$s miles</string>
245-
<string name="click_on_marker_instruction_toast">Click on a bolt marker to get started</string>
245+
<string name="click_on_marker_instruction_toast">Click on a bolt icon to get started</string>
246246

247247
<!-- Geocoding -->
248248
<string name="latitude">latitude</string>

0 commit comments

Comments
 (0)