[build] - initial commit
This commit is contained in:
1029
MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
Normal file
1029
MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
MapboxGLAndroidSDKTestApp/src/main/assets/Roboto-Medium.ttf
Normal file
BIN
MapboxGLAndroidSDKTestApp/src/main/assets/Roboto-Medium.ttf
Normal file
Binary file not shown.
BIN
MapboxGLAndroidSDKTestApp/src/main/assets/Roboto-Regular.ttf
Normal file
BIN
MapboxGLAndroidSDKTestApp/src/main/assets/Roboto-Regular.ttf
Normal file
Binary file not shown.
BIN
MapboxGLAndroidSDKTestApp/src/main/assets/commercial-24.png
Executable file
BIN
MapboxGLAndroidSDKTestApp/src/main/assets/commercial-24.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 308 B |
BIN
MapboxGLAndroidSDKTestApp/src/main/assets/dog-park-24.png
Normal file
BIN
MapboxGLAndroidSDKTestApp/src/main/assets/dog-park-24.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 831 B |
6113
MapboxGLAndroidSDKTestApp/src/main/assets/earthquakes.geojson
Normal file
6113
MapboxGLAndroidSDKTestApp/src/main/assets/earthquakes.geojson
Normal file
File diff suppressed because it is too large
Load Diff
10976
MapboxGLAndroidSDKTestApp/src/main/assets/fill_filter_style.json
Normal file
10976
MapboxGLAndroidSDKTestApp/src/main/assets/fill_filter_style.json
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
81857
MapboxGLAndroidSDKTestApp/src/main/assets/heavy_style.json
Normal file
81857
MapboxGLAndroidSDKTestApp/src/main/assets/heavy_style.json
Normal file
File diff suppressed because it is too large
Load Diff
8746
MapboxGLAndroidSDKTestApp/src/main/assets/line_filter_style.json
Normal file
8746
MapboxGLAndroidSDKTestApp/src/main/assets/line_filter_style.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
MapboxGLAndroidSDKTestApp/src/main/assets/london-underground-24.png
Executable file
BIN
MapboxGLAndroidSDKTestApp/src/main/assets/london-underground-24.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 729 B |
8734
MapboxGLAndroidSDKTestApp/src/main/assets/numeric_filter_style.json
Normal file
8734
MapboxGLAndroidSDKTestApp/src/main/assets/numeric_filter_style.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
MapboxGLAndroidSDKTestApp/src/main/assets/offline_test.db
Normal file
BIN
MapboxGLAndroidSDKTestApp/src/main/assets/offline_test.db
Normal file
Binary file not shown.
115
MapboxGLAndroidSDKTestApp/src/main/assets/points-sf.geojson
Normal file
115
MapboxGLAndroidSDKTestApp/src/main/assets/points-sf.geojson
Normal file
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
237.5580596923828,
|
||||
37.78563944612241
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
237.58346557617185,
|
||||
37.743571187449064
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
237.51068115234375,
|
||||
37.72347854862523
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
237.51583099365234,
|
||||
37.77125750792944
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
237.5913619995117,
|
||||
37.795406713958236
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
237.56080627441403,
|
||||
37.69441603823106
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
237.62981414794922,
|
||||
37.722392304715825
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
237.52235412597656,
|
||||
37.807071480609274
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
237.53608703613278,
|
||||
37.75334401310656
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
237.57591247558594,
|
||||
37.77071473849609
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
136346
MapboxGLAndroidSDKTestApp/src/main/assets/points.geojson
Normal file
136346
MapboxGLAndroidSDKTestApp/src/main/assets/points.geojson
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"LineString","coordinates":[[-121.3714599609375,38.64583568648869],[-121.48681640624999,38.64047263931154],[-121.53076171875,38.61579745317875],[-121.56509399414061,38.57823196583313],[-121.75186157226561,38.533127435052776],[-121.97021484374999,38.35350340353833],[-122.08007812499999,38.24680876017446],[-122.16796875,38.19718009396176],[-122.23800659179686,38.09457899232253],[-122.27371215820312,38.01455819225337],[-122.33551025390625,37.94094845586459],[-122.27371215820312,37.81846319511331],[-122.4151611328125,37.7652868250379]]}}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-122.28813171386719,38.617406963286136],[-122.26959228515624,38.6833657775237],[-122.18238830566406,38.55568323796419],[-122.10617065429688,38.51378825951165],[-122.11509704589845,38.50465406475561],[-122.18307495117188,38.542795073979015],[-122.19955444335938,38.496593518947556],[-122.28813171386719,38.617406963286136]]]}}]}
|
||||
10398
MapboxGLAndroidSDKTestApp/src/main/assets/streets.json
Normal file
10398
MapboxGLAndroidSDKTestApp/src/main/assets/streets.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
MapboxGLAndroidSDKTestApp/src/main/assets/town-hall-24.png
Executable file
BIN
MapboxGLAndroidSDKTestApp/src/main/assets/town-hall-24.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 552 B |
@@ -0,0 +1,95 @@
|
||||
package com.mapbox.mapboxsdk.testapp;
|
||||
|
||||
import android.app.Application;
|
||||
import android.os.StrictMode;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.mapbox.mapboxsdk.MapStrictMode;
|
||||
import com.mapbox.mapboxsdk.Mapbox;
|
||||
import com.mapbox.mapboxsdk.log.Logger;
|
||||
import com.mapbox.mapboxsdk.maps.TelemetryDefinition;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.TileLoadingMeasurementUtils;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.TimberLogger;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.TokenUtils;
|
||||
import com.squareup.leakcanary.LeakCanary;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
import static timber.log.Timber.DebugTree;
|
||||
|
||||
/**
|
||||
* Application class of the test application.
|
||||
* <p>
|
||||
* Initialises components as LeakCanary, Strictmode, Timber and Mapbox
|
||||
* </p>
|
||||
*/
|
||||
public class MapboxApplication extends Application {
|
||||
|
||||
private static final String DEFAULT_MAPBOX_ACCESS_TOKEN = "YOUR_MAPBOX_ACCESS_TOKEN_GOES_HERE";
|
||||
private static final String ACCESS_TOKEN_NOT_SET_MESSAGE = "In order to run the Test App you need to set a valid "
|
||||
+ "access token. During development, you can set the MAPBOX_ACCESS_TOKEN environment variable for the SDK to "
|
||||
+ "automatically include it in the Test App. Otherwise, you can manually include it in the "
|
||||
+ "res/values/developer-config.xml file in the MapboxGLAndroidSDKTestApp folder.";
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
if (!initializeLeakCanary()) {
|
||||
return;
|
||||
}
|
||||
initializeLogger();
|
||||
initializeStrictMode();
|
||||
initializeMapbox();
|
||||
}
|
||||
|
||||
protected boolean initializeLeakCanary() {
|
||||
if (LeakCanary.isInAnalyzerProcess(this)) {
|
||||
// This process is dedicated to LeakCanary for heap analysis.
|
||||
// You should not init your app in this process.
|
||||
return false;
|
||||
}
|
||||
LeakCanary.install(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void initializeLogger() {
|
||||
Logger.setLoggerDefinition(new TimberLogger());
|
||||
if (BuildConfig.DEBUG) {
|
||||
Timber.plant(new DebugTree());
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeStrictMode() {
|
||||
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
|
||||
.detectDiskReads()
|
||||
.detectDiskWrites()
|
||||
.detectNetwork()
|
||||
.penaltyLog()
|
||||
.build());
|
||||
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
|
||||
.detectLeakedSqlLiteObjects()
|
||||
.penaltyLog()
|
||||
.penaltyDeath()
|
||||
.build());
|
||||
}
|
||||
|
||||
private void initializeMapbox() {
|
||||
String accessToken = TokenUtils.getMapboxAccessToken(getApplicationContext());
|
||||
validateAccessToken(accessToken);
|
||||
Mapbox.getInstance(getApplicationContext(), accessToken);
|
||||
TelemetryDefinition telemetry = Mapbox.getTelemetry();
|
||||
if (telemetry == null) {
|
||||
throw new IllegalStateException("Telemetry was unavailable during test application start.");
|
||||
}
|
||||
telemetry.setDebugLoggingEnabled(true);
|
||||
TileLoadingMeasurementUtils.setUpTileLoadingMeasurement();
|
||||
|
||||
MapStrictMode.setStrictModeEnabled(true);
|
||||
}
|
||||
|
||||
private static void validateAccessToken(String accessToken) {
|
||||
if (TextUtils.isEmpty(accessToken) || accessToken.equals(DEFAULT_MAPBOX_ACCESS_TOKEN)) {
|
||||
Timber.e(ACCESS_TOKEN_NOT_SET_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.testapp.adapter.FeatureAdapter;
|
||||
import com.mapbox.mapboxsdk.testapp.adapter.FeatureSectionAdapter;
|
||||
import com.mapbox.mapboxsdk.testapp.model.activity.Feature;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.ItemClickSupport;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Activity shown when application is started
|
||||
* <p>
|
||||
* This activity will generate data for RecyclerView based on the AndroidManifest entries.
|
||||
* It uses tags as category and description to order the different entries.
|
||||
* </p>
|
||||
*/
|
||||
public class FeatureOverviewActivity extends AppCompatActivity {
|
||||
|
||||
private static final String KEY_STATE_FEATURES = "featureList";
|
||||
|
||||
private RecyclerView recyclerView;
|
||||
private FeatureSectionAdapter sectionAdapter;
|
||||
private List<Feature> features;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_feature_overview);
|
||||
|
||||
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener());
|
||||
recyclerView.setHasFixedSize(true);
|
||||
|
||||
ItemClickSupport.addTo(recyclerView).setOnItemClickListener((recyclerView, position, view) -> {
|
||||
if (!sectionAdapter.isSectionHeaderPosition(position)) {
|
||||
int itemPosition = sectionAdapter.getConvertedPosition(position);
|
||||
Feature feature = features.get(itemPosition);
|
||||
startFeature(feature);
|
||||
}
|
||||
});
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
loadFeatures();
|
||||
} else {
|
||||
features = savedInstanceState.getParcelableArrayList(KEY_STATE_FEATURES);
|
||||
onFeaturesLoaded(features);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadFeatures() {
|
||||
try {
|
||||
new LoadFeatureTask().execute(
|
||||
getPackageManager().getPackageInfo(getPackageName(),
|
||||
PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA));
|
||||
} catch (PackageManager.NameNotFoundException exception) {
|
||||
Timber.e(exception, "Could not resolve package info");
|
||||
}
|
||||
}
|
||||
|
||||
private void onFeaturesLoaded(List<Feature> featuresList) {
|
||||
features = featuresList;
|
||||
if (featuresList == null || featuresList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<FeatureSectionAdapter.Section> sections = new ArrayList<>();
|
||||
String currentCat = "";
|
||||
for (int i = 0; i < features.size(); i++) {
|
||||
String category = features.get(i).getCategory();
|
||||
if (!currentCat.equals(category)) {
|
||||
sections.add(new FeatureSectionAdapter.Section(i, category));
|
||||
currentCat = category;
|
||||
}
|
||||
}
|
||||
|
||||
FeatureSectionAdapter.Section[] dummy = new FeatureSectionAdapter.Section[sections.size()];
|
||||
sectionAdapter = new FeatureSectionAdapter(
|
||||
this, R.layout.section_main_layout, R.id.section_text, new FeatureAdapter(features));
|
||||
sectionAdapter.setSections(sections.toArray(dummy));
|
||||
recyclerView.setAdapter(sectionAdapter);
|
||||
}
|
||||
|
||||
private void startFeature(Feature feature) {
|
||||
Intent intent = new Intent();
|
||||
intent.setComponent(new ComponentName(getPackageName(), feature.getName()));
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putParcelableArrayList(KEY_STATE_FEATURES, (ArrayList<Feature>) features);
|
||||
}
|
||||
|
||||
private class LoadFeatureTask extends AsyncTask<PackageInfo, Void, List<Feature>> {
|
||||
|
||||
@Override
|
||||
protected List<Feature> doInBackground(PackageInfo... params) {
|
||||
List<Feature> features = new ArrayList<>();
|
||||
PackageInfo app = params[0];
|
||||
|
||||
String packageName = getApplicationContext().getPackageName();
|
||||
String metaDataKey = getString(R.string.category);
|
||||
for (ActivityInfo info : app.activities) {
|
||||
if (info.labelRes != 0 && info.name.startsWith(packageName)
|
||||
&& !info.name.equals(FeatureOverviewActivity.class.getName())) {
|
||||
String label = getString(info.labelRes);
|
||||
String description = resolveString(info.descriptionRes);
|
||||
String category = resolveMetaData(info.metaData, metaDataKey);
|
||||
features.add(new Feature(info.name, label, description, category));
|
||||
}
|
||||
}
|
||||
|
||||
if (!features.isEmpty()) {
|
||||
Comparator<Feature> comparator = (lhs, rhs) -> {
|
||||
int result = lhs.getCategory().compareToIgnoreCase(rhs.getCategory());
|
||||
if (result == 0) {
|
||||
result = lhs.getLabel().compareToIgnoreCase(rhs.getLabel());
|
||||
}
|
||||
return result;
|
||||
};
|
||||
Collections.sort(features, comparator);
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
private String resolveMetaData(Bundle bundle, String key) {
|
||||
String category = null;
|
||||
if (bundle != null) {
|
||||
category = bundle.getString(key);
|
||||
}
|
||||
return category;
|
||||
}
|
||||
|
||||
private String resolveString(@StringRes int stringRes) {
|
||||
try {
|
||||
return getString(stringRes);
|
||||
} catch (Resources.NotFoundException exception) {
|
||||
return "-";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<Feature> features) {
|
||||
super.onPostExecute(features);
|
||||
onFeaturesLoaded(features);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,443 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.annotation;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.TypeEvaluator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mapbox.geojson.Feature;
|
||||
import com.mapbox.geojson.FeatureCollection;
|
||||
import com.mapbox.geojson.Point;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
|
||||
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.turf.TurfMeasurement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconRotate;
|
||||
|
||||
/**
|
||||
* Test activity showcasing animating a SymbolLayer.
|
||||
*/
|
||||
public class AnimatedSymbolLayerActivity extends AppCompatActivity {
|
||||
|
||||
private static final String PASSENGER = "passenger";
|
||||
private static final String PASSENGER_LAYER = "passenger-layer";
|
||||
private static final String PASSENGER_SOURCE = "passenger-source";
|
||||
private static final String TAXI = "taxi";
|
||||
private static final String TAXI_LAYER = "taxi-layer";
|
||||
private static final String TAXI_SOURCE = "taxi-source";
|
||||
private static final String RANDOM_CAR_LAYER = "random-car-layer";
|
||||
private static final String RANDOM_CAR_SOURCE = "random-car-source";
|
||||
private static final String RANDOM_CAR_IMAGE_ID = "random-car";
|
||||
private static final String PROPERTY_BEARING = "bearing";
|
||||
private static final String WATERWAY_LAYER_ID = "waterway-label";
|
||||
private static final int DURATION_RANDOM_MAX = 1500;
|
||||
private static final int DURATION_BASE = 3000;
|
||||
|
||||
private final Random random = new Random();
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private Style style;
|
||||
|
||||
private List<Car> randomCars = new ArrayList<>();
|
||||
private GeoJsonSource randomCarSource;
|
||||
private Car taxi;
|
||||
private GeoJsonSource taxiSource;
|
||||
private LatLng passenger;
|
||||
|
||||
private List<Animator> animators = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_animated_marker);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(map -> {
|
||||
this.mapboxMap = map;
|
||||
map.setStyle(Style.MAPBOX_STREETS, style -> {
|
||||
this.style = style;
|
||||
setupCars();
|
||||
animateRandomRoutes();
|
||||
animateTaxi();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void setupCars() {
|
||||
addRandomCars();
|
||||
addPassenger();
|
||||
addMainCar();
|
||||
}
|
||||
|
||||
private void animateRandomRoutes() {
|
||||
final Car longestDrive = getLongestDrive();
|
||||
final Random random = new Random();
|
||||
for (final Car car : randomCars) {
|
||||
final boolean isLongestDrive = longestDrive.equals(car);
|
||||
ValueAnimator valueAnimator = ValueAnimator.ofObject(new LatLngEvaluator(), car.current, car.next);
|
||||
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
|
||||
private LatLng latLng;
|
||||
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
latLng = (LatLng) animation.getAnimatedValue();
|
||||
car.current = latLng;
|
||||
if (isLongestDrive) {
|
||||
updateRandomCarSource();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (isLongestDrive) {
|
||||
valueAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
updateRandomDestinations();
|
||||
animateRandomRoutes();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
valueAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
super.onAnimationStart(animation);
|
||||
car.feature.properties().addProperty("bearing", Car.getBearing(car.current, car.next));
|
||||
}
|
||||
});
|
||||
|
||||
int offset = random.nextInt(2) == 0 ? 0 : random.nextInt(1000) + 250;
|
||||
valueAnimator.setStartDelay(offset);
|
||||
valueAnimator.setDuration(car.duration - offset);
|
||||
valueAnimator.setInterpolator(new LinearInterpolator());
|
||||
valueAnimator.start();
|
||||
|
||||
animators.add(valueAnimator);
|
||||
}
|
||||
}
|
||||
|
||||
private void animateTaxi() {
|
||||
ValueAnimator valueAnimator = ValueAnimator.ofObject(new LatLngEvaluator(), taxi.current, taxi.next);
|
||||
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
|
||||
private LatLng latLng;
|
||||
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
latLng = (LatLng) animation.getAnimatedValue();
|
||||
taxi.current = latLng;
|
||||
updateTaxiSource();
|
||||
}
|
||||
});
|
||||
|
||||
valueAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
updatePassenger();
|
||||
animateTaxi();
|
||||
}
|
||||
});
|
||||
|
||||
valueAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
super.onAnimationStart(animation);
|
||||
taxi.feature.properties().addProperty("bearing", Car.getBearing(taxi.current, taxi.next));
|
||||
}
|
||||
});
|
||||
|
||||
valueAnimator.setDuration((long) (7 * taxi.current.distanceTo(taxi.next)));
|
||||
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
|
||||
valueAnimator.start();
|
||||
|
||||
animators.add(valueAnimator);
|
||||
}
|
||||
|
||||
private void updatePassenger() {
|
||||
passenger = getLatLngInBounds();
|
||||
updatePassengerSource();
|
||||
taxi.setNext(passenger);
|
||||
}
|
||||
|
||||
private void updatePassengerSource() {
|
||||
GeoJsonSource source = style.getSourceAs(PASSENGER_SOURCE);
|
||||
FeatureCollection featureCollection = FeatureCollection.fromFeatures(new Feature[] {
|
||||
Feature.fromGeometry(
|
||||
Point.fromLngLat(
|
||||
passenger.getLongitude(),
|
||||
passenger.getLatitude()
|
||||
)
|
||||
)
|
||||
});
|
||||
source.setGeoJson(featureCollection);
|
||||
}
|
||||
|
||||
private void updateTaxiSource() {
|
||||
taxi.updateFeature();
|
||||
taxiSource.setGeoJson(taxi.feature);
|
||||
}
|
||||
|
||||
private void updateRandomDestinations() {
|
||||
for (Car randomCar : randomCars) {
|
||||
randomCar.setNext(getLatLngInBounds());
|
||||
}
|
||||
}
|
||||
|
||||
private Car getLongestDrive() {
|
||||
Car longestDrive = null;
|
||||
for (Car randomCar : randomCars) {
|
||||
if (longestDrive == null) {
|
||||
longestDrive = randomCar;
|
||||
} else if (longestDrive.duration < randomCar.duration) {
|
||||
longestDrive = randomCar;
|
||||
}
|
||||
}
|
||||
return longestDrive;
|
||||
}
|
||||
|
||||
private void updateRandomCarSource() {
|
||||
for (Car randomCarsRoute : randomCars) {
|
||||
randomCarsRoute.updateFeature();
|
||||
}
|
||||
randomCarSource.setGeoJson(featuresFromRoutes());
|
||||
}
|
||||
|
||||
private FeatureCollection featuresFromRoutes() {
|
||||
List<Feature> features = new ArrayList<>();
|
||||
for (Car randomCarsRoute : randomCars) {
|
||||
features.add(randomCarsRoute.feature);
|
||||
}
|
||||
return FeatureCollection.fromFeatures(features);
|
||||
}
|
||||
|
||||
private long getDuration() {
|
||||
return random.nextInt(DURATION_RANDOM_MAX) + DURATION_BASE;
|
||||
}
|
||||
|
||||
private void addRandomCars() {
|
||||
LatLng latLng;
|
||||
LatLng next;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
latLng = getLatLngInBounds();
|
||||
next = getLatLngInBounds();
|
||||
|
||||
JsonObject properties = new JsonObject();
|
||||
properties.addProperty(PROPERTY_BEARING, Car.getBearing(latLng, next));
|
||||
|
||||
Feature feature = Feature.fromGeometry(
|
||||
Point.fromLngLat(
|
||||
latLng.getLongitude(),
|
||||
latLng.getLatitude()
|
||||
), properties);
|
||||
|
||||
randomCars.add(
|
||||
new Car(feature, next, getDuration())
|
||||
);
|
||||
}
|
||||
|
||||
randomCarSource = new GeoJsonSource(RANDOM_CAR_SOURCE, featuresFromRoutes());
|
||||
style.addSource(randomCarSource);
|
||||
style.addImage(RANDOM_CAR_IMAGE_ID,
|
||||
((BitmapDrawable) getResources().getDrawable(R.drawable.ic_car_top)).getBitmap());
|
||||
|
||||
SymbolLayer symbolLayer = new SymbolLayer(RANDOM_CAR_LAYER, RANDOM_CAR_SOURCE);
|
||||
symbolLayer.withProperties(
|
||||
iconImage(RANDOM_CAR_IMAGE_ID),
|
||||
iconAllowOverlap(true),
|
||||
iconRotate(get(PROPERTY_BEARING)),
|
||||
iconIgnorePlacement(true)
|
||||
);
|
||||
|
||||
style.addLayerBelow(symbolLayer, WATERWAY_LAYER_ID);
|
||||
}
|
||||
|
||||
private void addPassenger() {
|
||||
passenger = getLatLngInBounds();
|
||||
FeatureCollection featureCollection = FeatureCollection.fromFeatures(new Feature[] {
|
||||
Feature.fromGeometry(
|
||||
Point.fromLngLat(
|
||||
passenger.getLongitude(),
|
||||
passenger.getLatitude()
|
||||
)
|
||||
)
|
||||
});
|
||||
|
||||
style.addImage(PASSENGER,
|
||||
((BitmapDrawable) getResources().getDrawable(R.drawable.icon_burned)).getBitmap());
|
||||
|
||||
GeoJsonSource geoJsonSource = new GeoJsonSource(PASSENGER_SOURCE, featureCollection);
|
||||
style.addSource(geoJsonSource);
|
||||
|
||||
SymbolLayer symbolLayer = new SymbolLayer(PASSENGER_LAYER, PASSENGER_SOURCE);
|
||||
symbolLayer.withProperties(
|
||||
iconImage(PASSENGER),
|
||||
iconIgnorePlacement(true),
|
||||
iconAllowOverlap(true)
|
||||
);
|
||||
style.addLayerBelow(symbolLayer, RANDOM_CAR_LAYER);
|
||||
}
|
||||
|
||||
private void addMainCar() {
|
||||
LatLng latLng = getLatLngInBounds();
|
||||
JsonObject properties = new JsonObject();
|
||||
properties.addProperty(PROPERTY_BEARING, Car.getBearing(latLng, passenger));
|
||||
Feature feature = Feature.fromGeometry(
|
||||
Point.fromLngLat(
|
||||
latLng.getLongitude(),
|
||||
latLng.getLatitude()), properties);
|
||||
FeatureCollection featureCollection = FeatureCollection.fromFeatures(new Feature[] {feature});
|
||||
|
||||
taxi = new Car(feature, passenger, getDuration());
|
||||
style.addImage(TAXI,
|
||||
((BitmapDrawable) getResources().getDrawable(R.drawable.ic_taxi_top)).getBitmap());
|
||||
taxiSource = new GeoJsonSource(TAXI_SOURCE, featureCollection);
|
||||
style.addSource(taxiSource);
|
||||
|
||||
SymbolLayer symbolLayer = new SymbolLayer(TAXI_LAYER, TAXI_SOURCE);
|
||||
symbolLayer.withProperties(
|
||||
iconImage(TAXI),
|
||||
iconRotate(get(PROPERTY_BEARING)),
|
||||
iconAllowOverlap(true),
|
||||
iconIgnorePlacement(true)
|
||||
|
||||
);
|
||||
style.addLayer(symbolLayer);
|
||||
}
|
||||
|
||||
private LatLng getLatLngInBounds() {
|
||||
LatLngBounds bounds = mapboxMap.getProjection().getVisibleRegion().latLngBounds;
|
||||
Random generator = new Random();
|
||||
double randomLat = bounds.getLatSouth() + generator.nextDouble()
|
||||
* (bounds.getLatNorth() - bounds.getLatSouth());
|
||||
double randomLon = bounds.getLonWest() + generator.nextDouble()
|
||||
* (bounds.getLonEast() - bounds.getLonWest());
|
||||
return new LatLng(randomLat, randomLon);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
for (Animator animator : animators) {
|
||||
if (animator != null) {
|
||||
animator.removeAllListeners();
|
||||
animator.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluator for LatLng pairs
|
||||
*/
|
||||
private static class LatLngEvaluator implements TypeEvaluator<LatLng> {
|
||||
|
||||
private LatLng latLng = new LatLng();
|
||||
|
||||
@Override
|
||||
public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
|
||||
latLng.setLatitude(startValue.getLatitude()
|
||||
+ ((endValue.getLatitude() - startValue.getLatitude()) * fraction));
|
||||
latLng.setLongitude(startValue.getLongitude()
|
||||
+ ((endValue.getLongitude() - startValue.getLongitude()) * fraction));
|
||||
return latLng;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class Car {
|
||||
private Feature feature;
|
||||
private LatLng next;
|
||||
private LatLng current;
|
||||
private long duration;
|
||||
|
||||
Car(Feature feature, LatLng next, long duration) {
|
||||
this.feature = feature;
|
||||
Point point = ((Point) feature.geometry());
|
||||
this.current = new LatLng(point.latitude(), point.longitude());
|
||||
this.duration = duration;
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
void setNext(LatLng next) {
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
void updateFeature() {
|
||||
feature = Feature.fromGeometry(Point.fromLngLat(
|
||||
current.getLongitude(),
|
||||
current.getLatitude())
|
||||
);
|
||||
feature.properties().addProperty("bearing", getBearing(current, next));
|
||||
}
|
||||
|
||||
private static float getBearing(LatLng from, LatLng to) {
|
||||
return (float) TurfMeasurement.bearing(
|
||||
Point.fromLngLat(from.getLongitude(), from.getLatitude()),
|
||||
Point.fromLngLat(to.getLongitude(), to.getLatitude())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.annotation;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Spinner;
|
||||
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.GeoParseUtil;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Test activity showcasing adding a large amount of Markers.
|
||||
*/
|
||||
public class BulkMarkerActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
|
||||
|
||||
private MapboxMap mapboxMap;
|
||||
private MapView mapView;
|
||||
private List<LatLng> locations;
|
||||
private ProgressDialog progressDialog;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_marker_bulk);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(this::initMap);
|
||||
}
|
||||
|
||||
private void initMap(MapboxMap mapboxMap) {
|
||||
this.mapboxMap = mapboxMap;
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
ArrayAdapter<CharSequence> spinnerAdapter = ArrayAdapter.createFromResource(
|
||||
this, R.array.bulk_marker_list, android.R.layout.simple_spinner_item);
|
||||
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
getMenuInflater().inflate(R.menu.menu_bulk_marker, menu);
|
||||
MenuItem item = menu.findItem(R.id.spinner);
|
||||
Spinner spinner = (Spinner) MenuItemCompat.getActionView(item);
|
||||
spinner.setAdapter(spinnerAdapter);
|
||||
spinner.setOnItemSelectedListener(BulkMarkerActivity.this);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
int amount = Integer.valueOf(getResources().getStringArray(R.array.bulk_marker_list)[position]);
|
||||
if (locations == null) {
|
||||
progressDialog = ProgressDialog.show(this, "Loading", "Fetching markers", false);
|
||||
new LoadLocationTask(this, amount).execute();
|
||||
} else {
|
||||
showMarkers(amount);
|
||||
}
|
||||
}
|
||||
|
||||
private void onLatLngListLoaded(List<LatLng> latLngs, int amount) {
|
||||
progressDialog.hide();
|
||||
locations = latLngs;
|
||||
showMarkers(amount);
|
||||
}
|
||||
|
||||
private void showMarkers(int amount) {
|
||||
if (mapboxMap == null || locations == null || mapView.isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mapboxMap.clear();
|
||||
if (locations.size() < amount) {
|
||||
amount = locations.size();
|
||||
}
|
||||
|
||||
showGlMarkers(amount);
|
||||
}
|
||||
|
||||
private void showGlMarkers(int amount) {
|
||||
List<MarkerOptions> markerOptionsList = new ArrayList<>();
|
||||
DecimalFormat formatter = new DecimalFormat("#.#####");
|
||||
Random random = new Random();
|
||||
int randomIndex;
|
||||
|
||||
for (int i = 0; i < amount; i++) {
|
||||
randomIndex = random.nextInt(locations.size());
|
||||
LatLng latLng = locations.get(randomIndex);
|
||||
markerOptionsList.add(new MarkerOptions()
|
||||
.position(latLng)
|
||||
.title(String.valueOf(i))
|
||||
.snippet(formatter.format(latLng.getLatitude()) + ", " + formatter.format(latLng.getLongitude())));
|
||||
}
|
||||
|
||||
mapboxMap.addMarkers(markerOptionsList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
// nothing selected, nothing to do!
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
private static class LoadLocationTask extends AsyncTask<Void, Integer, List<LatLng>> {
|
||||
|
||||
private WeakReference<BulkMarkerActivity> activity;
|
||||
private int amount;
|
||||
|
||||
private LoadLocationTask(BulkMarkerActivity activity, int amount) {
|
||||
this.amount = amount;
|
||||
this.activity = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<LatLng> doInBackground(Void... params) {
|
||||
BulkMarkerActivity activity = this.activity.get();
|
||||
if (activity != null) {
|
||||
String json = null;
|
||||
try {
|
||||
json = GeoParseUtil.loadStringFromAssets(activity.getApplicationContext(), "points.geojson");
|
||||
} catch (IOException exception) {
|
||||
Timber.e(exception, "Could not add markers");
|
||||
}
|
||||
|
||||
if (json != null) {
|
||||
return GeoParseUtil.parseGeoJsonCoordinates(json);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<LatLng> locations) {
|
||||
super.onPostExecute(locations);
|
||||
BulkMarkerActivity activity = this.activity.get();
|
||||
if (activity != null) {
|
||||
activity.onLatLngListLoaded(locations, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.annotation;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.content.res.ResourcesCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import com.mapbox.mapboxsdk.annotations.Marker;
|
||||
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.IconUtils;
|
||||
|
||||
/**
|
||||
* Test activity showcasing updating a Marker position, title, icon and snippet.
|
||||
*/
|
||||
public class DynamicMarkerChangeActivity extends AppCompatActivity {
|
||||
|
||||
private static final LatLng LAT_LNG_CHELSEA = new LatLng(51.481670, -0.190849);
|
||||
private static final LatLng LAT_LNG_ARSENAL = new LatLng(51.555062, -0.108417);
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private Marker marker;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_dynamic_marker);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.setTag(false);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(mapboxMap -> {
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS);
|
||||
|
||||
DynamicMarkerChangeActivity.this.mapboxMap = mapboxMap;
|
||||
// Create marker
|
||||
MarkerOptions markerOptions = new MarkerOptions()
|
||||
.position(LAT_LNG_CHELSEA)
|
||||
.icon(IconUtils.drawableToIcon(DynamicMarkerChangeActivity.this, R.drawable.ic_stars,
|
||||
ResourcesCompat.getColor(getResources(), R.color.blueAccent, getTheme())))
|
||||
.title(getString(R.string.dynamic_marker_chelsea_title))
|
||||
.snippet(getString(R.string.dynamic_marker_chelsea_snippet));
|
||||
marker = mapboxMap.addMarker(markerOptions);
|
||||
});
|
||||
|
||||
FloatingActionButton fab = findViewById(R.id.fab);
|
||||
fab.setColorFilter(ContextCompat.getColor(this, R.color.primary));
|
||||
fab.setOnClickListener(view -> {
|
||||
if (mapboxMap != null) {
|
||||
updateMarker();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateMarker() {
|
||||
// update model
|
||||
boolean first = (boolean) mapView.getTag();
|
||||
mapView.setTag(!first);
|
||||
|
||||
// update marker
|
||||
marker.setPosition(first ? LAT_LNG_CHELSEA : LAT_LNG_ARSENAL);
|
||||
marker.setIcon(IconUtils.drawableToIcon(this, R.drawable.ic_stars, first
|
||||
? ResourcesCompat.getColor(getResources(), R.color.blueAccent, getTheme()) :
|
||||
ResourcesCompat.getColor(getResources(), R.color.redAccent, getTheme())
|
||||
));
|
||||
|
||||
marker.setTitle(first
|
||||
? getString(R.string.dynamic_marker_chelsea_title) : getString(R.string.dynamic_marker_arsenal_title));
|
||||
marker.setSnippet(first
|
||||
? getString(R.string.dynamic_marker_chelsea_snippet) : getString(R.string.dynamic_marker_arsenal_snippet));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.annotation;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.mapbox.mapboxsdk.annotations.Polygon;
|
||||
import com.mapbox.mapboxsdk.annotations.PolygonOptions;
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.Config.BLUE_COLOR;
|
||||
import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.Config.BROKEN_SHAPE_POINTS;
|
||||
import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.Config.FULL_ALPHA;
|
||||
import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.Config.NO_ALPHA;
|
||||
import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.Config.PARTIAL_ALPHA;
|
||||
import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.Config.RED_COLOR;
|
||||
import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.Config.STAR_SHAPE_HOLES;
|
||||
import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.Config.STAR_SHAPE_POINTS;
|
||||
|
||||
/**
|
||||
* Test activity to showcase the Polygon annotation API & programmatically creating a MapView.
|
||||
* <p>
|
||||
* Shows how to change Polygon features as visibility, alpha, color and points.
|
||||
* </p>
|
||||
*/
|
||||
public class PolygonActivity extends AppCompatActivity implements OnMapReadyCallback {
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
|
||||
private Polygon polygon;
|
||||
private boolean fullAlpha = true;
|
||||
private boolean visible = true;
|
||||
private boolean color = true;
|
||||
private boolean allPoints = true;
|
||||
private boolean holes = false;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// configure inital map state
|
||||
MapboxMapOptions options = MapboxMapOptions.createFromAttributes(this, null)
|
||||
.attributionTintColor(RED_COLOR)
|
||||
.compassFadesWhenFacingNorth(false)
|
||||
.camera(new CameraPosition.Builder()
|
||||
.target(new LatLng(45.520486, -122.673541))
|
||||
.zoom(12)
|
||||
.tilt(40)
|
||||
.build());
|
||||
|
||||
// create map
|
||||
mapView = new MapView(this, options);
|
||||
mapView.setId(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(this);
|
||||
|
||||
setContentView(mapView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull MapboxMap map) {
|
||||
mapboxMap = map;
|
||||
map.setStyle(Style.MAPBOX_STREETS);
|
||||
|
||||
map.setOnPolygonClickListener(polygon -> Toast.makeText(
|
||||
PolygonActivity.this,
|
||||
"You clicked on polygon with id = " + polygon.getId(),
|
||||
Toast.LENGTH_SHORT
|
||||
).show());
|
||||
|
||||
polygon = mapboxMap.addPolygon(new PolygonOptions()
|
||||
.addAll(STAR_SHAPE_POINTS)
|
||||
.fillColor(BLUE_COLOR));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_id_alpha:
|
||||
fullAlpha = !fullAlpha;
|
||||
polygon.setAlpha(fullAlpha ? FULL_ALPHA : PARTIAL_ALPHA);
|
||||
return true;
|
||||
case R.id.action_id_visible:
|
||||
visible = !visible;
|
||||
polygon.setAlpha(visible ? (fullAlpha ? FULL_ALPHA : PARTIAL_ALPHA) : NO_ALPHA);
|
||||
return true;
|
||||
case R.id.action_id_points:
|
||||
allPoints = !allPoints;
|
||||
polygon.setPoints(allPoints ? STAR_SHAPE_POINTS : BROKEN_SHAPE_POINTS);
|
||||
return true;
|
||||
case R.id.action_id_color:
|
||||
color = !color;
|
||||
polygon.setFillColor(color ? BLUE_COLOR : RED_COLOR);
|
||||
return true;
|
||||
case R.id.action_id_holes:
|
||||
holes = !holes;
|
||||
polygon.setHoles(holes ? STAR_SHAPE_HOLES : Collections.<List<LatLng>>emptyList());
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_polygon, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
static final class Config {
|
||||
static final int BLUE_COLOR = Color.parseColor("#3bb2d0");
|
||||
static final int RED_COLOR = Color.parseColor("#AF0000");
|
||||
|
||||
static final float FULL_ALPHA = 1.0f;
|
||||
static final float PARTIAL_ALPHA = 0.5f;
|
||||
static final float NO_ALPHA = 0.0f;
|
||||
|
||||
static final List<LatLng> STAR_SHAPE_POINTS = new ArrayList<LatLng>() {
|
||||
{
|
||||
add(new LatLng(45.522585, -122.685699));
|
||||
add(new LatLng(45.534611, -122.708873));
|
||||
add(new LatLng(45.530883, -122.678833));
|
||||
add(new LatLng(45.547115, -122.667503));
|
||||
add(new LatLng(45.530643, -122.660121));
|
||||
add(new LatLng(45.533529, -122.636260));
|
||||
add(new LatLng(45.521743, -122.659091));
|
||||
add(new LatLng(45.510677, -122.648792));
|
||||
add(new LatLng(45.515008, -122.664070));
|
||||
add(new LatLng(45.502496, -122.669048));
|
||||
add(new LatLng(45.515369, -122.678489));
|
||||
add(new LatLng(45.506346, -122.702007));
|
||||
add(new LatLng(45.522585, -122.685699));
|
||||
}
|
||||
};
|
||||
|
||||
static final List<LatLng> BROKEN_SHAPE_POINTS =
|
||||
STAR_SHAPE_POINTS.subList(0, STAR_SHAPE_POINTS.size() - 3);
|
||||
|
||||
static final List<? extends List<LatLng>> STAR_SHAPE_HOLES = new ArrayList<List<LatLng>>() {
|
||||
{
|
||||
add(new ArrayList<>(new ArrayList<LatLng>() {
|
||||
{
|
||||
add(new LatLng(45.521743, -122.669091));
|
||||
add(new LatLng(45.530483, -122.676833));
|
||||
add(new LatLng(45.520483, -122.676833));
|
||||
add(new LatLng(45.521743, -122.669091));
|
||||
}
|
||||
}));
|
||||
add(new ArrayList<>(new ArrayList<LatLng>() {
|
||||
{
|
||||
add(new LatLng(45.529743, -122.662791));
|
||||
add(new LatLng(45.525543, -122.662791));
|
||||
add(new LatLng(45.525543, -122.660));
|
||||
add(new LatLng(45.527743, -122.660));
|
||||
add(new LatLng(45.529743, -122.662791));
|
||||
}
|
||||
}));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.annotation;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.mapbox.mapboxsdk.annotations.Polyline;
|
||||
import com.mapbox.mapboxsdk.annotations.PolylineOptions;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Test activity showcasing the Polyline annotations API.
|
||||
* <p>
|
||||
* Shows how to add and remove polylines.
|
||||
* </p>
|
||||
*/
|
||||
public class PolylineActivity extends AppCompatActivity {
|
||||
|
||||
private static final String STATE_POLYLINE_OPTIONS = "polylineOptions";
|
||||
|
||||
private static final LatLng ANDORRA = new LatLng(42.505777, 1.52529);
|
||||
private static final LatLng LUXEMBOURG = new LatLng(49.815273, 6.129583);
|
||||
private static final LatLng MONACO = new LatLng(43.738418, 7.424616);
|
||||
private static final LatLng VATICAN_CITY = new LatLng(41.902916, 12.453389);
|
||||
private static final LatLng SAN_MARINO = new LatLng(43.942360, 12.457777);
|
||||
private static final LatLng LIECHTENSTEIN = new LatLng(47.166000, 9.555373);
|
||||
|
||||
private static final float FULL_ALPHA = 1.0f;
|
||||
private static final float PARTIAL_ALPHA = 0.5f;
|
||||
private static final float NO_ALPHA = 0.0f;
|
||||
|
||||
private List<Polyline> polylines;
|
||||
private ArrayList<PolylineOptions> polylineOptions = new ArrayList<>();
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
|
||||
private boolean fullAlpha = true;
|
||||
private boolean visible = true;
|
||||
private boolean width = true;
|
||||
private boolean color = true;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_polyline);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
polylineOptions = savedInstanceState.getParcelableArrayList(STATE_POLYLINE_OPTIONS);
|
||||
} else {
|
||||
polylineOptions.addAll(getAllPolylines());
|
||||
}
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(mapboxMap -> {
|
||||
PolylineActivity.this.mapboxMap = mapboxMap;
|
||||
mapboxMap.setStyle(Style.SATELLITE_STREETS);
|
||||
mapboxMap.setOnPolylineClickListener(polyline -> Toast.makeText(
|
||||
PolylineActivity.this,
|
||||
"You clicked on polyline with id = " + polyline.getId(),
|
||||
Toast.LENGTH_SHORT
|
||||
).show());
|
||||
|
||||
polylines = mapboxMap.addPolylines(polylineOptions);
|
||||
});
|
||||
|
||||
View fab = findViewById(R.id.fab);
|
||||
if (fab != null) {
|
||||
fab.setOnClickListener(view -> {
|
||||
if (mapboxMap != null) {
|
||||
if (polylines != null && polylines.size() > 0) {
|
||||
if (polylines.size() == 1) {
|
||||
// test for removing annotation
|
||||
mapboxMap.removeAnnotation(polylines.get(0));
|
||||
} else {
|
||||
// test for removing annotations
|
||||
mapboxMap.removeAnnotations(polylines);
|
||||
}
|
||||
}
|
||||
polylineOptions.clear();
|
||||
polylineOptions.addAll(getRandomLine());
|
||||
polylines = mapboxMap.addPolylines(polylineOptions);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private List<PolylineOptions> getAllPolylines() {
|
||||
List<PolylineOptions> options = new ArrayList<>();
|
||||
options.add(generatePolyline(ANDORRA, LUXEMBOURG, "#F44336"));
|
||||
options.add(generatePolyline(ANDORRA, MONACO, "#FF5722"));
|
||||
options.add(generatePolyline(MONACO, VATICAN_CITY, "#673AB7"));
|
||||
options.add(generatePolyline(VATICAN_CITY, SAN_MARINO, "#009688"));
|
||||
options.add(generatePolyline(SAN_MARINO, LIECHTENSTEIN, "#795548"));
|
||||
options.add(generatePolyline(LIECHTENSTEIN, LUXEMBOURG, "#3F51B5"));
|
||||
return options;
|
||||
}
|
||||
|
||||
private PolylineOptions generatePolyline(LatLng start, LatLng end, String color) {
|
||||
PolylineOptions line = new PolylineOptions();
|
||||
line.add(start);
|
||||
line.add(end);
|
||||
line.color(Color.parseColor(color));
|
||||
return line;
|
||||
}
|
||||
|
||||
public List<PolylineOptions> getRandomLine() {
|
||||
final List<PolylineOptions> randomLines = getAllPolylines();
|
||||
Collections.shuffle(randomLines);
|
||||
return new ArrayList<PolylineOptions>() {
|
||||
{
|
||||
add(randomLines.get(0));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
outState.putParcelableArrayList(STATE_POLYLINE_OPTIONS, polylineOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_polyline, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (polylines.size() <= 0) {
|
||||
Toast.makeText(PolylineActivity.this, "No polylines on map", Toast.LENGTH_LONG).show();
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_id_remove:
|
||||
// test to remove all annotations
|
||||
polylineOptions.clear();
|
||||
mapboxMap.clear();
|
||||
polylines.clear();
|
||||
return true;
|
||||
|
||||
case R.id.action_id_alpha:
|
||||
fullAlpha = !fullAlpha;
|
||||
for (Polyline p : polylines) {
|
||||
p.setAlpha(fullAlpha ? FULL_ALPHA : PARTIAL_ALPHA);
|
||||
}
|
||||
return true;
|
||||
|
||||
case R.id.action_id_color:
|
||||
color = !color;
|
||||
for (Polyline p : polylines) {
|
||||
p.setColor(color ? Color.RED : Color.BLUE);
|
||||
}
|
||||
return true;
|
||||
|
||||
case R.id.action_id_width:
|
||||
width = !width;
|
||||
for (Polyline p : polylines) {
|
||||
p.setWidth(width ? 3.0f : 5.0f);
|
||||
}
|
||||
return true;
|
||||
|
||||
case R.id.action_id_visible:
|
||||
visible = !visible;
|
||||
for (Polyline p : polylines) {
|
||||
p.setAlpha(visible ? (fullAlpha ? FULL_ALPHA : PARTIAL_ALPHA) : NO_ALPHA);
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.annotation;
|
||||
|
||||
import android.graphics.PointF;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Test activity showcasing to add a Marker on click.
|
||||
* <p>
|
||||
* Shows how to use a OnMapClickListener and a OnMapLongClickListener
|
||||
* </p>
|
||||
*/
|
||||
public class PressForMarkerActivity extends AppCompatActivity {
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private ArrayList<MarkerOptions> markerList = new ArrayList<>();
|
||||
|
||||
private static final DecimalFormat LAT_LON_FORMATTER = new DecimalFormat("#.#####");
|
||||
|
||||
private static String STATE_MARKER_LIST = "markerList";
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_press_for_marker);
|
||||
|
||||
mapView = (MapView) findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(map -> {
|
||||
mapboxMap = map;
|
||||
resetMap();
|
||||
|
||||
mapboxMap.addOnMapLongClickListener(point -> {
|
||||
addMarker(point);
|
||||
return false;
|
||||
});
|
||||
|
||||
mapboxMap.addOnMapClickListener(point -> {
|
||||
addMarker(point);
|
||||
return false;
|
||||
});
|
||||
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
markerList = savedInstanceState.getParcelableArrayList(STATE_MARKER_LIST);
|
||||
if (markerList != null) {
|
||||
mapboxMap.addMarkers(markerList);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void addMarker(LatLng point) {
|
||||
final PointF pixel = mapboxMap.getProjection().toScreenLocation(point);
|
||||
|
||||
String title = LAT_LON_FORMATTER.format(point.getLatitude()) + ", "
|
||||
+ LAT_LON_FORMATTER.format(point.getLongitude());
|
||||
String snippet = "X = " + (int) pixel.x + ", Y = " + (int) pixel.y;
|
||||
|
||||
MarkerOptions marker = new MarkerOptions()
|
||||
.position(point)
|
||||
.title(title)
|
||||
.snippet(snippet);
|
||||
|
||||
markerList.add(marker);
|
||||
mapboxMap.addMarker(marker);
|
||||
}
|
||||
|
||||
private void resetMap() {
|
||||
if (mapboxMap == null) {
|
||||
return;
|
||||
}
|
||||
markerList.clear();
|
||||
mapboxMap.removeAnnotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_press_for_marker, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
mapView.onSaveInstanceState(outState);
|
||||
outState.putParcelableArrayList(STATE_MARKER_LIST, markerList);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menuItemReset:
|
||||
resetMap();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.camera;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Test activity showcasing the Camera API and listen to camera updates by animating the camera above London.
|
||||
* <p>
|
||||
* Shows how to use animate, ease and move camera update factory methods.
|
||||
* </p>
|
||||
*/
|
||||
public class CameraAnimationTypeActivity extends AppCompatActivity implements OnMapReadyCallback {
|
||||
|
||||
private static final LatLng LAT_LNG_LONDON_EYE = new LatLng(51.50325, -0.11968);
|
||||
private static final LatLng LAT_LNG_TOWER_BRIDGE = new LatLng(51.50550, -0.07520);
|
||||
|
||||
private final MapboxMap.CancelableCallback callback = new MapboxMap.CancelableCallback() {
|
||||
@Override
|
||||
public void onCancel() {
|
||||
Timber.i("Duration onCancel Callback called.");
|
||||
Toast.makeText(
|
||||
CameraAnimationTypeActivity.this.getApplicationContext(),
|
||||
"Ease onCancel Callback called.",
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
Timber.i("Duration onFinish Callback called.");
|
||||
Toast.makeText(
|
||||
CameraAnimationTypeActivity.this.getApplicationContext(),
|
||||
"Ease onFinish Callback called.",
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
};
|
||||
|
||||
private MapboxMap mapboxMap;
|
||||
private MapView mapView;
|
||||
private boolean cameraState;
|
||||
|
||||
private MapboxMap.OnCameraIdleListener cameraIdleListener = new MapboxMap.OnCameraIdleListener() {
|
||||
@Override
|
||||
public void onCameraIdle() {
|
||||
if (mapboxMap != null) {
|
||||
Timber.w(mapboxMap.getCameraPosition().toString());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_camera_animation_types);
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull MapboxMap map) {
|
||||
mapboxMap = map;
|
||||
mapboxMap.setStyle(new Style.Builder().fromUri(Style.MAPBOX_STREETS));
|
||||
mapboxMap.getUiSettings().setAttributionEnabled(false);
|
||||
mapboxMap.getUiSettings().setLogoEnabled(false);
|
||||
mapboxMap.addOnCameraIdleListener(cameraIdleListener);
|
||||
|
||||
// handle move button clicks
|
||||
View moveButton = findViewById(R.id.cameraMoveButton);
|
||||
if (moveButton != null) {
|
||||
moveButton.setOnClickListener(view -> {
|
||||
CameraPosition cameraPosition = new CameraPosition.Builder()
|
||||
.target(getNextLatLng())
|
||||
.zoom(14)
|
||||
.tilt(30)
|
||||
.tilt(0)
|
||||
.build();
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
|
||||
});
|
||||
}
|
||||
|
||||
// handle ease button clicks
|
||||
View easeButton = findViewById(R.id.cameraEaseButton);
|
||||
if (easeButton != null) {
|
||||
easeButton.setOnClickListener(view -> {
|
||||
CameraPosition cameraPosition = new CameraPosition.Builder()
|
||||
.target(getNextLatLng())
|
||||
.zoom(15)
|
||||
.bearing(180)
|
||||
.tilt(30)
|
||||
.build();
|
||||
mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 7500, callback);
|
||||
});
|
||||
}
|
||||
|
||||
// handle animate button clicks
|
||||
View animateButton = findViewById(R.id.cameraAnimateButton);
|
||||
if (animateButton != null) {
|
||||
animateButton.setOnClickListener(view -> {
|
||||
CameraPosition cameraPosition = new CameraPosition.Builder()
|
||||
.target(getNextLatLng())
|
||||
.bearing(270)
|
||||
.tilt(20)
|
||||
.build();
|
||||
|
||||
mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 7500, callback);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private LatLng getNextLatLng() {
|
||||
cameraState = !cameraState;
|
||||
return cameraState ? LAT_LNG_TOWER_BRIDGE : LAT_LNG_LONDON_EYE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mapboxMap != null) {
|
||||
mapboxMap.removeOnCameraIdleListener(cameraIdleListener);
|
||||
}
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.camera;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.TypeEvaluator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
import android.support.v4.view.animation.FastOutLinearInInterpolator;
|
||||
import android.support.v4.view.animation.FastOutSlowInInterpolator;
|
||||
import android.support.v4.view.animation.PathInterpolatorCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.animation.AnticipateOvershootInterpolator;
|
||||
import android.view.animation.BounceInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
/**
|
||||
* Test activity showcasing using Android SDK animators to animate camera position changes.
|
||||
*/
|
||||
public class CameraAnimatorActivity extends AppCompatActivity implements OnMapReadyCallback {
|
||||
|
||||
private static final double ANIMATION_DELAY_FACTOR = 1.5;
|
||||
private static final LatLng START_LAT_LNG = new LatLng(37.787947, -122.407432);
|
||||
|
||||
private final LongSparseArray<Animator> animators = new LongSparseArray<>();
|
||||
private Animator set;
|
||||
|
||||
{
|
||||
AnimatorSet accelerateDecelerateAnimatorSet = new AnimatorSet();
|
||||
accelerateDecelerateAnimatorSet.playTogether(
|
||||
createLatLngAnimator(START_LAT_LNG, new LatLng(37.826715, -122.422795)),
|
||||
obtainExampleInterpolator(new FastOutSlowInInterpolator(), 2500)
|
||||
);
|
||||
animators.put(R.id.menu_action_accelerate_decelerate_interpolator, accelerateDecelerateAnimatorSet);
|
||||
|
||||
AnimatorSet bounceAnimatorSet = new AnimatorSet();
|
||||
bounceAnimatorSet.playTogether(
|
||||
createLatLngAnimator(START_LAT_LNG, new LatLng(37.787947, -122.407432)),
|
||||
obtainExampleInterpolator(new BounceInterpolator(), 3750)
|
||||
);
|
||||
animators.put(R.id.menu_action_bounce_interpolator, bounceAnimatorSet);
|
||||
|
||||
animators.put(R.id.menu_action_anticipate_overshoot_interpolator,
|
||||
obtainExampleInterpolator(new AnticipateOvershootInterpolator(), 2500)
|
||||
);
|
||||
|
||||
animators.put(R.id.menu_action_path_interpolator, obtainExampleInterpolator(
|
||||
PathInterpolatorCompat.create(.22f, .68f, 0, 1.71f), 2500));
|
||||
}
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_camera_animator);
|
||||
mapView = (MapView) findViewById(R.id.mapView);
|
||||
if (mapView != null) {
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull final MapboxMap map) {
|
||||
mapboxMap = map;
|
||||
map.setStyle(Style.MAPBOX_STREETS);
|
||||
initFab();
|
||||
}
|
||||
|
||||
private void initFab() {
|
||||
findViewById(R.id.fab).setOnClickListener(view -> {
|
||||
view.setVisibility(View.GONE);
|
||||
|
||||
CameraPosition animatedPosition = new CameraPosition.Builder()
|
||||
.target(new LatLng(37.789992, -122.402214))
|
||||
.tilt(60)
|
||||
.zoom(14.5f)
|
||||
.bearing(135)
|
||||
.build();
|
||||
|
||||
set = createExampleAnimator(mapboxMap.getCameraPosition(), animatedPosition);
|
||||
set.start();
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Animator API used for the animation on the FAB
|
||||
//
|
||||
|
||||
private Animator createExampleAnimator(CameraPosition currentPosition, CameraPosition targetPosition) {
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
animatorSet.play(createLatLngAnimator(currentPosition.target, targetPosition.target));
|
||||
animatorSet.play(createZoomAnimator(currentPosition.zoom, targetPosition.zoom));
|
||||
animatorSet.play(createBearingAnimator(currentPosition.bearing, targetPosition.bearing));
|
||||
animatorSet.play(createTiltAnimator(currentPosition.tilt, targetPosition.tilt));
|
||||
return animatorSet;
|
||||
}
|
||||
|
||||
private Animator createLatLngAnimator(LatLng currentPosition, LatLng targetPosition) {
|
||||
ValueAnimator latLngAnimator = ValueAnimator.ofObject(new LatLngEvaluator(), currentPosition, targetPosition);
|
||||
latLngAnimator.setDuration((long) (1000 * ANIMATION_DELAY_FACTOR));
|
||||
latLngAnimator.setInterpolator(new FastOutSlowInInterpolator());
|
||||
latLngAnimator.addUpdateListener(animation -> mapboxMap.moveCamera(
|
||||
CameraUpdateFactory.newLatLng((LatLng) animation.getAnimatedValue()))
|
||||
);
|
||||
return latLngAnimator;
|
||||
}
|
||||
|
||||
private Animator createZoomAnimator(double currentZoom, double targetZoom) {
|
||||
ValueAnimator zoomAnimator = ValueAnimator.ofFloat((float) currentZoom, (float) targetZoom);
|
||||
zoomAnimator.setDuration((long) (2200 * ANIMATION_DELAY_FACTOR));
|
||||
zoomAnimator.setStartDelay((long) (600 * ANIMATION_DELAY_FACTOR));
|
||||
zoomAnimator.setInterpolator(new AnticipateOvershootInterpolator());
|
||||
zoomAnimator.addUpdateListener(animation -> mapboxMap.moveCamera(
|
||||
CameraUpdateFactory.zoomTo((Float) animation.getAnimatedValue()))
|
||||
);
|
||||
return zoomAnimator;
|
||||
}
|
||||
|
||||
private Animator createBearingAnimator(double currentBearing, double targetBearing) {
|
||||
ValueAnimator bearingAnimator = ValueAnimator.ofFloat((float) currentBearing, (float) targetBearing);
|
||||
bearingAnimator.setDuration((long) (1000 * ANIMATION_DELAY_FACTOR));
|
||||
bearingAnimator.setStartDelay((long) (1000 * ANIMATION_DELAY_FACTOR));
|
||||
bearingAnimator.setInterpolator(new FastOutLinearInInterpolator());
|
||||
bearingAnimator.addUpdateListener(animation -> mapboxMap.moveCamera(
|
||||
CameraUpdateFactory.bearingTo((Float) animation.getAnimatedValue()))
|
||||
);
|
||||
return bearingAnimator;
|
||||
}
|
||||
|
||||
private Animator createTiltAnimator(double currentTilt, double targetTilt) {
|
||||
ValueAnimator tiltAnimator = ValueAnimator.ofFloat((float) currentTilt, (float) targetTilt);
|
||||
tiltAnimator.setDuration((long) (1000 * ANIMATION_DELAY_FACTOR));
|
||||
tiltAnimator.setStartDelay((long) (1500 * ANIMATION_DELAY_FACTOR));
|
||||
tiltAnimator.addUpdateListener(animation -> mapboxMap.moveCamera(
|
||||
CameraUpdateFactory.tiltTo((Float) animation.getAnimatedValue()))
|
||||
);
|
||||
return tiltAnimator;
|
||||
}
|
||||
|
||||
//
|
||||
// Interpolator examples
|
||||
//
|
||||
|
||||
private Animator obtainExampleInterpolator(int menuItemId) {
|
||||
return animators.get(menuItemId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_animator, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (mapboxMap == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item.getItemId() != android.R.id.home) {
|
||||
findViewById(R.id.fab).setVisibility(View.GONE);
|
||||
resetCameraPosition();
|
||||
playAnimation(item.getItemId());
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void resetCameraPosition() {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
|
||||
new CameraPosition.Builder()
|
||||
.target(START_LAT_LNG)
|
||||
.zoom(11)
|
||||
.bearing(0)
|
||||
.tilt(0)
|
||||
.build()
|
||||
));
|
||||
}
|
||||
|
||||
private void playAnimation(int itemId) {
|
||||
Animator animator = obtainExampleInterpolator(itemId);
|
||||
if (animator != null) {
|
||||
animator.cancel();
|
||||
animator.start();
|
||||
}
|
||||
}
|
||||
|
||||
private Animator obtainExampleInterpolator(Interpolator interpolator, long duration) {
|
||||
ValueAnimator zoomAnimator = ValueAnimator.ofFloat(11.0f, 16.0f);
|
||||
zoomAnimator.setDuration((long) (duration * ANIMATION_DELAY_FACTOR));
|
||||
zoomAnimator.setInterpolator(interpolator);
|
||||
zoomAnimator.addUpdateListener(animation -> mapboxMap.moveCamera(
|
||||
CameraUpdateFactory.zoomTo((Float) animation.getAnimatedValue()))
|
||||
);
|
||||
return zoomAnimator;
|
||||
}
|
||||
|
||||
//
|
||||
// MapView lifecycle
|
||||
//
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
for (int i = 0; i < animators.size(); i++) {
|
||||
animators.get(animators.keyAt(i)).cancel();
|
||||
}
|
||||
if (set != null) {
|
||||
set.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to evaluate LatLng objects with a ValueAnimator
|
||||
*/
|
||||
private static class LatLngEvaluator implements TypeEvaluator<LatLng> {
|
||||
|
||||
private final LatLng latLng = new LatLng();
|
||||
|
||||
@Override
|
||||
public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
|
||||
latLng.setLatitude(startValue.getLatitude()
|
||||
+ ((endValue.getLatitude() - startValue.getLatitude()) * fraction));
|
||||
latLng.setLongitude(startValue.getLongitude()
|
||||
+ ((endValue.getLongitude() - startValue.getLongitude()) * fraction));
|
||||
return latLng;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.camera;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import timber.log.Timber;
|
||||
|
||||
import static com.mapbox.mapboxsdk.constants.GeometryConstants.MAX_LATITUDE;
|
||||
import static com.mapbox.mapboxsdk.constants.GeometryConstants.MIN_LATITUDE;
|
||||
|
||||
/**
|
||||
* Test activity showcasing how to listen to camera change events.
|
||||
*/
|
||||
public class CameraPositionActivity extends FragmentActivity implements OnMapReadyCallback, View.OnClickListener,
|
||||
MapboxMap.OnMapLongClickListener {
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private FloatingActionButton fab;
|
||||
private boolean logCameraChanges;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_camera_position);
|
||||
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
toolbar.setTitle(R.string.activity_camera_position);
|
||||
toolbar.setNavigationIcon(R.drawable.ic_ab_back);
|
||||
toolbar.setNavigationOnClickListener(v -> finish());
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull final MapboxMap map) {
|
||||
mapboxMap = map;
|
||||
map.setStyle(Style.SATELLITE_STREETS, style -> {
|
||||
// add a listener to FAB
|
||||
fab = findViewById(R.id.fab);
|
||||
fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, R.color.primary));
|
||||
fab.setOnClickListener(this);
|
||||
|
||||
toggleLogCameraChanges();
|
||||
|
||||
// listen to long click events to toggle logging camera changes
|
||||
mapboxMap.addOnMapLongClickListener(this);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMapLongClick(@NonNull LatLng point) {
|
||||
toggleLogCameraChanges();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Context context = view.getContext();
|
||||
final View dialogContent = LayoutInflater.from(context).inflate(R.layout.dialog_camera_position, null);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(R.string.dialog_camera_position);
|
||||
builder.setView(onInflateDialogContent(dialogContent));
|
||||
builder.setPositiveButton("Animate", new DialogClickListener(mapboxMap, dialogContent));
|
||||
builder.setNegativeButton("Cancel", null);
|
||||
builder.setCancelable(false);
|
||||
builder.show();
|
||||
}
|
||||
|
||||
private void toggleLogCameraChanges() {
|
||||
logCameraChanges = !logCameraChanges;
|
||||
if (logCameraChanges) {
|
||||
mapboxMap.addOnCameraIdleListener(idleListener);
|
||||
mapboxMap.addOnCameraMoveCancelListener(moveCanceledListener);
|
||||
mapboxMap.addOnCameraMoveListener(moveListener);
|
||||
mapboxMap.addOnCameraMoveStartedListener(moveStartedListener);
|
||||
} else {
|
||||
mapboxMap.removeOnCameraIdleListener(idleListener);
|
||||
mapboxMap.removeOnCameraMoveCancelListener(moveCanceledListener);
|
||||
mapboxMap.removeOnCameraMoveListener(moveListener);
|
||||
mapboxMap.removeOnCameraMoveStartedListener(moveStartedListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mapboxMap != null) {
|
||||
mapboxMap.removeOnMapLongClickListener(this);
|
||||
}
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
private View onInflateDialogContent(View view) {
|
||||
linkTextView(view, R.id.value_lat, R.id.seekbar_lat, new LatLngChangeListener(), 180 + 38);
|
||||
linkTextView(view, R.id.value_lon, R.id.seekbar_lon, new LatLngChangeListener(), 180 - 77);
|
||||
linkTextView(view, R.id.value_zoom, R.id.seekbar_zoom, new ValueChangeListener(), 6);
|
||||
linkTextView(view, R.id.value_bearing, R.id.seekbar_bearing, new ValueChangeListener(), 90);
|
||||
linkTextView(view, R.id.value_tilt, R.id.seekbar_tilt, new ValueChangeListener(), 40);
|
||||
return view;
|
||||
}
|
||||
|
||||
private void linkTextView(
|
||||
View view, @IdRes int textViewRes, @IdRes int seekBarRes, ValueChangeListener listener, int defaultValue) {
|
||||
final TextView value = (TextView) view.findViewById(textViewRes);
|
||||
SeekBar seekBar = (SeekBar) view.findViewById(seekBarRes);
|
||||
listener.setLinkedValueView(value);
|
||||
seekBar.setOnSeekBarChangeListener(listener);
|
||||
seekBar.setProgress(defaultValue);
|
||||
}
|
||||
|
||||
private MapboxMap.OnCameraIdleListener idleListener = new MapboxMap.OnCameraIdleListener() {
|
||||
@Override
|
||||
public void onCameraIdle() {
|
||||
Timber.e("OnCameraIdle");
|
||||
fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, android.R.color.holo_green_dark));
|
||||
}
|
||||
};
|
||||
|
||||
private MapboxMap.OnCameraMoveListener moveListener = new MapboxMap.OnCameraMoveListener() {
|
||||
@Override
|
||||
public void onCameraMove() {
|
||||
Timber.e("OnCameraMove");
|
||||
fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, android.R.color.holo_orange_dark));
|
||||
}
|
||||
};
|
||||
|
||||
private MapboxMap.OnCameraMoveCanceledListener moveCanceledListener = () -> Timber.e("OnCameraMoveCanceled");
|
||||
|
||||
private MapboxMap.OnCameraMoveStartedListener moveStartedListener = new MapboxMap.OnCameraMoveStartedListener() {
|
||||
|
||||
private final String[] REASONS = {"REASON_API_GESTURE", "REASON_DEVELOPER_ANIMATION", "REASON_API_ANIMATION"};
|
||||
|
||||
@Override
|
||||
public void onCameraMoveStarted(int reason) {
|
||||
// reason ranges from 1 <-> 3
|
||||
fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, android.R.color.holo_red_dark));
|
||||
Timber.e("OnCameraMoveStarted: %s", REASONS[reason - 1]);
|
||||
}
|
||||
};
|
||||
|
||||
private class ValueChangeListener implements SeekBar.OnSeekBarChangeListener {
|
||||
|
||||
protected TextView textView;
|
||||
|
||||
public void setLinkedValueView(TextView textView) {
|
||||
this.textView = textView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
textView.setText(String.valueOf(progress));
|
||||
}
|
||||
}
|
||||
|
||||
private class LatLngChangeListener extends ValueChangeListener {
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
super.onProgressChanged(seekBar, progress - 180, fromUser);
|
||||
}
|
||||
}
|
||||
|
||||
private static class DialogClickListener implements DialogInterface.OnClickListener {
|
||||
|
||||
private MapboxMap mapboxMap;
|
||||
private View dialogContent;
|
||||
|
||||
public DialogClickListener(MapboxMap mapboxMap, View view) {
|
||||
this.mapboxMap = mapboxMap;
|
||||
this.dialogContent = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
double latitude = Double.parseDouble(
|
||||
((TextView) dialogContent.findViewById(R.id.value_lat)).getText().toString());
|
||||
double longitude = Double.parseDouble(
|
||||
((TextView) dialogContent.findViewById(R.id.value_lon)).getText().toString());
|
||||
double zoom = Double.parseDouble(
|
||||
((TextView) dialogContent.findViewById(R.id.value_zoom)).getText().toString());
|
||||
double bearing = Double.parseDouble(
|
||||
((TextView) dialogContent.findViewById(R.id.value_bearing)).getText().toString());
|
||||
double tilt = Double.parseDouble(
|
||||
((TextView) dialogContent.findViewById(R.id.value_tilt)).getText().toString());
|
||||
|
||||
if (latitude < MIN_LATITUDE || latitude > MAX_LATITUDE) {
|
||||
Toast.makeText(dialogContent.getContext(), "latitude value must be set "
|
||||
+ " between " + MIN_LATITUDE + " and " + MAX_LATITUDE,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
CameraPosition cameraPosition = new CameraPosition.Builder()
|
||||
.target(new LatLng(latitude, longitude))
|
||||
.zoom(zoom)
|
||||
.bearing(bearing)
|
||||
.tilt(tilt)
|
||||
.build();
|
||||
|
||||
mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 5000,
|
||||
new MapboxMap.CancelableCallback() {
|
||||
@Override
|
||||
public void onCancel() {
|
||||
Timber.v("OnCancel called");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
Timber.v("OnFinish called");
|
||||
}
|
||||
});
|
||||
Timber.v(cameraPosition.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,456 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.camera;
|
||||
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.ColorInt;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mapbox.android.gestures.AndroidGesturesManager;
|
||||
import com.mapbox.android.gestures.MoveGestureDetector;
|
||||
import com.mapbox.android.gestures.RotateGestureDetector;
|
||||
import com.mapbox.android.gestures.ShoveGestureDetector;
|
||||
import com.mapbox.android.gestures.StandardScaleGestureDetector;
|
||||
import com.mapbox.mapboxsdk.annotations.Marker;
|
||||
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.maps.UiSettings;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.FontCache;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Test activity showcasing APIs around gestures implementation.
|
||||
*/
|
||||
public class GestureDetectorActivity extends AppCompatActivity {
|
||||
|
||||
private static final int MAX_NUMBER_OF_ALERTS = 30;
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private RecyclerView recyclerView;
|
||||
private GestureAlertsAdapter gestureAlertsAdapter;
|
||||
|
||||
private AndroidGesturesManager gesturesManager;
|
||||
|
||||
@Nullable
|
||||
private Marker marker;
|
||||
@Nullable
|
||||
private LatLng focalPointLatLng;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_gesture_detector);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(mapboxMap -> {
|
||||
GestureDetectorActivity.this.mapboxMap = mapboxMap;
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS);
|
||||
initializeMap();
|
||||
});
|
||||
|
||||
recyclerView = findViewById(R.id.alerts_recycler);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
|
||||
gestureAlertsAdapter = new GestureAlertsAdapter();
|
||||
recyclerView.setAdapter(gestureAlertsAdapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
gestureAlertsAdapter.cancelUpdates();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
private void initializeMap() {
|
||||
gesturesManager = mapboxMap.getGesturesManager();
|
||||
|
||||
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) recyclerView.getLayoutParams();
|
||||
layoutParams.height = (int) (mapView.getHeight() / 1.75);
|
||||
layoutParams.width = (mapView.getWidth() / 3);
|
||||
recyclerView.setLayoutParams(layoutParams);
|
||||
|
||||
attachListeners();
|
||||
|
||||
fixedFocalPointEnabled(mapboxMap.getUiSettings().getFocalPoint() != null);
|
||||
}
|
||||
|
||||
public void attachListeners() {
|
||||
mapboxMap.addOnMoveListener(new MapboxMap.OnMoveListener() {
|
||||
@Override
|
||||
public void onMoveBegin(@NonNull MoveGestureDetector detector) {
|
||||
gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_START, "MOVE START"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMove(@NonNull MoveGestureDetector detector) {
|
||||
gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_PROGRESS, "MOVE PROGRESS"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMoveEnd(@NonNull MoveGestureDetector detector) {
|
||||
gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_END, "MOVE END"));
|
||||
recalculateFocalPoint();
|
||||
}
|
||||
});
|
||||
|
||||
mapboxMap.addOnRotateListener(new MapboxMap.OnRotateListener() {
|
||||
@Override
|
||||
public void onRotateBegin(@NonNull RotateGestureDetector detector) {
|
||||
gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_START, "ROTATE START"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRotate(@NonNull RotateGestureDetector detector) {
|
||||
gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_PROGRESS, "ROTATE PROGRESS"));
|
||||
recalculateFocalPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRotateEnd(@NonNull RotateGestureDetector detector) {
|
||||
gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_END, "ROTATE END"));
|
||||
}
|
||||
});
|
||||
|
||||
mapboxMap.addOnScaleListener(new MapboxMap.OnScaleListener() {
|
||||
@Override
|
||||
public void onScaleBegin(@NonNull StandardScaleGestureDetector detector) {
|
||||
gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_START, "SCALE START"));
|
||||
if (focalPointLatLng != null) {
|
||||
gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_OTHER, "INCREASING MOVE THRESHOLD"));
|
||||
gesturesManager.getMoveGestureDetector().setMoveThreshold(
|
||||
ResourceUtils.convertDpToPx(GestureDetectorActivity.this, 175));
|
||||
|
||||
gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_OTHER, "MANUALLY INTERRUPTING MOVE"));
|
||||
gesturesManager.getMoveGestureDetector().interrupt();
|
||||
}
|
||||
recalculateFocalPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScale(@NonNull StandardScaleGestureDetector detector) {
|
||||
gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_PROGRESS, "SCALE PROGRESS"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScaleEnd(@NonNull StandardScaleGestureDetector detector) {
|
||||
gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_END, "SCALE END"));
|
||||
|
||||
if (focalPointLatLng != null) {
|
||||
gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_OTHER, "REVERTING MOVE THRESHOLD"));
|
||||
gesturesManager.getMoveGestureDetector().setMoveThreshold(0f);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mapboxMap.addOnShoveListener(new MapboxMap.OnShoveListener() {
|
||||
@Override
|
||||
public void onShoveBegin(@NonNull ShoveGestureDetector detector) {
|
||||
gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_START, "SHOVE START"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShove(@NonNull ShoveGestureDetector detector) {
|
||||
gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_PROGRESS, "SHOVE PROGRESS"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShoveEnd(@NonNull ShoveGestureDetector detector) {
|
||||
gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_END, "SHOVE END"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_gestures, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
UiSettings uiSettings = mapboxMap.getUiSettings();
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_gesture_focus_point:
|
||||
fixedFocalPointEnabled(focalPointLatLng == null);
|
||||
return true;
|
||||
case R.id.menu_gesture_animation:
|
||||
uiSettings.setScaleVelocityAnimationEnabled(!uiSettings.isScaleVelocityAnimationEnabled());
|
||||
uiSettings.setRotateVelocityAnimationEnabled(!uiSettings.isRotateVelocityAnimationEnabled());
|
||||
uiSettings.setFlingVelocityAnimationEnabled(!uiSettings.isFlingVelocityAnimationEnabled());
|
||||
return true;
|
||||
case R.id.menu_gesture_rotate:
|
||||
uiSettings.setRotateGesturesEnabled(!uiSettings.isRotateGesturesEnabled());
|
||||
return true;
|
||||
case R.id.menu_gesture_tilt:
|
||||
uiSettings.setTiltGesturesEnabled(!uiSettings.isTiltGesturesEnabled());
|
||||
return true;
|
||||
case R.id.menu_gesture_zoom:
|
||||
uiSettings.setZoomGesturesEnabled(!uiSettings.isZoomGesturesEnabled());
|
||||
return true;
|
||||
case R.id.menu_gesture_scroll:
|
||||
uiSettings.setScrollGesturesEnabled(!uiSettings.isScrollGesturesEnabled());
|
||||
return true;
|
||||
case R.id.menu_gesture_double_tap:
|
||||
uiSettings.setDoubleTapGesturesEnabled(!uiSettings.isDoubleTapGesturesEnabled());
|
||||
return true;
|
||||
case R.id.menu_gesture_quick_zoom:
|
||||
uiSettings.setQuickZoomGesturesEnabled(!uiSettings.isQuickZoomGesturesEnabled());
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void fixedFocalPointEnabled(boolean enabled) {
|
||||
if (enabled) {
|
||||
focalPointLatLng = new LatLng(51.50325, -0.12968);
|
||||
marker = mapboxMap.addMarker(new MarkerOptions().position(focalPointLatLng));
|
||||
mapboxMap.easeCamera(CameraUpdateFactory.newLatLngZoom(focalPointLatLng, 16),
|
||||
new MapboxMap.CancelableCallback() {
|
||||
@Override
|
||||
public void onCancel() {
|
||||
recalculateFocalPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
recalculateFocalPoint();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (marker != null) {
|
||||
mapboxMap.removeMarker(marker);
|
||||
marker = null;
|
||||
}
|
||||
focalPointLatLng = null;
|
||||
mapboxMap.getUiSettings().setFocalPoint(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void recalculateFocalPoint() {
|
||||
if (focalPointLatLng != null) {
|
||||
mapboxMap.getUiSettings().setFocalPoint(
|
||||
mapboxMap.getProjection().toScreenLocation(focalPointLatLng)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static class GestureAlertsAdapter extends RecyclerView.Adapter<GestureAlertsAdapter.ViewHolder> {
|
||||
|
||||
private boolean isUpdating;
|
||||
private final Handler updateHandler = new Handler();
|
||||
private final List<GestureAlert> alerts = new ArrayList<>();
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
TextView alertMessageTv;
|
||||
|
||||
@ColorInt
|
||||
public int textColor;
|
||||
|
||||
ViewHolder(View view) {
|
||||
super(view);
|
||||
Typeface typeface = FontCache.get("Roboto-Regular.ttf", view.getContext());
|
||||
alertMessageTv = view.findViewById(R.id.alert_message);
|
||||
alertMessageTv.setTypeface(typeface);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_gesture_alert, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
GestureAlert alert = alerts.get(position);
|
||||
holder.alertMessageTv.setText(alert.getMessage());
|
||||
holder.alertMessageTv.setTextColor(
|
||||
ContextCompat.getColor(holder.alertMessageTv.getContext(), alert.getColor()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return alerts.size();
|
||||
}
|
||||
|
||||
void addAlert(GestureAlert alert) {
|
||||
for (GestureAlert gestureAlert : alerts) {
|
||||
if (gestureAlert.getAlertType() != GestureAlert.TYPE_PROGRESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (alert.getAlertType() == GestureAlert.TYPE_PROGRESS && gestureAlert.equals(alert)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (getItemCount() >= MAX_NUMBER_OF_ALERTS) {
|
||||
alerts.remove(getItemCount() - 1);
|
||||
}
|
||||
|
||||
alerts.add(0, alert);
|
||||
if (!isUpdating) {
|
||||
isUpdating = true;
|
||||
updateHandler.postDelayed(updateRunnable, 250);
|
||||
}
|
||||
}
|
||||
|
||||
private Runnable updateRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
notifyDataSetChanged();
|
||||
isUpdating = false;
|
||||
}
|
||||
};
|
||||
|
||||
void cancelUpdates() {
|
||||
updateHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
}
|
||||
|
||||
private static class GestureAlert {
|
||||
@Retention(SOURCE)
|
||||
@IntDef( {TYPE_NONE, TYPE_START, TYPE_PROGRESS, TYPE_END, TYPE_OTHER})
|
||||
@interface Type {
|
||||
}
|
||||
|
||||
static final int TYPE_NONE = 0;
|
||||
static final int TYPE_START = 1;
|
||||
static final int TYPE_END = 2;
|
||||
static final int TYPE_PROGRESS = 3;
|
||||
static final int TYPE_OTHER = 4;
|
||||
|
||||
@Type
|
||||
private int alertType;
|
||||
|
||||
private String message;
|
||||
|
||||
@ColorInt
|
||||
private int color;
|
||||
|
||||
GestureAlert(@Type int alertType, String message) {
|
||||
this.alertType = alertType;
|
||||
this.message = message;
|
||||
|
||||
switch (alertType) {
|
||||
case TYPE_NONE:
|
||||
color = android.R.color.black;
|
||||
break;
|
||||
case TYPE_END:
|
||||
color = android.R.color.holo_red_dark;
|
||||
break;
|
||||
case TYPE_OTHER:
|
||||
color = android.R.color.holo_purple;
|
||||
break;
|
||||
case TYPE_PROGRESS:
|
||||
color = android.R.color.holo_orange_dark;
|
||||
break;
|
||||
case TYPE_START:
|
||||
color = android.R.color.holo_green_dark;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int getAlertType() {
|
||||
return alertType;
|
||||
}
|
||||
|
||||
String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
int getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GestureAlert that = (GestureAlert) o;
|
||||
|
||||
if (alertType != that.alertType) {
|
||||
return false;
|
||||
}
|
||||
return message != null ? message.equals(that.message) : that.message == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = alertType;
|
||||
result = 31 * result + (message != null ? message.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.camera
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.BottomSheetBehavior
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.view.View
|
||||
import com.mapbox.geojson.FeatureCollection
|
||||
import com.mapbox.geojson.FeatureCollection.fromJson
|
||||
import com.mapbox.geojson.Point
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng
|
||||
import com.mapbox.mapboxsdk.geometry.LatLngBounds
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.style.layers.Property.ICON_ANCHOR_CENTER
|
||||
import com.mapbox.mapboxsdk.style.layers.PropertyFactory.*
|
||||
import com.mapbox.mapboxsdk.style.layers.SymbolLayer
|
||||
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import com.mapbox.mapboxsdk.testapp.utils.GeoParseUtil.loadStringFromAssets
|
||||
import com.mapbox.mapboxsdk.utils.BitmapUtils
|
||||
import java.net.URISyntaxException
|
||||
import kotlinx.android.synthetic.main.activity_latlngbounds.*
|
||||
|
||||
/**
|
||||
* Test activity showcasing using the LatLngBounds camera API.
|
||||
*/
|
||||
class LatLngBoundsActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private lateinit var bottomSheetBehavior: BottomSheetBehavior<*>
|
||||
private lateinit var bounds: LatLngBounds
|
||||
|
||||
private val peekHeight by lazy {
|
||||
375.toPx(this) // 375dp
|
||||
}
|
||||
|
||||
private val additionalPadding by lazy {
|
||||
32.toPx(this) // 32dp
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_latlngbounds)
|
||||
initMapView(savedInstanceState)
|
||||
}
|
||||
|
||||
private fun initMapView(savedInstanceState: Bundle?) {
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync { map ->
|
||||
mapboxMap = map
|
||||
|
||||
val featureCollection: FeatureCollection = fromJson(loadStringFromAssets(this, "points-sf.geojson"))
|
||||
bounds = createBounds(featureCollection)
|
||||
|
||||
map.getCameraForLatLngBounds(bounds, createPadding(peekHeight))?.let {
|
||||
map.cameraPosition = it
|
||||
}
|
||||
|
||||
try {
|
||||
loadStyle(featureCollection)
|
||||
} catch (e: URISyntaxException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadStyle(featureCollection: FeatureCollection) {
|
||||
mapboxMap.setStyle(Style.Builder()
|
||||
.fromUri(Style.MAPBOX_STREETS)
|
||||
.withLayer(SymbolLayer("symbol", "symbol")
|
||||
.withProperties(
|
||||
iconAllowOverlap(true),
|
||||
iconIgnorePlacement(true),
|
||||
iconImage("icon"),
|
||||
iconAnchor(ICON_ANCHOR_CENTER)
|
||||
)
|
||||
)
|
||||
.withSource(GeoJsonSource("symbol", featureCollection))
|
||||
.withImage("icon", BitmapUtils.getDrawableFromRes(this@LatLngBoundsActivity, R.drawable.ic_android)!!)
|
||||
) {
|
||||
initBottomSheet()
|
||||
fab.setOnClickListener { bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED }
|
||||
}
|
||||
}
|
||||
|
||||
private fun initBottomSheet() {
|
||||
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet)
|
||||
bottomSheetBehavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
|
||||
override fun onSlide(bottomSheet: View, slideOffset: Float) {
|
||||
val offset = convertSlideOffset(slideOffset)
|
||||
val bottomPadding = (peekHeight * offset).toInt()
|
||||
|
||||
mapboxMap.getCameraForLatLngBounds(bounds, createPadding(bottomPadding))?.let {
|
||||
mapboxMap.cameraPosition = it
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
||||
// no-op
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// slideOffset ranges from NaN to -1.0, range from 1.0 to 0 instead
|
||||
fun convertSlideOffset(slideOffset: Float): Float {
|
||||
return if (slideOffset.equals(Float.NaN)) {
|
||||
1.0f
|
||||
} else {
|
||||
1 + slideOffset
|
||||
}
|
||||
}
|
||||
|
||||
fun createPadding(bottomPadding: Int): IntArray {
|
||||
return intArrayOf(additionalPadding, additionalPadding, additionalPadding, bottomPadding)
|
||||
}
|
||||
|
||||
private fun createBounds(featureCollection: FeatureCollection): LatLngBounds {
|
||||
val boundsBuilder = LatLngBounds.Builder()
|
||||
featureCollection.features()?.let {
|
||||
for (feature in it) {
|
||||
val point = feature.geometry() as Point
|
||||
boundsBuilder.include(LatLng(point.latitude(), point.longitude()))
|
||||
}
|
||||
}
|
||||
return boundsBuilder.build()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
}
|
||||
|
||||
fun Int.toPx(context: Context): Int = (this * context.resources.displayMetrics.density).toInt()
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.camera;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.UiSettings;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
/**
|
||||
* Test activity showcasing the zoom Camera API.
|
||||
* <p>
|
||||
* This includes zoomIn, zoomOut, zoomTo, zoomBy (center and custom focal point).
|
||||
* </p>
|
||||
*/
|
||||
public class ManualZoomActivity extends AppCompatActivity {
|
||||
|
||||
private MapboxMap mapboxMap;
|
||||
private MapView mapView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_manual_zoom);
|
||||
|
||||
mapView = (MapView) findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(mapboxMap -> {
|
||||
ManualZoomActivity.this.mapboxMap = mapboxMap;
|
||||
mapboxMap.setStyle(new Style.Builder().fromUri(Style.SATELLITE));
|
||||
UiSettings uiSettings = ManualZoomActivity.this.mapboxMap.getUiSettings();
|
||||
uiSettings.setAllGesturesEnabled(false);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_zoom, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
|
||||
case R.id.action_zoom_in:
|
||||
mapboxMap.animateCamera(CameraUpdateFactory.zoomIn());
|
||||
return true;
|
||||
|
||||
case R.id.action_zoom_out:
|
||||
mapboxMap.animateCamera(CameraUpdateFactory.zoomOut());
|
||||
return true;
|
||||
|
||||
case R.id.action_zoom_by:
|
||||
mapboxMap.animateCamera(CameraUpdateFactory.zoomBy(2));
|
||||
return true;
|
||||
case R.id.action_zoom_to:
|
||||
mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(2));
|
||||
return true;
|
||||
|
||||
case R.id.action_zoom_to_point:
|
||||
View view = getWindow().getDecorView();
|
||||
mapboxMap.animateCamera(
|
||||
CameraUpdateFactory.zoomBy(1, new Point(view.getMeasuredWidth() / 4, view.getMeasuredHeight() / 4)));
|
||||
return true;
|
||||
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.camera;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Test activity showcasing using maximum and minimum zoom levels to restrict camera movement.
|
||||
*/
|
||||
public class MaxMinZoomActivity extends AppCompatActivity implements OnMapReadyCallback {
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
|
||||
private MapboxMap.OnMapClickListener clickListener = new MapboxMap.OnMapClickListener() {
|
||||
@Override
|
||||
public boolean onMapClick(@NonNull LatLng point) {
|
||||
if (mapboxMap != null) {
|
||||
mapboxMap.setStyle(new Style.Builder().fromUri(Style.OUTDOORS));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_maxmin_zoom);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(this);
|
||||
|
||||
mapView.addOnDidFinishLoadingStyleListener(() -> Timber.d("Style Loaded"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull final MapboxMap map) {
|
||||
mapboxMap = map;
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS);
|
||||
mapboxMap.setMinZoomPreference(3);
|
||||
mapboxMap.setMaxZoomPreference(5);
|
||||
mapboxMap.addOnMapClickListener(clickListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mapboxMap != null) {
|
||||
mapboxMap.removeOnMapClickListener(clickListener);
|
||||
}
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.camera;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.maps.UiSettings;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
/**
|
||||
* Test activity showcasing using the scrollBy Camera API by moving x,y pixels above Grenada, Spain.
|
||||
*/
|
||||
public class ScrollByActivity extends AppCompatActivity implements OnMapReadyCallback {
|
||||
|
||||
public static final int MULTIPLIER_PER_PIXEL = 50;
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private SeekBar seekBarX;
|
||||
private SeekBar seekBarY;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_scroll_by);
|
||||
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setDisplayShowHomeEnabled(true);
|
||||
}
|
||||
|
||||
seekBarX = findViewById(R.id.seekbar_move_x);
|
||||
TextView textViewX = findViewById(R.id.textview_x);
|
||||
seekBarX.setOnSeekBarChangeListener(new PixelBarChangeListener(textViewX, R.string.scrollby_x_value));
|
||||
|
||||
seekBarY = findViewById(R.id.seekbar_move_y);
|
||||
TextView textViewY = findViewById(R.id.textview_y);
|
||||
seekBarY.setOnSeekBarChangeListener(new PixelBarChangeListener(textViewY, R.string.scrollby_y_value));
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.setTag(true);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull MapboxMap map) {
|
||||
mapboxMap = map;
|
||||
mapboxMap.setStyle(Style.DARK);
|
||||
|
||||
UiSettings uiSettings = mapboxMap.getUiSettings();
|
||||
uiSettings.setLogoEnabled(false);
|
||||
uiSettings.setAttributionEnabled(false);
|
||||
FloatingActionButton fab = findViewById(R.id.fab);
|
||||
fab.setColorFilter(ContextCompat.getColor(ScrollByActivity.this, R.color.primary));
|
||||
fab.setOnClickListener(view -> mapboxMap.scrollBy(
|
||||
seekBarX.getProgress() * MULTIPLIER_PER_PIXEL,
|
||||
seekBarY.getProgress() * MULTIPLIER_PER_PIXEL)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
onBackPressed();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private static class PixelBarChangeListener implements SeekBar.OnSeekBarChangeListener {
|
||||
|
||||
@StringRes
|
||||
private int prefixTextResource;
|
||||
private TextView valueView;
|
||||
|
||||
PixelBarChangeListener(@NonNull TextView textView, @StringRes int textRes) {
|
||||
valueView = textView;
|
||||
prefixTextResource = textRes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
int value = progress * ScrollByActivity.MULTIPLIER_PER_PIXEL;
|
||||
valueView.setText(String.format(seekBar.getResources().getString(prefixTextResource), value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.customlayer;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.style.layers.CustomLayer;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.testapp.model.customlayer.ExampleCustomLayer;
|
||||
|
||||
/**
|
||||
* Test activity showcasing the Custom Layer API
|
||||
* <p>
|
||||
* Note: experimental API, do not use.
|
||||
* </p>
|
||||
*/
|
||||
public class CustomLayerActivity extends AppCompatActivity {
|
||||
|
||||
private MapboxMap mapboxMap;
|
||||
private MapView mapView;
|
||||
private CustomLayer customLayer;
|
||||
|
||||
private FloatingActionButton fab;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_custom_layer);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(map -> {
|
||||
mapboxMap = map;
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(39.91448, -243.60947), 10));
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS, style -> initFab());
|
||||
});
|
||||
}
|
||||
|
||||
private void initFab() {
|
||||
fab = findViewById(R.id.fab);
|
||||
fab.setColorFilter(ContextCompat.getColor(this, R.color.primary));
|
||||
fab.setOnClickListener(view -> {
|
||||
if (mapboxMap != null) {
|
||||
swapCustomLayer();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void swapCustomLayer() {
|
||||
Style style = mapboxMap.getStyle();
|
||||
if (customLayer != null) {
|
||||
style.removeLayer(customLayer);
|
||||
customLayer = null;
|
||||
fab.setImageResource(R.drawable.ic_layers);
|
||||
} else {
|
||||
customLayer = new CustomLayer("custom",
|
||||
ExampleCustomLayer.createContext());
|
||||
style.addLayerBelow(customLayer, "building");
|
||||
fab.setImageResource(R.drawable.ic_layers_clear);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLayer() {
|
||||
if (customLayer != null) {
|
||||
customLayer.update();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_custom_layer, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_update_layer:
|
||||
updateLayer();
|
||||
return true;
|
||||
case R.id.action_set_color_red:
|
||||
ExampleCustomLayer.setColor(1, 0, 0, 1);
|
||||
return true;
|
||||
case R.id.action_set_color_green:
|
||||
ExampleCustomLayer.setColor(0, 1, 0, 1);
|
||||
return true;
|
||||
case R.id.action_set_color_blue:
|
||||
ExampleCustomLayer.setColor(0, 0, 1, 1);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.espresso;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
public class DeviceIndependentTestActivity extends AppCompatActivity implements OnMapReadyCallback {
|
||||
|
||||
public MapView mapView;
|
||||
protected MapboxMap mapboxMap;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_camera_test);
|
||||
|
||||
// Initialize map as normal
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull MapboxMap map) {
|
||||
mapboxMap = map;
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS);
|
||||
}
|
||||
|
||||
public MapboxMap getMapboxMap() {
|
||||
return mapboxMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.espresso;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
/**
|
||||
* Base activity for instrumentation testing.
|
||||
*/
|
||||
public class EspressoTestActivity extends AppCompatActivity {
|
||||
|
||||
public MapView mapView;
|
||||
protected MapboxMap mapboxMap;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_espresso_test);
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.espresso
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import com.mapbox.mapboxsdk.maps.MapView
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
|
||||
/**
|
||||
* Test activity used for instrumentation tests that require a specific device size.
|
||||
*/
|
||||
class PixelTestActivity : AppCompatActivity(), OnMapReadyCallback {
|
||||
|
||||
lateinit var mapView: MapView
|
||||
lateinit var mapboxMap: MapboxMap
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_pixel_test)
|
||||
mapView = findViewById(R.id.mapView)
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync(this)
|
||||
}
|
||||
|
||||
override fun onMapReady(map: MapboxMap) {
|
||||
mapboxMap = map
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS)
|
||||
}
|
||||
|
||||
public override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
public override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.feature;
|
||||
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.mapbox.geojson.Feature;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.NavUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Test activity showcasing using the query rendered features API to count features in a rectangle.
|
||||
*/
|
||||
public class QueryRenderedFeaturesBoxCountActivity extends AppCompatActivity {
|
||||
|
||||
public MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_query_features_box);
|
||||
|
||||
final View selectionBox = findViewById(R.id.selection_box);
|
||||
|
||||
// Initialize map as normal
|
||||
mapView = (MapView) findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(mapboxMap -> {
|
||||
QueryRenderedFeaturesBoxCountActivity.this.mapboxMap = mapboxMap;
|
||||
|
||||
mapboxMap.setStyle(new Style.Builder().fromUri(Style.MAPBOX_STREETS));
|
||||
|
||||
selectionBox.setOnClickListener(view -> {
|
||||
// Query
|
||||
int top = selectionBox.getTop() - mapView.getTop();
|
||||
int left = selectionBox.getLeft() - mapView.getLeft();
|
||||
RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
|
||||
Timber.i("Querying box %s", box);
|
||||
List<Feature> features = mapboxMap.queryRenderedFeatures(box);
|
||||
|
||||
// Show count
|
||||
Toast.makeText(
|
||||
QueryRenderedFeaturesBoxCountActivity.this,
|
||||
String.format("%s features in box", features.size()),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
|
||||
// Debug output
|
||||
debugOutput(features);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void debugOutput(List<Feature> features) {
|
||||
Timber.i("Got %s features", features.size());
|
||||
for (Feature feature : features) {
|
||||
if (feature != null) {
|
||||
Timber.i("Got feature %s with %s properties and Geometry %s",
|
||||
feature.id(),
|
||||
feature.properties() != null ? feature.properties().entrySet().size() : "<null>",
|
||||
feature.geometry() != null ? feature.geometry().getClass().getSimpleName() : "<null>"
|
||||
);
|
||||
if (feature.properties() != null) {
|
||||
for (Map.Entry<String, JsonElement> entry : feature.properties().entrySet()) {
|
||||
Timber.i("Prop %s - %s", entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Timber.i("Got 0 features");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MapboxMap getMapboxMap() {
|
||||
return mapboxMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
|
||||
if (mapboxMap != null) {
|
||||
// Regression test for #14394
|
||||
mapboxMap.queryRenderedFeatures(new PointF(0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
// activity uses singleInstance for testing purposes
|
||||
// code below provides a default navigation when using the app
|
||||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
// activity uses singleInstance for testing purposes
|
||||
// code below provides a default navigation when using the app
|
||||
NavUtils.navigateHome(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.feature;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.mapbox.geojson.Feature;
|
||||
import com.mapbox.geojson.FeatureCollection;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.style.expressions.Expression;
|
||||
import com.mapbox.mapboxsdk.style.layers.FillLayer;
|
||||
import com.mapbox.mapboxsdk.style.layers.Layer;
|
||||
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.lt;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.toNumber;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillColor;
|
||||
|
||||
/**
|
||||
* Demo's query rendered features
|
||||
*/
|
||||
public class QueryRenderedFeaturesBoxHighlightActivity extends AppCompatActivity {
|
||||
|
||||
public MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_query_features_box);
|
||||
|
||||
final View selectionBox = findViewById(R.id.selection_box);
|
||||
|
||||
// Initialize map as normal
|
||||
mapView = (MapView) findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(mapboxMap -> {
|
||||
QueryRenderedFeaturesBoxHighlightActivity.this.mapboxMap = mapboxMap;
|
||||
|
||||
// Add layer / source
|
||||
final GeoJsonSource source = new GeoJsonSource("highlighted-shapes-source");
|
||||
final Layer layer = new FillLayer("highlighted-shapes-layer", "highlighted-shapes-source")
|
||||
.withProperties(fillColor(Color.RED));
|
||||
|
||||
selectionBox.setOnClickListener(view -> {
|
||||
// Query
|
||||
int top = selectionBox.getTop() - mapView.getTop();
|
||||
int left = selectionBox.getLeft() - mapView.getLeft();
|
||||
RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
|
||||
Timber.i("Querying box %s for buildings", box);
|
||||
|
||||
Expression filter = lt(toNumber(get("height")), literal(10));
|
||||
List<Feature> features = mapboxMap.queryRenderedFeatures(box, filter, "building");
|
||||
|
||||
// Show count
|
||||
Toast.makeText(
|
||||
QueryRenderedFeaturesBoxHighlightActivity.this,
|
||||
String.format("%s features in box", features.size()),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
|
||||
// Update source data
|
||||
source.setGeoJson(FeatureCollection.fromFeatures(features));
|
||||
});
|
||||
|
||||
mapboxMap.setStyle(new Style.Builder()
|
||||
.fromUri(Style.MAPBOX_STREETS)
|
||||
.withSource(source)
|
||||
.withLayer(layer)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
public MapboxMap getMapboxMap() {
|
||||
return mapboxMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.feature;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.mapbox.geojson.Feature;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.style.layers.BackgroundLayer;
|
||||
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
|
||||
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.rgb;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.backgroundColor;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
|
||||
|
||||
/**
|
||||
* Test activity showcasing using the query rendered features API to count Symbols in a rectangle.
|
||||
*/
|
||||
public class QueryRenderedFeaturesBoxSymbolCountActivity extends AppCompatActivity {
|
||||
|
||||
public MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
|
||||
private Toast toast;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_query_features_box);
|
||||
|
||||
final View selectionBox = findViewById(R.id.selection_box);
|
||||
|
||||
// Initialize map as normal
|
||||
mapView = (MapView) findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(mapboxMap -> {
|
||||
QueryRenderedFeaturesBoxSymbolCountActivity.this.mapboxMap = mapboxMap;
|
||||
|
||||
try {
|
||||
String testPoints = ResourceUtils.readRawResource(mapView.getContext(), R.raw.test_points_utrecht);
|
||||
Bitmap markerImage = BitmapFactory.decodeResource(getResources(), R.drawable.mapbox_marker_icon_default);
|
||||
|
||||
mapboxMap.setStyle(new Style.Builder()
|
||||
.withLayer(
|
||||
new BackgroundLayer("bg")
|
||||
.withProperties(
|
||||
backgroundColor(rgb(120, 161, 226))
|
||||
)
|
||||
)
|
||||
.withLayer(
|
||||
new SymbolLayer("symbols-layer", "symbols-source")
|
||||
.withProperties(
|
||||
iconImage("test-icon")
|
||||
)
|
||||
)
|
||||
.withSource(
|
||||
new GeoJsonSource("symbols-source", testPoints)
|
||||
)
|
||||
.withImage("test-icon", markerImage)
|
||||
);
|
||||
} catch (IOException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
selectionBox.setOnClickListener(view -> {
|
||||
// Query
|
||||
int top = selectionBox.getTop() - mapView.getTop();
|
||||
int left = selectionBox.getLeft() - mapView.getLeft();
|
||||
RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
|
||||
Timber.i("Querying box %s", box);
|
||||
List<Feature> features = mapboxMap.queryRenderedFeatures(box, "symbols-layer");
|
||||
|
||||
// Show count
|
||||
if (toast != null) {
|
||||
toast.cancel();
|
||||
}
|
||||
toast = Toast.makeText(
|
||||
QueryRenderedFeaturesBoxSymbolCountActivity.this,
|
||||
String.format("%s features in box", features.size()),
|
||||
Toast.LENGTH_SHORT);
|
||||
toast.show();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public MapboxMap getMapboxMap() {
|
||||
return mapboxMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.feature;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PointF;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.mapbox.geojson.Feature;
|
||||
import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
|
||||
import com.mapbox.mapboxsdk.annotations.Marker;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Test activity showcasing using the query rendered features API to query feature properties on Map click.
|
||||
*/
|
||||
public class QueryRenderedFeaturesPropertiesActivity extends AppCompatActivity {
|
||||
|
||||
public MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private Marker marker;
|
||||
|
||||
private MapboxMap.OnMapClickListener mapClickListener = new MapboxMap.OnMapClickListener() {
|
||||
@Override
|
||||
public boolean onMapClick(@NonNull LatLng point) {
|
||||
final float density = getResources().getDisplayMetrics().density;
|
||||
final PointF pixel = mapboxMap.getProjection().toScreenLocation(point);
|
||||
Timber.i(
|
||||
"Requesting features for %sx%s (%sx%s adjusted for density)",
|
||||
pixel.x, pixel.y, pixel.x / density, pixel.y / density
|
||||
);
|
||||
List<Feature> features = mapboxMap.queryRenderedFeatures(pixel);
|
||||
|
||||
// Debug output
|
||||
debugOutput(features);
|
||||
|
||||
// Remove any previous markers
|
||||
if (marker != null) {
|
||||
mapboxMap.removeMarker(marker);
|
||||
}
|
||||
|
||||
// Add a marker on the clicked point
|
||||
marker = mapboxMap.addMarker(new CustomMarkerOptions().position(point).features(features));
|
||||
mapboxMap.selectMarker(marker);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_query_features_point);
|
||||
|
||||
// Initialize map as normal
|
||||
mapView = (MapView) findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(mapboxMap -> {
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS, style -> {
|
||||
QueryRenderedFeaturesPropertiesActivity.this.mapboxMap = mapboxMap;
|
||||
|
||||
// Add custom window adapter
|
||||
addCustomInfoWindowAdapter(mapboxMap);
|
||||
|
||||
// Add a click listener
|
||||
mapboxMap.addOnMapClickListener(mapClickListener);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void debugOutput(List<Feature> features) {
|
||||
Timber.i("Got %s features", features.size());
|
||||
for (Feature feature : features) {
|
||||
if (feature != null) {
|
||||
Timber.i("Got feature %s with %s properties and Geometry %s",
|
||||
feature.id(),
|
||||
feature.properties() != null ? feature.properties().entrySet().size() : "<null>",
|
||||
feature.geometry() != null ? feature.geometry().getClass().getSimpleName() : "<null>"
|
||||
);
|
||||
if (feature.properties() != null) {
|
||||
for (Map.Entry<String, JsonElement> entry : feature.properties().entrySet()) {
|
||||
Timber.i("Prop %s - %s", entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Timber.i("Got NULL feature");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addCustomInfoWindowAdapter(MapboxMap mapboxMap) {
|
||||
mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() {
|
||||
|
||||
private TextView row(String text) {
|
||||
TextView view = new TextView(QueryRenderedFeaturesPropertiesActivity.this);
|
||||
view.setText(text);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getInfoWindow(@NonNull Marker marker) {
|
||||
CustomMarker customMarker = (CustomMarker) marker;
|
||||
LinearLayout view = new LinearLayout(QueryRenderedFeaturesPropertiesActivity.this);
|
||||
view.setOrientation(LinearLayout.VERTICAL);
|
||||
view.setBackgroundColor(Color.WHITE);
|
||||
|
||||
if (customMarker.features.size() > 0) {
|
||||
view.addView(row(String.format("Found %s features", customMarker.features.size())));
|
||||
Feature feature = customMarker.features.get(0);
|
||||
for (Map.Entry<String, JsonElement> prop : feature.properties().entrySet()) {
|
||||
view.addView(row(String.format("%s: %s", prop.getKey(), prop.getValue())));
|
||||
}
|
||||
} else {
|
||||
view.addView(row("No features here"));
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public MapboxMap getMapboxMap() {
|
||||
return mapboxMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mapboxMap != null) {
|
||||
mapboxMap.removeOnMapClickListener(mapClickListener);
|
||||
}
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
private static class CustomMarker extends Marker {
|
||||
|
||||
private final List<Feature> features;
|
||||
|
||||
CustomMarker(BaseMarkerOptions baseMarkerOptions, List<Feature> features) {
|
||||
super(baseMarkerOptions);
|
||||
this.features = features;
|
||||
}
|
||||
}
|
||||
|
||||
private static class CustomMarkerOptions extends BaseMarkerOptions<CustomMarker, CustomMarkerOptions> {
|
||||
|
||||
|
||||
private List<Feature> features;
|
||||
|
||||
public CustomMarkerOptions features(List<Feature> features) {
|
||||
this.features = features;
|
||||
return this;
|
||||
}
|
||||
|
||||
CustomMarkerOptions() {
|
||||
}
|
||||
|
||||
private CustomMarkerOptions(Parcel in) {
|
||||
// Should implement this
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomMarkerOptions getThis() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomMarker getMarker() {
|
||||
return new CustomMarker(this, features);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<CustomMarkerOptions> CREATOR =
|
||||
new Parcelable.Creator<CustomMarkerOptions>() {
|
||||
public CustomMarkerOptions createFromParcel(Parcel in) {
|
||||
return new CustomMarkerOptions(in);
|
||||
}
|
||||
|
||||
public CustomMarkerOptions[] newArray(int size) {
|
||||
return new CustomMarkerOptions[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
// Should implement this
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.feature;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.Toast;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mapbox.geojson.Feature;
|
||||
import com.mapbox.geojson.FeatureCollection;
|
||||
import com.mapbox.geojson.Point;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.style.expressions.Expression;
|
||||
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
|
||||
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.neq;
|
||||
|
||||
/**
|
||||
* Test activity showcasing using the query source features API to query feature counts
|
||||
*/
|
||||
public class QuerySourceFeaturesActivity extends AppCompatActivity {
|
||||
|
||||
public MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_query_source_features);
|
||||
|
||||
// Initialize map as normal
|
||||
mapView = (MapView) findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(map -> {
|
||||
this.mapboxMap = map;
|
||||
mapboxMap.getStyle(this::initStyle);
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS);
|
||||
});
|
||||
}
|
||||
|
||||
private void initStyle(Style style) {
|
||||
JsonObject properties = new JsonObject();
|
||||
properties.addProperty("key1", "value1");
|
||||
final GeoJsonSource source = new GeoJsonSource("test-source",
|
||||
FeatureCollection.fromFeatures(new Feature[] {
|
||||
Feature.fromGeometry(Point.fromLngLat(17.1, 51), properties),
|
||||
Feature.fromGeometry(Point.fromLngLat(17.2, 51), properties),
|
||||
Feature.fromGeometry(Point.fromLngLat(17.3, 51), properties),
|
||||
Feature.fromGeometry(Point.fromLngLat(17.4, 51), properties),
|
||||
}));
|
||||
style.addSource(source);
|
||||
|
||||
Expression visible = eq(get("key1"), literal("value1"));
|
||||
Expression invisible = neq(get("key1"), literal("value1"));
|
||||
|
||||
CircleLayer layer = new CircleLayer("test-layer", source.getId())
|
||||
.withFilter(visible);
|
||||
style.addLayer(layer);
|
||||
|
||||
// Add a click listener
|
||||
mapboxMap.addOnMapClickListener(point -> {
|
||||
// Query
|
||||
List<Feature> features = source.querySourceFeatures(eq(get("key1"), literal("value1")));
|
||||
Toast.makeText(QuerySourceFeaturesActivity.this, String.format("Found %s features",
|
||||
features.size()), Toast.LENGTH_SHORT).show();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
|
||||
fab.setColorFilter(ContextCompat.getColor(this, R.color.primary));
|
||||
fab.setOnClickListener(view -> {
|
||||
Expression visibility = layer.getFilter();
|
||||
if (visibility != null && visibility.equals(visible)) {
|
||||
layer.setFilter(invisible);
|
||||
fab.setImageResource(R.drawable.ic_layers_clear);
|
||||
} else {
|
||||
layer.setFilter(visible);
|
||||
fab.setImageResource(R.drawable.ic_layers);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.maps.SupportMapFragment
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import com.mapbox.mapboxsdk.testapp.utils.NavUtils
|
||||
import kotlinx.android.synthetic.main.activity_backstack_fragment.*
|
||||
|
||||
/**
|
||||
* Test activity showcasing using the MapFragment API as part of a backstacked fragment.
|
||||
*/
|
||||
class FragmentBackStackActivity : AppCompatActivity() {
|
||||
|
||||
companion object {
|
||||
private const val FRAGMENT_TAG = "map_fragment"
|
||||
}
|
||||
|
||||
private lateinit var mapFragment: SupportMapFragment
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_backstack_fragment)
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
mapFragment = SupportMapFragment.newInstance()
|
||||
mapFragment.getMapAsync { initMap(it) }
|
||||
|
||||
supportFragmentManager.beginTransaction().apply {
|
||||
add(R.id.container, mapFragment, FRAGMENT_TAG)
|
||||
}.commit()
|
||||
} else {
|
||||
supportFragmentManager.findFragmentByTag(FRAGMENT_TAG)?.also { fragment ->
|
||||
if (fragment is SupportMapFragment) {
|
||||
fragment.getMapAsync { initMap(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button.setOnClickListener { handleClick() }
|
||||
}
|
||||
|
||||
private fun initMap(mapboxMap: MapboxMap) {
|
||||
mapboxMap.setStyle(Style.SATELLITE) {
|
||||
mapboxMap.setPadding(300, 300, 300, 300)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleClick() {
|
||||
supportFragmentManager.beginTransaction().apply {
|
||||
replace(R.id.container, NestedViewPagerActivity.ItemAdapter.EmptyFragment())
|
||||
addToBackStack("map_empty_fragment")
|
||||
}.commit()
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (supportFragmentManager.backStackEntryCount == 0) {
|
||||
// activity uses singleInstance for testing purposes
|
||||
// code below provides a default navigation when using the app
|
||||
NavUtils.navigateHome(this)
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapFragment;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
/**
|
||||
* Test activity showcasing using the MapFragment API using SDK Fragments.
|
||||
* <p>
|
||||
* Uses MapboxMapOptions to initialise the Fragment.
|
||||
* </p>
|
||||
*/
|
||||
public class MapFragmentActivity extends AppCompatActivity implements MapFragment.OnMapViewReadyCallback,
|
||||
OnMapReadyCallback, MapView.OnDidFinishRenderingFrameListener {
|
||||
|
||||
private static final String TAG = "com.mapbox.map";
|
||||
private MapboxMap mapboxMap;
|
||||
private MapView mapView;
|
||||
private boolean initialCameraAnimation = true;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_map_fragment);
|
||||
|
||||
MapFragment mapFragment;
|
||||
if (savedInstanceState == null) {
|
||||
mapFragment = MapFragment.newInstance(createFragmentOptions());
|
||||
getFragmentManager()
|
||||
.beginTransaction()
|
||||
.add(R.id.fragment_container, mapFragment, TAG)
|
||||
.commit();
|
||||
} else {
|
||||
mapFragment = (MapFragment) getFragmentManager().findFragmentByTag(TAG);
|
||||
}
|
||||
mapFragment.getMapAsync(this);
|
||||
}
|
||||
|
||||
private MapboxMapOptions createFragmentOptions() {
|
||||
MapboxMapOptions options = MapboxMapOptions.createFromAttributes(this, null);
|
||||
|
||||
options.scrollGesturesEnabled(false);
|
||||
options.zoomGesturesEnabled(false);
|
||||
options.tiltGesturesEnabled(false);
|
||||
options.rotateGesturesEnabled(false);
|
||||
options.debugActive(false);
|
||||
|
||||
LatLng dc = new LatLng(38.90252, -77.02291);
|
||||
|
||||
options.minZoomPreference(9);
|
||||
options.maxZoomPreference(11);
|
||||
options.camera(new CameraPosition.Builder()
|
||||
.target(dc)
|
||||
.zoom(11)
|
||||
.build());
|
||||
return options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapViewReady(MapView map) {
|
||||
mapView = map;
|
||||
mapView.addOnDidFinishRenderingFrameListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull MapboxMap map) {
|
||||
mapboxMap = map;
|
||||
mapboxMap.setStyle(Style.OUTDOORS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.removeOnDidFinishRenderingFrameListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDidFinishRenderingFrame(boolean fully) {
|
||||
if (initialCameraAnimation && fully && mapboxMap != null) {
|
||||
mapboxMap.animateCamera(
|
||||
CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder().tilt(45.0).build()), 5000);
|
||||
initialCameraAnimation = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.maps.SupportMapFragment;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
/**
|
||||
* Test Activity showcasing using multiple static map fragments in one layout.
|
||||
*/
|
||||
public class MultiMapActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_multi_map);
|
||||
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
initFragmentStyle(fragmentManager, R.id.map1, Style.MAPBOX_STREETS);
|
||||
initFragmentStyle(fragmentManager, R.id.map2, Style.LIGHT);
|
||||
initFragmentStyle(fragmentManager, R.id.map3, Style.SATELLITE_STREETS);
|
||||
initFragmentStyle(fragmentManager, R.id.map4, Style.DARK);
|
||||
}
|
||||
|
||||
private void initFragmentStyle(FragmentManager fragmentManager, int fragmentId, String styleId) {
|
||||
((SupportMapFragment) fragmentManager.findFragmentById(fragmentId))
|
||||
.getMapAsync(mapboxMap -> mapboxMap.setStyle(styleId));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.fragment
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.support.v4.app.FragmentStatePagerAdapter
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMapOptions
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.maps.SupportMapFragment
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import kotlinx.android.synthetic.main.activity_recyclerview.*
|
||||
|
||||
/**
|
||||
* TestActivity showcasing how to integrate a MapView in a RecyclerView.
|
||||
* <p>
|
||||
* It requires calling the correct lifecycle methods when detaching and attaching the View to
|
||||
* the RecyclerView with onViewAttachedToWindow and onViewDetachedFromWindow.
|
||||
* </p>
|
||||
*/
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
class NestedViewPagerActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_recyclerview)
|
||||
recyclerView.layoutManager = LinearLayoutManager(this)
|
||||
recyclerView.adapter = ItemAdapter(this, LayoutInflater.from(this), supportFragmentManager)
|
||||
}
|
||||
|
||||
class ItemAdapter(private val context: Context, private val inflater: LayoutInflater, private val fragmentManager: FragmentManager) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
private val items = listOf(
|
||||
"one", "two", "three", ViewPagerItem(), "four", "five", "six", "seven", "eight", "nine", "ten",
|
||||
"eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen",
|
||||
"nineteen", "twenty", "twenty-one"
|
||||
)
|
||||
|
||||
private var mapHolder: ViewPagerHolder? = null
|
||||
|
||||
companion object {
|
||||
const val TYPE_VIEWPAGER = 0
|
||||
const val TYPE_TEXT = 1
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return if (viewType == TYPE_VIEWPAGER) {
|
||||
val viewPager = inflater.inflate(R.layout.item_viewpager, parent, false) as ViewPager
|
||||
mapHolder = ViewPagerHolder(context, viewPager, fragmentManager)
|
||||
return mapHolder as ViewPagerHolder
|
||||
} else {
|
||||
TextHolder(inflater.inflate(android.R.layout.simple_list_item_1, parent, false) as TextView)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return items.count()
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder.itemViewType == TYPE_TEXT) {
|
||||
val textHolder = holder as TextHolder
|
||||
textHolder.bind(items[position] as String)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (items[position] is ViewPagerItem) {
|
||||
TYPE_VIEWPAGER
|
||||
} else {
|
||||
TYPE_TEXT
|
||||
}
|
||||
}
|
||||
|
||||
class TextHolder(val textView: TextView) : RecyclerView.ViewHolder(textView) {
|
||||
fun bind(item: String) {
|
||||
textView.text = item
|
||||
}
|
||||
}
|
||||
|
||||
class ViewPagerItem
|
||||
class ViewPagerHolder(context: Context, private val viewPager: ViewPager, fragmentManager: FragmentManager) : RecyclerView.ViewHolder(viewPager) {
|
||||
init {
|
||||
viewPager.adapter = MapPagerAdapter(context, fragmentManager)
|
||||
viewPager.setOnTouchListener { view, motionEvent ->
|
||||
// Disallow the touch request for recyclerView scroll
|
||||
view.parent.requestDisallowInterceptTouchEvent(true)
|
||||
viewPager.onTouchEvent(motionEvent)
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MapPagerAdapter(private val context: Context, fm: FragmentManager?) : FragmentStatePagerAdapter(fm) {
|
||||
|
||||
override fun getItem(position: Int): Fragment {
|
||||
val options = MapboxMapOptions.createFromAttributes(context)
|
||||
options.textureMode(true)
|
||||
options.doubleTapGesturesEnabled(false)
|
||||
options.rotateGesturesEnabled(false)
|
||||
options.tiltGesturesEnabled(false)
|
||||
options.scrollGesturesEnabled(false)
|
||||
options.zoomGesturesEnabled(false)
|
||||
when (position) {
|
||||
0 -> {
|
||||
options.camera(CameraPosition.Builder().target(LatLng(34.920526, 102.634774)).zoom(3.0).build())
|
||||
val fragment = SupportMapFragment.newInstance(options)
|
||||
fragment.getMapAsync { mapboxMap -> mapboxMap.setStyle(Style.MAPBOX_STREETS) }
|
||||
return fragment
|
||||
}
|
||||
1 -> {
|
||||
return EmptyFragment.newInstance()
|
||||
}
|
||||
2 -> {
|
||||
options.camera(CameraPosition.Builder().target(LatLng(62.326440, 92.764913)).zoom(3.0).build())
|
||||
val fragment = SupportMapFragment.newInstance(options)
|
||||
fragment.getMapAsync { mapboxMap -> mapboxMap.setStyle(Style.DARK) }
|
||||
return fragment
|
||||
}
|
||||
3 -> {
|
||||
return EmptyFragment.newInstance()
|
||||
}
|
||||
4 -> {
|
||||
options.camera(CameraPosition.Builder().target(LatLng(-25.007786, 133.623852)).zoom(3.0).build())
|
||||
val fragment = SupportMapFragment.newInstance(options)
|
||||
fragment.getMapAsync { mapboxMap -> mapboxMap.setStyle(Style.SATELLITE) }
|
||||
return fragment
|
||||
}
|
||||
5 -> {
|
||||
return EmptyFragment.newInstance()
|
||||
}
|
||||
}
|
||||
throw IllegalAccessError()
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return 6
|
||||
}
|
||||
}
|
||||
|
||||
class EmptyFragment : Fragment() {
|
||||
companion object {
|
||||
fun newInstance(): EmptyFragment {
|
||||
return EmptyFragment()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
val textView = TextView(inflater.context)
|
||||
textView.text = "This is an empty Fragment"
|
||||
return textView
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapFragment;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.maps.SupportMapFragment;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
/**
|
||||
* Test activity showcasing using the MapFragment API using Support Library Fragments.
|
||||
* <p>
|
||||
* Uses MapboxMapOptions to initialise the Fragment.
|
||||
* </p>
|
||||
*/
|
||||
public class SupportMapFragmentActivity extends AppCompatActivity implements MapFragment.OnMapViewReadyCallback,
|
||||
OnMapReadyCallback, MapView.OnDidFinishRenderingFrameListener {
|
||||
|
||||
private static final String TAG = "com.mapbox.map";
|
||||
private MapboxMap mapboxMap;
|
||||
private MapView mapView;
|
||||
private boolean initialCameraAnimation = true;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_map_fragment);
|
||||
SupportMapFragment mapFragment;
|
||||
if (savedInstanceState == null) {
|
||||
mapFragment = SupportMapFragment.newInstance(createFragmentOptions());
|
||||
getSupportFragmentManager()
|
||||
.beginTransaction()
|
||||
.add(R.id.fragment_container, mapFragment, TAG)
|
||||
.commit();
|
||||
} else {
|
||||
mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentByTag(TAG);
|
||||
}
|
||||
mapFragment.getMapAsync(this);
|
||||
|
||||
}
|
||||
|
||||
private MapboxMapOptions createFragmentOptions() {
|
||||
MapboxMapOptions options = MapboxMapOptions.createFromAttributes(this, null);
|
||||
|
||||
options.scrollGesturesEnabled(false);
|
||||
options.zoomGesturesEnabled(false);
|
||||
options.tiltGesturesEnabled(false);
|
||||
options.rotateGesturesEnabled(false);
|
||||
options.debugActive(false);
|
||||
|
||||
LatLng dc = new LatLng(38.90252, -77.02291);
|
||||
|
||||
options.minZoomPreference(9);
|
||||
options.maxZoomPreference(11);
|
||||
options.camera(new CameraPosition.Builder()
|
||||
.target(dc)
|
||||
.zoom(11)
|
||||
.build());
|
||||
return options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapViewReady(MapView map) {
|
||||
mapView = map;
|
||||
mapView.addOnDidFinishRenderingFrameListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull MapboxMap map) {
|
||||
mapboxMap = map;
|
||||
mapboxMap.setStyle(Style.SATELLITE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.removeOnDidFinishRenderingFrameListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDidFinishRenderingFrame(boolean fully) {
|
||||
if (initialCameraAnimation && fully && mapboxMap != null) {
|
||||
mapboxMap.animateCamera(
|
||||
CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder().tilt(45.0).build()), 5000);
|
||||
initialCameraAnimation = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.fragment
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.support.v4.app.FragmentStatePagerAdapter
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMapOptions
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.maps.SupportMapFragment
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import kotlinx.android.synthetic.main.activity_viewpager.*
|
||||
|
||||
/**
|
||||
* Test activity showcasing using the Android SDK ViewPager API to show MapFragments.
|
||||
*/
|
||||
class ViewPagerActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_viewpager)
|
||||
viewPager.adapter = MapFragmentAdapter(this, supportFragmentManager)
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||
super.onRestoreInstanceState(savedInstanceState)
|
||||
val currentPosition = viewPager.currentItem
|
||||
val offscreenLimit = viewPager.offscreenPageLimit
|
||||
for (i in currentPosition - offscreenLimit..currentPosition + offscreenLimit) {
|
||||
if (i < 0 || i > viewPager.adapter?.count ?: 0) {
|
||||
continue
|
||||
}
|
||||
val mapFragment = viewPager.adapter?.instantiateItem(viewPager, i) as SupportMapFragment
|
||||
mapFragment.getMapAsync(i)
|
||||
}
|
||||
}
|
||||
|
||||
internal class MapFragmentAdapter(private val context: Context, fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager) {
|
||||
|
||||
override fun getCount(): Int {
|
||||
return NUM_ITEMS
|
||||
}
|
||||
|
||||
override fun getItem(position: Int): Fragment? {
|
||||
val options = MapboxMapOptions.createFromAttributes(context)
|
||||
options.textureMode(true)
|
||||
options.camera(
|
||||
CameraPosition.Builder()
|
||||
.zoom(3.0)
|
||||
.target(
|
||||
when (position) {
|
||||
0 -> {
|
||||
LatLng(34.920526, 102.634774)
|
||||
}
|
||||
1 -> {
|
||||
LatLng(62.326440, 92.764913)
|
||||
}
|
||||
2 -> {
|
||||
LatLng(-25.007786, 133.623852)
|
||||
}
|
||||
3 -> {
|
||||
LatLng(62.326440, 92.764913)
|
||||
}
|
||||
else -> {
|
||||
LatLng(34.920526, 102.634774)
|
||||
}
|
||||
}
|
||||
)
|
||||
.build())
|
||||
|
||||
val fragment = SupportMapFragment.newInstance(options)
|
||||
fragment.getMapAsync(position)
|
||||
return fragment
|
||||
}
|
||||
|
||||
override fun getPageTitle(position: Int): CharSequence? {
|
||||
return "Page $position"
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val NUM_ITEMS = 5
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun SupportMapFragment.getMapAsync(index: Int) {
|
||||
this.getMapAsync {
|
||||
it.setStyle(
|
||||
when (index) {
|
||||
0 -> Style.MAPBOX_STREETS
|
||||
1 -> Style.DARK
|
||||
2 -> Style.SATELLITE
|
||||
3 -> Style.LIGHT
|
||||
4 -> Style.TRAFFIC_NIGHT
|
||||
else -> Style.MAPBOX_STREETS
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.imagegenerator;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.print.PrintHelper;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
/**
|
||||
* Test activity showcasing using the Snaphot API to print a Map.
|
||||
*/
|
||||
public class PrintActivity extends AppCompatActivity implements MapboxMap.SnapshotReadyCallback {
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_print);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(this::initMap);
|
||||
|
||||
final View fab = findViewById(R.id.fab);
|
||||
if (fab != null) {
|
||||
fab.setOnClickListener(view -> {
|
||||
if (mapboxMap != null && mapboxMap.getStyle() != null) {
|
||||
mapboxMap.snapshot(PrintActivity.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void initMap(MapboxMap mapboxMap) {
|
||||
this.mapboxMap = mapboxMap;
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSnapshotReady(Bitmap snapshot) {
|
||||
PrintHelper photoPrinter = new PrintHelper(this);
|
||||
photoPrinter.setScaleMode(PrintHelper.SCALE_MODE_FIT);
|
||||
photoPrinter.printBitmap("map.jpg - mapbox print job", snapshot);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.imagegenerator
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import com.mapbox.mapboxsdk.log.Logger
|
||||
import com.mapbox.mapboxsdk.maps.MapView
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import kotlinx.android.synthetic.main.activity_snapshot.*
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Test activity showcasing the Snapshot API to create and display a bitmap of the current shown Map.
|
||||
*/
|
||||
class SnapshotActivity : AppCompatActivity(), OnMapReadyCallback {
|
||||
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
|
||||
private val idleListener = object : MapView.OnDidFinishRenderingFrameListener {
|
||||
override fun onDidFinishRenderingFrame(fully: Boolean) {
|
||||
if (fully) {
|
||||
mapView.removeOnDidFinishRenderingFrameListener(this)
|
||||
Logger.v(TAG, LOG_MESSAGE)
|
||||
mapboxMap.snapshot { snapshot ->
|
||||
imageView.setImageBitmap(snapshot)
|
||||
mapView.addOnDidFinishRenderingFrameListener(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_snapshot)
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync(this)
|
||||
}
|
||||
|
||||
override fun onMapReady(map: MapboxMap) {
|
||||
mapboxMap = map
|
||||
mapboxMap.setStyle(Style.Builder().fromUri(Style.OUTDOORS)) { mapView.addOnDidFinishRenderingFrameListener(idleListener) }
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapboxMap.snapshot {
|
||||
Timber.e("Regression test for https://github.com/mapbox/mapbox-gl-native/pull/11358")
|
||||
}
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
public override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
public override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.removeOnDidFinishRenderingFrameListener(idleListener)
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "Mbgl-SnapshotActivity"
|
||||
const val LOG_MESSAGE = "OnSnapshot"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.infowindow;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.content.res.ResourcesCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mapbox.mapboxsdk.annotations.InfoWindow;
|
||||
import com.mapbox.mapboxsdk.annotations.Marker;
|
||||
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.IconUtils;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Test activity showcasing how to dynamically update InfoWindow when Using an MapboxMap.InfoWindowAdapter.
|
||||
*/
|
||||
public class DynamicInfoWindowAdapterActivity extends AppCompatActivity implements OnMapReadyCallback {
|
||||
|
||||
private static final LatLng PARIS = new LatLng(48.864716, 2.349014);
|
||||
|
||||
private MapboxMap mapboxMap;
|
||||
private MapView mapView;
|
||||
private Marker marker;
|
||||
|
||||
private MapboxMap.OnMapClickListener mapClickListener = new MapboxMap.OnMapClickListener() {
|
||||
@Override
|
||||
public boolean onMapClick(@NonNull LatLng point) {
|
||||
if (marker == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Distance from click to marker
|
||||
double distanceKm = marker.getPosition().distanceTo(point) / 1000;
|
||||
|
||||
// Get the info window
|
||||
final InfoWindow infoWindow = marker.getInfoWindow();
|
||||
|
||||
// Get the view from the info window
|
||||
if (infoWindow != null && infoWindow.getView() != null) {
|
||||
// Set the new text on the text view in the info window
|
||||
TextView textView = (TextView) infoWindow.getView();
|
||||
textView.setText(String.format(Locale.getDefault(), "%.2fkm", distanceKm));
|
||||
// Update the info window position (as the text length changes)
|
||||
textView.post(infoWindow::update);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_infowindow_adapter);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull MapboxMap map) {
|
||||
mapboxMap = map;
|
||||
|
||||
map.setStyle(Style.MAPBOX_STREETS);
|
||||
|
||||
// Add info window adapter
|
||||
addCustomInfoWindowAdapter(mapboxMap);
|
||||
|
||||
// Keep info windows open on click
|
||||
mapboxMap.getUiSettings().setDeselectMarkersOnTap(false);
|
||||
|
||||
// Add a marker
|
||||
marker = addMarker(mapboxMap);
|
||||
mapboxMap.selectMarker(marker);
|
||||
|
||||
// On map click, change the info window contents
|
||||
mapboxMap.addOnMapClickListener(mapClickListener);
|
||||
|
||||
// Focus on Paris
|
||||
mapboxMap.animateCamera(CameraUpdateFactory.newLatLng(PARIS));
|
||||
}
|
||||
|
||||
private Marker addMarker(MapboxMap mapboxMap) {
|
||||
return mapboxMap.addMarker(
|
||||
new MarkerOptions()
|
||||
.position(PARIS)
|
||||
.icon(IconUtils.drawableToIcon(this, R.drawable.ic_location_city,
|
||||
ResourcesCompat.getColor(getResources(), R.color.mapbox_blue, getTheme()))
|
||||
));
|
||||
}
|
||||
|
||||
private void addCustomInfoWindowAdapter(final MapboxMap mapboxMap) {
|
||||
final int padding = (int) getResources().getDimension(R.dimen.attr_margin);
|
||||
mapboxMap.setInfoWindowAdapter(marker -> {
|
||||
TextView textView = new TextView(DynamicInfoWindowAdapterActivity.this);
|
||||
textView.setText(marker.getTitle());
|
||||
textView.setBackgroundColor(Color.WHITE);
|
||||
textView.setText(R.string.action_calculate_distance);
|
||||
textView.setPadding(padding, padding, padding, padding);
|
||||
return textView;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mapboxMap != null) {
|
||||
mapboxMap.removeOnMapClickListener(mapClickListener);
|
||||
}
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.infowindow;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.mapbox.mapboxsdk.annotations.Marker;
|
||||
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
/**
|
||||
* Test activity showcasing using the InfoWindow API above Washington D.C.
|
||||
* <p>
|
||||
* Allows to test mulitple concurrently open InfoWindows.
|
||||
* </p>
|
||||
*/
|
||||
public class InfoWindowActivity extends AppCompatActivity
|
||||
implements OnMapReadyCallback, MapboxMap.OnInfoWindowCloseListener, MapboxMap.OnInfoWindowClickListener,
|
||||
MapboxMap.OnInfoWindowLongClickListener {
|
||||
|
||||
private MapboxMap mapboxMap;
|
||||
private MapView mapView;
|
||||
private Marker customMarker;
|
||||
|
||||
private MapboxMap.OnMapLongClickListener mapLongClickListener = new MapboxMap.OnMapLongClickListener() {
|
||||
@Override
|
||||
public boolean onMapLongClick(@NonNull LatLng point) {
|
||||
if (customMarker != null) {
|
||||
// Remove previous added marker
|
||||
mapboxMap.removeAnnotation(customMarker);
|
||||
customMarker = null;
|
||||
}
|
||||
|
||||
// Add marker on long click location with default marker image
|
||||
customMarker = mapboxMap.addMarker(new MarkerOptions()
|
||||
.title("Custom Marker")
|
||||
.snippet(new DecimalFormat("#.#####").format(point.getLatitude()) + ", "
|
||||
+ new DecimalFormat("#.#####").format(point.getLongitude()))
|
||||
.position(point));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_infowindow);
|
||||
|
||||
mapView = (MapView) findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull MapboxMap mapboxMap) {
|
||||
this.mapboxMap = mapboxMap;
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS, style -> {
|
||||
addMarkers();
|
||||
addInfoWindowListeners();
|
||||
});
|
||||
}
|
||||
|
||||
private void addMarkers() {
|
||||
mapboxMap.addMarker(new MarkerOptions()
|
||||
.title("Intersection")
|
||||
.snippet("H St NW with 15th St NW")
|
||||
.position(new LatLng(38.9002073, -77.03364419)));
|
||||
|
||||
mapboxMap.addMarker(new MarkerOptions().title("Intersection")
|
||||
.snippet("E St NW with 17th St NW")
|
||||
.position(new LatLng(38.8954236, -77.0394623)));
|
||||
|
||||
mapboxMap.addMarker(new MarkerOptions().title("The Ellipse").position(new LatLng(38.89393, -77.03654)));
|
||||
|
||||
mapboxMap.addMarker(new MarkerOptions().position(new LatLng(38.89596, -77.03434)));
|
||||
|
||||
mapboxMap.addMarker(new MarkerOptions().snippet("Lafayette Square").position(new LatLng(38.89949, -77.03656)));
|
||||
|
||||
Marker marker = mapboxMap.addMarker(new MarkerOptions()
|
||||
.title("White House")
|
||||
.snippet("The official residence and principal workplace of the President of the United States, "
|
||||
+ "located at 1600 Pennsylvania Avenue NW in Washington, D.C. It has been the residence of every"
|
||||
+ "U.S. president since John Adams in 1800.")
|
||||
.position(new LatLng(38.897705003219784, -77.03655168667463)));
|
||||
|
||||
// open InfoWindow at startup
|
||||
mapboxMap.selectMarker(marker);
|
||||
}
|
||||
|
||||
private void addInfoWindowListeners() {
|
||||
mapboxMap.setOnInfoWindowCloseListener(this);
|
||||
mapboxMap.addOnMapLongClickListener(mapLongClickListener);
|
||||
mapboxMap.setOnInfoWindowClickListener(this);
|
||||
mapboxMap.setOnInfoWindowLongClickListener(this);
|
||||
}
|
||||
|
||||
private void toggleConcurrentInfoWindow(boolean allowConcurrentInfoWindow) {
|
||||
mapboxMap.deselectMarkers();
|
||||
mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(allowConcurrentInfoWindow);
|
||||
}
|
||||
|
||||
private void toggleDeselectMarkersOnTap(boolean deselectMarkersOnTap) {
|
||||
mapboxMap.getUiSettings().setDeselectMarkersOnTap(deselectMarkersOnTap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInfoWindowClick(@NonNull Marker marker) {
|
||||
Toast.makeText(getApplicationContext(), "OnClick: " + marker.getTitle(), Toast.LENGTH_LONG).show();
|
||||
// returning true will leave the info window open
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInfoWindowClose(Marker marker) {
|
||||
Toast.makeText(getApplicationContext(), "OnClose: " + marker.getTitle(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInfoWindowLongClick(Marker marker) {
|
||||
Toast.makeText(getApplicationContext(), "OnLongClick: " + marker.getTitle(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mapboxMap != null) {
|
||||
mapboxMap.removeOnMapLongClickListener(mapLongClickListener);
|
||||
}
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_infowindow, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_toggle_concurrent_infowindow:
|
||||
toggleConcurrentInfoWindow(!item.isChecked());
|
||||
item.setChecked(!item.isChecked());
|
||||
return true;
|
||||
case R.id.action_toggle_deselect_markers_on_tap:
|
||||
toggleDeselectMarkersOnTap(!item.isChecked());
|
||||
item.setChecked(!item.isChecked());
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.infowindow;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mapbox.mapboxsdk.annotations.Icon;
|
||||
import com.mapbox.mapboxsdk.annotations.Marker;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.testapp.model.annotations.CityStateMarker;
|
||||
import com.mapbox.mapboxsdk.testapp.model.annotations.CityStateMarkerOptions;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.IconUtils;
|
||||
|
||||
/**
|
||||
* Test activity showcasing using an InfoWindowAdapter to provide a custom InfoWindow content.
|
||||
*/
|
||||
public class InfoWindowAdapterActivity extends AppCompatActivity {
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_infowindow_adapter);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(map -> {
|
||||
mapboxMap = map;
|
||||
map.setStyle(Style.MAPBOX_STREETS, style -> {
|
||||
addMarkers();
|
||||
addCustomInfoWindowAdapter();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void addMarkers() {
|
||||
mapboxMap.addMarker(generateCityStateMarker("Andorra", 42.505777, 1.52529, "#F44336"));
|
||||
mapboxMap.addMarker(generateCityStateMarker("Luxembourg", 49.815273, 6.129583, "#3F51B5"));
|
||||
mapboxMap.addMarker(generateCityStateMarker("Monaco", 43.738418, 7.424616, "#673AB7"));
|
||||
mapboxMap.addMarker(generateCityStateMarker("Vatican City", 41.902916, 12.453389, "#009688"));
|
||||
mapboxMap.addMarker(generateCityStateMarker("San Marino", 43.942360, 12.457777, "#795548"));
|
||||
mapboxMap.addMarker(generateCityStateMarker("Liechtenstein", 47.166000, 9.555373, "#FF5722"));
|
||||
}
|
||||
|
||||
private CityStateMarkerOptions generateCityStateMarker(String title, double lat, double lng, String color) {
|
||||
CityStateMarkerOptions marker = new CityStateMarkerOptions();
|
||||
marker.title(title);
|
||||
marker.position(new LatLng(lat, lng));
|
||||
marker.infoWindowBackground(color);
|
||||
|
||||
Icon icon = IconUtils.drawableToIcon(this, R.drawable.ic_location_city, Color.parseColor(color));
|
||||
marker.icon(icon);
|
||||
return marker;
|
||||
}
|
||||
|
||||
private void addCustomInfoWindowAdapter() {
|
||||
mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() {
|
||||
|
||||
private int tenDp = (int) getResources().getDimension(R.dimen.attr_margin);
|
||||
|
||||
@Override
|
||||
public View getInfoWindow(@NonNull Marker marker) {
|
||||
TextView textView = new TextView(InfoWindowAdapterActivity.this);
|
||||
textView.setText(marker.getTitle());
|
||||
textView.setTextColor(Color.WHITE);
|
||||
|
||||
if (marker instanceof CityStateMarker) {
|
||||
CityStateMarker cityStateMarker = (CityStateMarker) marker;
|
||||
textView.setBackgroundColor(Color.parseColor(cityStateMarker.getInfoWindowBackgroundColor()));
|
||||
}
|
||||
|
||||
textView.setPadding(tenDp, tenDp, tenDp, tenDp);
|
||||
return textView;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.location;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.mapbox.android.core.permissions.PermissionsListener;
|
||||
import com.mapbox.android.core.permissions.PermissionsManager;
|
||||
import com.mapbox.mapboxsdk.location.LocationComponent;
|
||||
import com.mapbox.mapboxsdk.location.LocationComponentActivationOptions;
|
||||
import com.mapbox.mapboxsdk.location.LocationComponentOptions;
|
||||
import com.mapbox.mapboxsdk.location.modes.CameraMode;
|
||||
import com.mapbox.mapboxsdk.location.modes.RenderMode;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class LocationComponentActivationActivity extends AppCompatActivity implements OnMapReadyCallback {
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private PermissionsManager permissionsManager;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_location_layer_activation_builder);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
|
||||
mapView.onCreate(savedInstanceState);
|
||||
|
||||
if (PermissionsManager.areLocationPermissionsGranted(this)) {
|
||||
mapView.getMapAsync(this);
|
||||
} else {
|
||||
permissionsManager = new PermissionsManager(new PermissionsListener() {
|
||||
@Override
|
||||
public void onExplanationNeeded(List<String> permissionsToExplain) {
|
||||
Toast.makeText(LocationComponentActivationActivity.this, "You need to accept location permissions.",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionResult(boolean granted) {
|
||||
if (granted) {
|
||||
mapView.getMapAsync(LocationComponentActivationActivity.this);
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
permissionsManager.requestLocationPermissions(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull MapboxMap mapboxMap) {
|
||||
this.mapboxMap = mapboxMap;
|
||||
mapboxMap.setStyle(Style.DARK,
|
||||
style -> activateLocationComponent(style));
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
private void activateLocationComponent(@NonNull Style style) {
|
||||
LocationComponent locationComponent = mapboxMap.getLocationComponent();
|
||||
|
||||
LocationComponentOptions locationComponentOptions = LocationComponentOptions.builder(this)
|
||||
.elevation(5)
|
||||
.accuracyAlpha(.6f)
|
||||
.accuracyColor(Color.GREEN)
|
||||
.foregroundDrawable(R.drawable.mapbox_logo_helmet)
|
||||
.build();
|
||||
|
||||
LocationComponentActivationOptions locationComponentActivationOptions = LocationComponentActivationOptions
|
||||
.builder(this, style)
|
||||
.locationComponentOptions(locationComponentOptions)
|
||||
.useDefaultLocationEngine(true)
|
||||
.build();
|
||||
|
||||
locationComponent.activateLocationComponent(locationComponentActivationOptions);
|
||||
locationComponent.setLocationComponentEnabled(true);
|
||||
locationComponent.setRenderMode(RenderMode.NORMAL);
|
||||
locationComponent.setCameraMode(CameraMode.TRACKING);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.location
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import com.mapbox.android.core.location.LocationEngineCallback
|
||||
import com.mapbox.android.core.location.LocationEngineResult
|
||||
import com.mapbox.android.core.permissions.PermissionsListener
|
||||
import com.mapbox.android.core.permissions.PermissionsManager
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng
|
||||
import com.mapbox.mapboxsdk.location.LocationComponentActivationOptions
|
||||
import com.mapbox.mapboxsdk.maps.MapView
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import kotlinx.android.synthetic.main.activity_location_layer_fragment.*
|
||||
|
||||
class LocationFragmentActivity : AppCompatActivity() {
|
||||
private lateinit var permissionsManager: PermissionsManager
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_location_layer_fragment)
|
||||
|
||||
fab.setOnClickListener {
|
||||
val fragment = supportFragmentManager.findFragmentByTag(EmptyFragment.TAG)
|
||||
if (fragment == null) {
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.container, EmptyFragment.newInstance(), EmptyFragment.TAG)
|
||||
.addToBackStack("transaction2")
|
||||
.commit()
|
||||
} else {
|
||||
this.onBackPressed()
|
||||
}
|
||||
}
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
if (PermissionsManager.areLocationPermissionsGranted(this)) {
|
||||
if (savedInstanceState == null) {
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.container, LocationFragment.newInstance(), LocationFragment.TAG)
|
||||
.commit()
|
||||
}
|
||||
} else {
|
||||
permissionsManager = PermissionsManager(object : PermissionsListener {
|
||||
override fun onExplanationNeeded(permissionsToExplain: MutableList<String>?) {
|
||||
Toast.makeText(this@LocationFragmentActivity, "You need to accept location permissions.",
|
||||
Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
override fun onPermissionResult(granted: Boolean) {
|
||||
if (granted) {
|
||||
if (savedInstanceState == null) {
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.container, LocationFragment.newInstance(), LocationFragment.TAG)
|
||||
.commit()
|
||||
}
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
})
|
||||
permissionsManager.requestLocationPermissions(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
}
|
||||
|
||||
class LocationFragment : Fragment(), LocationEngineCallback<LocationEngineResult> {
|
||||
companion object {
|
||||
const val TAG = "LFragment"
|
||||
fun newInstance(): LocationFragment {
|
||||
return LocationFragment()
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var mapView: MapView
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
mapView = MapView(inflater.context)
|
||||
return mapView
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync {
|
||||
mapboxMap = it
|
||||
it.setStyle(Style.MAPBOX_STREETS) { style ->
|
||||
val component = mapboxMap.locationComponent
|
||||
|
||||
component.activateLocationComponent(LocationComponentActivationOptions
|
||||
.builder(activity!!, style)
|
||||
.useDefaultLocationEngine(true)
|
||||
.build())
|
||||
|
||||
component.isLocationComponentEnabled = true
|
||||
component.locationEngine?.getLastLocation(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSuccess(result: LocationEngineResult?) {
|
||||
mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(LatLng(result?.lastLocation), 12.0))
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
// noop
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
}
|
||||
|
||||
class EmptyFragment : Fragment() {
|
||||
companion object {
|
||||
const val TAG = "EmptyFragment"
|
||||
fun newInstance(): EmptyFragment {
|
||||
return EmptyFragment()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
val textView = TextView(inflater.context)
|
||||
textView.text = "This is an empty Fragment"
|
||||
return textView
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.location;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.mapbox.android.core.permissions.PermissionsListener;
|
||||
import com.mapbox.android.core.permissions.PermissionsManager;
|
||||
import com.mapbox.mapboxsdk.location.LocationComponent;
|
||||
import com.mapbox.mapboxsdk.location.LocationComponentActivationOptions;
|
||||
import com.mapbox.mapboxsdk.location.modes.RenderMode;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class LocationMapChangeActivity extends AppCompatActivity implements OnMapReadyCallback {
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private PermissionsManager permissionsManager;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_location_layer_map_change);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
FloatingActionButton stylesFab = findViewById(R.id.fabStyles);
|
||||
|
||||
stylesFab.setOnClickListener(v -> {
|
||||
if (mapboxMap != null) {
|
||||
mapboxMap.setStyle(new Style.Builder().fromUri(Utils.getNextStyle()));
|
||||
}
|
||||
});
|
||||
|
||||
mapView.onCreate(savedInstanceState);
|
||||
|
||||
if (PermissionsManager.areLocationPermissionsGranted(this)) {
|
||||
mapView.getMapAsync(this);
|
||||
} else {
|
||||
permissionsManager = new PermissionsManager(new PermissionsListener() {
|
||||
@Override
|
||||
public void onExplanationNeeded(List<String> permissionsToExplain) {
|
||||
Toast.makeText(LocationMapChangeActivity.this, "You need to accept location permissions.",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionResult(boolean granted) {
|
||||
if (granted) {
|
||||
mapView.getMapAsync(LocationMapChangeActivity.this);
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
permissionsManager.requestLocationPermissions(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull MapboxMap mapboxMap) {
|
||||
this.mapboxMap = mapboxMap;
|
||||
mapboxMap.setStyle(new Style.Builder().fromUri(Utils.getNextStyle()),
|
||||
style -> activateLocationComponent(style));
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
private void activateLocationComponent(@NonNull Style style) {
|
||||
LocationComponent locationComponent = mapboxMap.getLocationComponent();
|
||||
|
||||
locationComponent.activateLocationComponent(
|
||||
LocationComponentActivationOptions
|
||||
.builder(this, style)
|
||||
.useDefaultLocationEngine(true)
|
||||
.build());
|
||||
|
||||
locationComponent.setLocationComponentEnabled(true);
|
||||
locationComponent.setRenderMode(RenderMode.COMPASS);
|
||||
|
||||
locationComponent.addOnLocationClickListener(
|
||||
() -> Toast.makeText(this, "Location clicked", Toast.LENGTH_SHORT).show());
|
||||
|
||||
locationComponent.addOnLocationLongClickListener(
|
||||
() -> Toast.makeText(this, "Location long clicked", Toast.LENGTH_SHORT).show());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,432 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.location;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.res.Configuration;
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.ListPopupWindow;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.mapbox.android.core.location.LocationEngineRequest;
|
||||
import com.mapbox.android.core.permissions.PermissionsListener;
|
||||
import com.mapbox.android.core.permissions.PermissionsManager;
|
||||
import com.mapbox.mapboxsdk.location.LocationComponent;
|
||||
import com.mapbox.mapboxsdk.location.LocationComponentActivationOptions;
|
||||
import com.mapbox.mapboxsdk.location.LocationComponentOptions;
|
||||
import com.mapbox.mapboxsdk.location.OnCameraTrackingChangedListener;
|
||||
import com.mapbox.mapboxsdk.location.OnLocationCameraTransitionListener;
|
||||
import com.mapbox.mapboxsdk.location.OnLocationClickListener;
|
||||
import com.mapbox.mapboxsdk.location.modes.CameraMode;
|
||||
import com.mapbox.mapboxsdk.location.modes.RenderMode;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LocationModesActivity extends AppCompatActivity implements OnMapReadyCallback,
|
||||
OnLocationClickListener, OnCameraTrackingChangedListener {
|
||||
|
||||
private MapView mapView;
|
||||
private Button locationModeBtn;
|
||||
private Button locationTrackingBtn;
|
||||
|
||||
private PermissionsManager permissionsManager;
|
||||
|
||||
private LocationComponent locationComponent;
|
||||
private MapboxMap mapboxMap;
|
||||
private boolean defaultStyle = false;
|
||||
|
||||
private static final String SAVED_STATE_CAMERA = "saved_state_camera";
|
||||
private static final String SAVED_STATE_RENDER = "saved_state_render";
|
||||
private static final String SAVED_STATE_LOCATION = "saved_state_location";
|
||||
|
||||
@CameraMode.Mode
|
||||
private int cameraMode = CameraMode.TRACKING;
|
||||
|
||||
@RenderMode.Mode
|
||||
private int renderMode = RenderMode.NORMAL;
|
||||
|
||||
private Location lastLocation;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_location_layer_mode);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
|
||||
locationModeBtn = findViewById(R.id.button_location_mode);
|
||||
locationModeBtn.setOnClickListener(v -> {
|
||||
if (locationComponent == null) {
|
||||
return;
|
||||
}
|
||||
showModeListDialog();
|
||||
});
|
||||
|
||||
locationTrackingBtn = findViewById(R.id.button_location_tracking);
|
||||
locationTrackingBtn.setOnClickListener(v -> {
|
||||
if (locationComponent == null) {
|
||||
return;
|
||||
}
|
||||
showTrackingListDialog();
|
||||
});
|
||||
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
cameraMode = savedInstanceState.getInt(SAVED_STATE_CAMERA);
|
||||
renderMode = savedInstanceState.getInt(SAVED_STATE_RENDER);
|
||||
lastLocation = savedInstanceState.getParcelable(SAVED_STATE_LOCATION);
|
||||
}
|
||||
|
||||
mapView.onCreate(savedInstanceState);
|
||||
|
||||
if (PermissionsManager.areLocationPermissionsGranted(this)) {
|
||||
mapView.getMapAsync(this);
|
||||
} else {
|
||||
permissionsManager = new PermissionsManager(new PermissionsListener() {
|
||||
@Override
|
||||
public void onExplanationNeeded(List<String> permissionsToExplain) {
|
||||
Toast.makeText(LocationModesActivity.this, "You need to accept location permissions.",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionResult(boolean granted) {
|
||||
if (granted) {
|
||||
mapView.getMapAsync(LocationModesActivity.this);
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
permissionsManager.requestLocationPermissions(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@Override
|
||||
public void onMapReady(@NonNull MapboxMap mapboxMap) {
|
||||
this.mapboxMap = mapboxMap;
|
||||
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS, style -> {
|
||||
locationComponent = mapboxMap.getLocationComponent();
|
||||
locationComponent.activateLocationComponent(
|
||||
LocationComponentActivationOptions
|
||||
.builder(this, style)
|
||||
.useDefaultLocationEngine(true)
|
||||
.locationEngineRequest(new LocationEngineRequest.Builder(750)
|
||||
.setFastestInterval(750)
|
||||
.setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY)
|
||||
.build())
|
||||
.build());
|
||||
|
||||
toggleStyle();
|
||||
locationComponent.setLocationComponentEnabled(true);
|
||||
locationComponent.addOnLocationClickListener(this);
|
||||
locationComponent.addOnCameraTrackingChangedListener(this);
|
||||
locationComponent.setCameraMode(cameraMode);
|
||||
setRendererMode(renderMode);
|
||||
locationComponent.forceLocationUpdate(lastLocation);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_location_mode, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (locationComponent == null) {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
int id = item.getItemId();
|
||||
if (id == R.id.action_style_change) {
|
||||
toggleStyle();
|
||||
return true;
|
||||
} else if (id == R.id.action_map_style_change) {
|
||||
toggleMapStyle();
|
||||
return true;
|
||||
} else if (id == R.id.action_component_disable) {
|
||||
locationComponent.setLocationComponentEnabled(false);
|
||||
return true;
|
||||
} else if (id == R.id.action_component_enabled) {
|
||||
locationComponent.setLocationComponentEnabled(true);
|
||||
return true;
|
||||
} else if (id == R.id.action_gestures_management_disabled) {
|
||||
disableGesturesManagement();
|
||||
return true;
|
||||
} else if (id == R.id.action_gestures_management_enabled) {
|
||||
enableGesturesManagement();
|
||||
return true;
|
||||
} else if (id == R.id.action_component_throttling_enabled) {
|
||||
locationComponent.setMaxAnimationFps(5);
|
||||
} else if (id == R.id.action_component_throttling_disabled) {
|
||||
locationComponent.setMaxAnimationFps(Integer.MAX_VALUE);
|
||||
} else if (id == R.id.action_component_animate_while_tracking) {
|
||||
locationComponent.zoomWhileTracking(17, 750, new MapboxMap.CancelableCallback() {
|
||||
@Override
|
||||
public void onCancel() {
|
||||
// No impl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
locationComponent.tiltWhileTracking(60);
|
||||
}
|
||||
});
|
||||
if (locationComponent.getCameraMode() == CameraMode.NONE) {
|
||||
|
||||
Toast.makeText(this, "Not possible to animate - not tracking", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void toggleStyle() {
|
||||
if (locationComponent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
defaultStyle = !defaultStyle;
|
||||
LocationComponentOptions options = LocationComponentOptions.createFromAttributes(
|
||||
this, defaultStyle ? R.style.mapbox_LocationComponent : R.style.CustomLocationComponent);
|
||||
|
||||
if (defaultStyle) {
|
||||
int[] padding;
|
||||
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||
padding = new int[] {0, 750, 0, 0};
|
||||
} else {
|
||||
padding = new int[] {0, 250, 0, 0};
|
||||
}
|
||||
|
||||
options = options.toBuilder()
|
||||
.padding(padding)
|
||||
.build();
|
||||
}
|
||||
|
||||
locationComponent.applyStyle(options);
|
||||
}
|
||||
|
||||
private void toggleMapStyle() {
|
||||
if (locationComponent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String styleUrl = Style.DARK.equals(mapboxMap.getStyle().getUri()) ? Style.LIGHT : Style.DARK;
|
||||
mapboxMap.setStyle(new Style.Builder().fromUri(styleUrl));
|
||||
}
|
||||
|
||||
private void disableGesturesManagement() {
|
||||
if (locationComponent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
LocationComponentOptions options = locationComponent
|
||||
.getLocationComponentOptions()
|
||||
.toBuilder()
|
||||
.trackingGesturesManagement(false)
|
||||
.build();
|
||||
locationComponent.applyStyle(options);
|
||||
}
|
||||
|
||||
private void enableGesturesManagement() {
|
||||
if (locationComponent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
LocationComponentOptions options = locationComponent
|
||||
.getLocationComponentOptions()
|
||||
.toBuilder()
|
||||
.trackingGesturesManagement(true)
|
||||
.build();
|
||||
locationComponent.applyStyle(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
outState.putInt(SAVED_STATE_CAMERA, cameraMode);
|
||||
outState.putInt(SAVED_STATE_RENDER, renderMode);
|
||||
if (locationComponent != null) {
|
||||
outState.putParcelable(SAVED_STATE_LOCATION, locationComponent.getLastKnownLocation());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationComponentClick() {
|
||||
Toast.makeText(this, "OnLocationComponentClick", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
private void showModeListDialog() {
|
||||
List<String> modes = new ArrayList<>();
|
||||
modes.add("Normal");
|
||||
modes.add("Compass");
|
||||
modes.add("GPS");
|
||||
ArrayAdapter<String> profileAdapter = new ArrayAdapter<>(this,
|
||||
android.R.layout.simple_list_item_1, modes);
|
||||
ListPopupWindow listPopup = new ListPopupWindow(this);
|
||||
listPopup.setAdapter(profileAdapter);
|
||||
listPopup.setAnchorView(locationModeBtn);
|
||||
listPopup.setOnItemClickListener((parent, itemView, position, id) -> {
|
||||
String selectedMode = modes.get(position);
|
||||
locationModeBtn.setText(selectedMode);
|
||||
if (selectedMode.contentEquals("Normal")) {
|
||||
setRendererMode(RenderMode.NORMAL);
|
||||
} else if (selectedMode.contentEquals("Compass")) {
|
||||
setRendererMode(RenderMode.COMPASS);
|
||||
} else if (selectedMode.contentEquals("GPS")) {
|
||||
setRendererMode(RenderMode.GPS);
|
||||
}
|
||||
listPopup.dismiss();
|
||||
});
|
||||
listPopup.show();
|
||||
}
|
||||
|
||||
private void setRendererMode(@RenderMode.Mode int mode) {
|
||||
renderMode = mode;
|
||||
locationComponent.setRenderMode(mode);
|
||||
if (mode == RenderMode.NORMAL) {
|
||||
locationModeBtn.setText("Normal");
|
||||
} else if (mode == RenderMode.COMPASS) {
|
||||
locationModeBtn.setText("Compass");
|
||||
} else if (mode == RenderMode.GPS) {
|
||||
locationModeBtn.setText("Gps");
|
||||
}
|
||||
}
|
||||
|
||||
private void showTrackingListDialog() {
|
||||
List<String> trackingTypes = new ArrayList<>();
|
||||
trackingTypes.add("None");
|
||||
trackingTypes.add("None Compass");
|
||||
trackingTypes.add("None GPS");
|
||||
trackingTypes.add("Tracking");
|
||||
trackingTypes.add("Tracking Compass");
|
||||
trackingTypes.add("Tracking GPS");
|
||||
trackingTypes.add("Tracking GPS North");
|
||||
ArrayAdapter<String> profileAdapter = new ArrayAdapter<>(this,
|
||||
android.R.layout.simple_list_item_1, trackingTypes);
|
||||
ListPopupWindow listPopup = new ListPopupWindow(this);
|
||||
listPopup.setAdapter(profileAdapter);
|
||||
listPopup.setAnchorView(locationTrackingBtn);
|
||||
listPopup.setOnItemClickListener((parent, itemView, position, id) -> {
|
||||
String selectedTrackingType = trackingTypes.get(position);
|
||||
locationTrackingBtn.setText(selectedTrackingType);
|
||||
if (selectedTrackingType.contentEquals("None")) {
|
||||
setCameraTrackingMode(CameraMode.NONE);
|
||||
} else if (selectedTrackingType.contentEquals("None Compass")) {
|
||||
setCameraTrackingMode(CameraMode.NONE_COMPASS);
|
||||
} else if (selectedTrackingType.contentEquals("None GPS")) {
|
||||
setCameraTrackingMode(CameraMode.NONE_GPS);
|
||||
} else if (selectedTrackingType.contentEquals("Tracking")) {
|
||||
setCameraTrackingMode(CameraMode.TRACKING);
|
||||
} else if (selectedTrackingType.contentEquals("Tracking Compass")) {
|
||||
setCameraTrackingMode(CameraMode.TRACKING_COMPASS);
|
||||
} else if (selectedTrackingType.contentEquals("Tracking GPS")) {
|
||||
setCameraTrackingMode(CameraMode.TRACKING_GPS);
|
||||
} else if (selectedTrackingType.contentEquals("Tracking GPS North")) {
|
||||
setCameraTrackingMode(CameraMode.TRACKING_GPS_NORTH);
|
||||
}
|
||||
listPopup.dismiss();
|
||||
});
|
||||
listPopup.show();
|
||||
}
|
||||
|
||||
private void setCameraTrackingMode(@CameraMode.Mode int mode) {
|
||||
locationComponent.setCameraMode(mode, 1200, 16.0, null, 45.0,
|
||||
new OnLocationCameraTransitionListener() {
|
||||
@Override
|
||||
public void onLocationCameraTransitionFinished(@CameraMode.Mode int cameraMode) {
|
||||
Toast.makeText(LocationModesActivity.this, "Transition finished", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationCameraTransitionCanceled(@CameraMode.Mode int cameraMode) {
|
||||
Toast.makeText(LocationModesActivity.this, "Transition canceled", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCameraTrackingDismissed() {
|
||||
locationTrackingBtn.setText("None");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCameraTrackingChanged(int currentMode) {
|
||||
this.cameraMode = currentMode;
|
||||
if (currentMode == CameraMode.NONE) {
|
||||
locationTrackingBtn.setText("None");
|
||||
} else if (currentMode == CameraMode.NONE_COMPASS) {
|
||||
locationTrackingBtn.setText("None Compass");
|
||||
} else if (currentMode == CameraMode.NONE_GPS) {
|
||||
locationTrackingBtn.setText("None GPS");
|
||||
} else if (currentMode == CameraMode.TRACKING) {
|
||||
locationTrackingBtn.setText("Tracking");
|
||||
} else if (currentMode == CameraMode.TRACKING_COMPASS) {
|
||||
locationTrackingBtn.setText("Tracking Compass");
|
||||
} else if (currentMode == CameraMode.TRACKING_GPS) {
|
||||
locationTrackingBtn.setText("Tracking GPS");
|
||||
} else if (currentMode == CameraMode.TRACKING_GPS_NORTH) {
|
||||
locationTrackingBtn.setText("Tracking GPS North");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.location;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.mapbox.android.core.location.LocationEngine;
|
||||
import com.mapbox.android.core.location.LocationEngineProvider;
|
||||
import com.mapbox.android.core.location.LocationEngineRequest;
|
||||
import com.mapbox.android.core.permissions.PermissionsListener;
|
||||
import com.mapbox.android.core.permissions.PermissionsManager;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
|
||||
import com.mapbox.mapboxsdk.location.LocationComponent;
|
||||
import com.mapbox.mapboxsdk.location.LocationComponentActivationOptions;
|
||||
import com.mapbox.mapboxsdk.location.modes.RenderMode;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ManualLocationUpdatesActivity extends AppCompatActivity implements OnMapReadyCallback {
|
||||
|
||||
private MapView mapView;
|
||||
private LocationComponent locationComponent;
|
||||
private LocationEngine locationEngine;
|
||||
private PermissionsManager permissionsManager;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_location_manual_update);
|
||||
|
||||
locationEngine = LocationEngineProvider.getBestLocationEngine(this, false);
|
||||
|
||||
FloatingActionButton fabManualUpdate = findViewById(R.id.fabManualLocationChange);
|
||||
fabManualUpdate.setOnClickListener(v -> {
|
||||
if (locationComponent != null && locationComponent.getLocationEngine() == null) {
|
||||
locationComponent.forceLocationUpdate(
|
||||
Utils.getRandomLocation(LatLngBounds.from(60, 25, 40, -5)));
|
||||
}
|
||||
});
|
||||
fabManualUpdate.setEnabled(false);
|
||||
|
||||
FloatingActionButton fabToggle = findViewById(R.id.fabToggleManualLocation);
|
||||
fabToggle.setOnClickListener(v -> {
|
||||
if (locationComponent != null) {
|
||||
locationComponent.setLocationEngine(locationComponent.getLocationEngine() == null ? locationEngine : null);
|
||||
|
||||
if (locationComponent.getLocationEngine() == null) {
|
||||
fabToggle.setImageResource(R.drawable.ic_layers_clear);
|
||||
fabManualUpdate.setEnabled(true);
|
||||
fabManualUpdate.setAlpha(1f);
|
||||
Toast.makeText(
|
||||
ManualLocationUpdatesActivity.this.getApplicationContext(),
|
||||
"LocationEngine disabled, use manual updates",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
fabToggle.setImageResource(R.drawable.ic_layers);
|
||||
fabManualUpdate.setEnabled(false);
|
||||
fabManualUpdate.setAlpha(0.5f);
|
||||
Toast.makeText(
|
||||
ManualLocationUpdatesActivity.this.getApplicationContext(),
|
||||
"LocationEngine enabled",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
|
||||
if (PermissionsManager.areLocationPermissionsGranted(this)) {
|
||||
mapView.getMapAsync(this);
|
||||
} else {
|
||||
permissionsManager = new PermissionsManager(new PermissionsListener() {
|
||||
@Override
|
||||
public void onExplanationNeeded(List<String> permissionsToExplain) {
|
||||
Toast.makeText(ManualLocationUpdatesActivity.this.getApplicationContext(),
|
||||
"You need to accept location permissions.",
|
||||
Toast.LENGTH_SHORT
|
||||
).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionResult(boolean granted) {
|
||||
if (granted) {
|
||||
mapView.getMapAsync(ManualLocationUpdatesActivity.this);
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
permissionsManager.requestLocationPermissions(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@Override
|
||||
public void onMapReady(@NonNull MapboxMap mapboxMap) {
|
||||
mapboxMap.setStyle(new Style.Builder().fromUri(Style.MAPBOX_STREETS), style -> {
|
||||
locationComponent = mapboxMap.getLocationComponent();
|
||||
|
||||
locationComponent.activateLocationComponent(
|
||||
LocationComponentActivationOptions
|
||||
.builder(this, style)
|
||||
.locationEngine(locationEngine)
|
||||
.locationEngineRequest(new LocationEngineRequest.Builder(500)
|
||||
.setFastestInterval(500)
|
||||
.setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY).build())
|
||||
.build());
|
||||
|
||||
locationComponent.setLocationComponentEnabled(true);
|
||||
locationComponent.setRenderMode(RenderMode.COMPASS);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.location;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Useful utilities used throughout the testapp.
|
||||
*/
|
||||
public class Utils {
|
||||
|
||||
private static final String[] STYLES = new String[] {
|
||||
Style.MAPBOX_STREETS,
|
||||
Style.OUTDOORS,
|
||||
Style.LIGHT,
|
||||
Style.DARK,
|
||||
Style.SATELLITE_STREETS
|
||||
};
|
||||
|
||||
private static int index;
|
||||
|
||||
/**
|
||||
* Utility to cycle through map styles. Useful to test if runtime styling source and layers transfer over to new
|
||||
* style.
|
||||
*
|
||||
* @return a string ID representing the map style
|
||||
*/
|
||||
public static String getNextStyle() {
|
||||
index++;
|
||||
if (index == STYLES.length) {
|
||||
index = 0;
|
||||
}
|
||||
return STYLES[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility for getting a random coordinate inside a provided bounds and creates a {@link Location} from it.
|
||||
*
|
||||
* @param bounds bounds of the generated location
|
||||
* @return a {@link Location} object using the random coordinate
|
||||
*/
|
||||
public static Location getRandomLocation(LatLngBounds bounds) {
|
||||
Random random = new Random();
|
||||
|
||||
double randomLat = bounds.getLatSouth() + (bounds.getLatNorth() - bounds.getLatSouth()) * random.nextDouble();
|
||||
double randomLon = bounds.getLonWest() + (bounds.getLonEast() - bounds.getLonWest()) * random.nextDouble();
|
||||
|
||||
Location location = new Location("random-loc");
|
||||
location.setLongitude(randomLon);
|
||||
location.setLatitude(randomLat);
|
||||
Timber.d("getRandomLatLng: %s", location.toString());
|
||||
return location;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.maplayout;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.BottomSheetBehavior;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.utils.MapFragmentUtils;
|
||||
|
||||
/**
|
||||
* Test activity showcasing using a bottomView with a MapView and stacking map fragments below.
|
||||
*/
|
||||
public class BottomSheetActivity extends AppCompatActivity {
|
||||
|
||||
private static final String TAG_MAIN_FRAGMENT = "com.mapbox.mapboxsdk.fragment.tag.main";
|
||||
private static final String TAG_BOTTOM_FRAGMENT = "com.mapbox.mapboxsdk.fragment.tag.bottom";
|
||||
private static final String AMOUNT_OF_MAIN_MAP_FRAGMENTS = "Amount of main map fragments: %s";
|
||||
private boolean bottomSheetFragmentAdded;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_bottom_sheet);
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
findViewById(R.id.fabFragment).setOnClickListener(v -> addMapFragment());
|
||||
|
||||
findViewById(R.id.fabBottomSheet).setOnClickListener(v -> toggleBottomSheetMapFragment());
|
||||
|
||||
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.bottom_sheet));
|
||||
bottomSheetBehavior.setPeekHeight((int) (64 * getResources().getDisplayMetrics().density));
|
||||
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
||||
toggleBottomSheetMapFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
onBackPressed();
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
|
||||
if (fragmentManager.getBackStackEntryCount() > 0) {
|
||||
fragmentManager.popBackStack();
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
private void addMapFragment() {
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
int fragmentCount = fragmentManager.getBackStackEntryCount();
|
||||
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
MainMapFragment mainMapFragment = MainMapFragment.newInstance(this, fragmentCount);
|
||||
if (fragmentCount == 0) {
|
||||
fragmentTransaction.add(R.id.fragment_container, mainMapFragment, TAG_MAIN_FRAGMENT);
|
||||
} else {
|
||||
fragmentTransaction.replace(R.id.fragment_container, mainMapFragment, TAG_MAIN_FRAGMENT);
|
||||
}
|
||||
fragmentTransaction.addToBackStack(String.valueOf(mainMapFragment.hashCode()));
|
||||
fragmentTransaction.commit();
|
||||
Toast.makeText(getApplicationContext(),
|
||||
String.format(AMOUNT_OF_MAIN_MAP_FRAGMENTS, (fragmentCount + 1)),
|
||||
Toast.LENGTH_SHORT
|
||||
).show();
|
||||
}
|
||||
|
||||
private void toggleBottomSheetMapFragment() {
|
||||
if (!bottomSheetFragmentAdded) {
|
||||
addBottomSheetMapFragment();
|
||||
} else {
|
||||
removeBottomSheetFragment();
|
||||
}
|
||||
bottomSheetFragmentAdded = !bottomSheetFragmentAdded;
|
||||
}
|
||||
|
||||
private void addBottomSheetMapFragment() {
|
||||
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
|
||||
fragmentTransaction.add(R.id.fragment_container_bottom, BottomSheetFragment.newInstance(this), TAG_BOTTOM_FRAGMENT);
|
||||
fragmentTransaction.commit();
|
||||
}
|
||||
|
||||
private void removeBottomSheetFragment() {
|
||||
Fragment fragment = getSupportFragmentManager().findFragmentByTag(TAG_BOTTOM_FRAGMENT);
|
||||
if (fragment != null) {
|
||||
getSupportFragmentManager().beginTransaction().remove(fragment).commit();
|
||||
}
|
||||
}
|
||||
|
||||
public static class MainMapFragment extends Fragment implements OnMapReadyCallback {
|
||||
|
||||
private static final String[] STYLES = new String[] {
|
||||
Style.MAPBOX_STREETS,
|
||||
Style.SATELLITE_STREETS,
|
||||
Style.LIGHT,
|
||||
Style.DARK,
|
||||
Style.SATELLITE,
|
||||
Style.OUTDOORS
|
||||
};
|
||||
|
||||
private MapView map;
|
||||
|
||||
public static MainMapFragment newInstance(Context context, int mapCounter) {
|
||||
MainMapFragment mapFragment = new MainMapFragment();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt("mapcounter", mapCounter);
|
||||
mapFragment.setArguments(bundle);
|
||||
MapboxMapOptions mapboxMapOptions = MapboxMapOptions.createFromAttributes(context);
|
||||
mapFragment.setArguments(MapFragmentUtils.createFragmentArgs(mapboxMapOptions));
|
||||
return mapFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
Context context = inflater.getContext();
|
||||
return map = new MapView(context, MapFragmentUtils.resolveArgs(context, getArguments()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
map.onCreate(savedInstanceState);
|
||||
map.getMapAsync(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull MapboxMap mapboxMap) {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(37.760545, -122.436055), 15));
|
||||
mapboxMap.setStyle(
|
||||
new Style.Builder().fromUri(
|
||||
STYLES[Math.min(Math.max(getArguments().getInt("mapcounter"), 0), STYLES.length - 1)]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
map.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
map.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
map.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
map.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
map.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
map.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
map.onDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
public static class BottomSheetFragment extends Fragment implements OnMapReadyCallback {
|
||||
|
||||
private MapView map;
|
||||
|
||||
public static BottomSheetFragment newInstance(Context context) {
|
||||
BottomSheetFragment mapFragment = new BottomSheetFragment();
|
||||
MapboxMapOptions mapboxMapOptions = MapboxMapOptions.createFromAttributes(context);
|
||||
mapboxMapOptions.renderSurfaceOnTop(true);
|
||||
mapFragment.setArguments(MapFragmentUtils.createFragmentArgs(mapboxMapOptions));
|
||||
return mapFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
Context context = inflater.getContext();
|
||||
return map = new MapView(context, MapFragmentUtils.resolveArgs(context, getArguments()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
map.onCreate(savedInstanceState);
|
||||
map.getMapAsync(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull MapboxMap mapboxMap) {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(37.760545, -122.436055), 15));
|
||||
mapboxMap.setStyle(Style.LIGHT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
map.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
map.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
map.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
map.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
map.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
map.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
map.onDestroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.maplayout;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.ActionBarDrawerToggle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.style.layers.Layer;
|
||||
import com.mapbox.mapboxsdk.style.layers.Property;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
|
||||
|
||||
/**
|
||||
* Test activity showcasing the different debug modes and allows to cycle between the default map styles.
|
||||
*/
|
||||
public class DebugModeActivity extends AppCompatActivity implements OnMapReadyCallback, MapboxMap.OnFpsChangedListener {
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private MapboxMap.OnCameraMoveListener cameraMoveListener;
|
||||
private ActionBarDrawerToggle actionBarDrawerToggle;
|
||||
private int currentStyleIndex;
|
||||
private boolean isReportFps = true;
|
||||
|
||||
private static final String[] STYLES = new String[] {
|
||||
Style.MAPBOX_STREETS,
|
||||
Style.OUTDOORS,
|
||||
Style.LIGHT,
|
||||
Style.DARK,
|
||||
Style.SATELLITE,
|
||||
Style.SATELLITE_STREETS,
|
||||
Style.TRAFFIC_DAY,
|
||||
Style.TRAFFIC_NIGHT
|
||||
};
|
||||
private TextView fpsView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_debug_mode);
|
||||
setupToolbar();
|
||||
setupMapView(savedInstanceState);
|
||||
setupDebugChangeView();
|
||||
setupStyleChangeView();
|
||||
}
|
||||
|
||||
private void setupToolbar() {
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
DrawerLayout drawerLayout = findViewById(R.id.drawer_layout);
|
||||
actionBarDrawerToggle = new ActionBarDrawerToggle(this,
|
||||
drawerLayout,
|
||||
R.string.navigation_drawer_open,
|
||||
R.string.navigation_drawer_close
|
||||
);
|
||||
actionBarDrawerToggle.setDrawerIndicatorEnabled(true);
|
||||
actionBarDrawerToggle.syncState();
|
||||
}
|
||||
}
|
||||
|
||||
private void setupMapView(Bundle savedInstanceState) {
|
||||
MapboxMapOptions mapboxMapOptions = setupMapboxMapOptions();
|
||||
mapView = new MapView(this, mapboxMapOptions);
|
||||
((ViewGroup) findViewById(R.id.coordinator_layout)).addView(mapView, 0);
|
||||
mapView.addOnDidFinishLoadingStyleListener(() -> {
|
||||
if (mapboxMap != null) {
|
||||
setupNavigationView(mapboxMap.getStyle().getLayers());
|
||||
}
|
||||
});
|
||||
|
||||
mapView.setTag(true);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(this);
|
||||
mapView.addOnDidFinishLoadingStyleListener(() -> Timber.d("Style loaded"));
|
||||
}
|
||||
|
||||
protected MapboxMapOptions setupMapboxMapOptions() {
|
||||
return MapboxMapOptions.createFromAttributes(this, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull MapboxMap map) {
|
||||
mapboxMap = map;
|
||||
mapboxMap.setStyle(
|
||||
new Style.Builder().fromUri(STYLES[currentStyleIndex]), style -> setupNavigationView(style.getLayers())
|
||||
);
|
||||
setupZoomView();
|
||||
setFpsView();
|
||||
}
|
||||
|
||||
private void setFpsView() {
|
||||
fpsView = findViewById(R.id.fpsView);
|
||||
mapboxMap.setOnFpsChangedListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFpsChanged(double fps) {
|
||||
fpsView.setText(String.format(Locale.US, "FPS: %4.2f", fps));
|
||||
}
|
||||
|
||||
private void setupNavigationView(List<Layer> layerList) {
|
||||
Timber.v("New style loaded with JSON: %s", mapboxMap.getStyle().getJson());
|
||||
final LayerListAdapter adapter = new LayerListAdapter(this, layerList);
|
||||
ListView listView = findViewById(R.id.listView);
|
||||
listView.setAdapter(adapter);
|
||||
listView.setOnItemClickListener((parent, view, position, id) -> {
|
||||
Layer clickedLayer = adapter.getItem(position);
|
||||
toggleLayerVisibility(clickedLayer);
|
||||
closeNavigationView();
|
||||
});
|
||||
}
|
||||
|
||||
private void toggleLayerVisibility(Layer layer) {
|
||||
boolean isVisible = layer.getVisibility().getValue().equals(Property.VISIBLE);
|
||||
layer.setProperties(
|
||||
visibility(
|
||||
isVisible ? Property.NONE : Property.VISIBLE
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void closeNavigationView() {
|
||||
DrawerLayout drawerLayout = findViewById(R.id.drawer_layout);
|
||||
drawerLayout.closeDrawers();
|
||||
}
|
||||
|
||||
private void setupZoomView() {
|
||||
final TextView textView = findViewById(R.id.textZoom);
|
||||
mapboxMap.addOnCameraMoveListener(cameraMoveListener = new MapboxMap.OnCameraMoveListener() {
|
||||
@Override
|
||||
public void onCameraMove() {
|
||||
textView.setText(String.format(DebugModeActivity.this.getString(
|
||||
R.string.debug_zoom), mapboxMap.getCameraPosition().zoom));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupDebugChangeView() {
|
||||
FloatingActionButton fabDebug = findViewById(R.id.fabDebug);
|
||||
fabDebug.setOnClickListener(view -> {
|
||||
if (mapboxMap != null) {
|
||||
Timber.d("Debug FAB: isDebug Active? %s", mapboxMap.isDebugActive());
|
||||
mapboxMap.cycleDebugOptions();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupStyleChangeView() {
|
||||
FloatingActionButton fabStyles = findViewById(R.id.fabStyles);
|
||||
fabStyles.setOnClickListener(view -> {
|
||||
if (mapboxMap != null) {
|
||||
currentStyleIndex++;
|
||||
if (currentStyleIndex == STYLES.length) {
|
||||
currentStyleIndex = 0;
|
||||
}
|
||||
mapboxMap.setStyle(new Style.Builder().fromUri(STYLES[currentStyleIndex]));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int itemId = item.getItemId();
|
||||
if (itemId == R.id.menu_action_toggle_report_fps) {
|
||||
isReportFps = !isReportFps;
|
||||
fpsView.setVisibility(isReportFps ? View.VISIBLE : View.GONE);
|
||||
mapboxMap.setOnFpsChangedListener(isReportFps ? this : null);
|
||||
} else if (itemId == R.id.menu_action_limit_to_30_fps) {
|
||||
mapView.setMaximumFps(30);
|
||||
} else if (itemId == R.id.menu_action_limit_to_60_fps) {
|
||||
mapView.setMaximumFps(60);
|
||||
}
|
||||
|
||||
return actionBarDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_debug, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mapboxMap != null) {
|
||||
mapboxMap.removeOnCameraMoveListener(cameraMoveListener);
|
||||
}
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
private static class LayerListAdapter extends BaseAdapter {
|
||||
|
||||
private LayoutInflater layoutInflater;
|
||||
private List<Layer> layers;
|
||||
|
||||
LayerListAdapter(Context context, List<Layer> layers) {
|
||||
this.layoutInflater = LayoutInflater.from(context);
|
||||
this.layers = layers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return layers.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Layer getItem(int position) {
|
||||
return layers.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
Layer layer = layers.get(position);
|
||||
View view = convertView;
|
||||
if (view == null) {
|
||||
view = layoutInflater.inflate(android.R.layout.simple_list_item_2, parent, false);
|
||||
ViewHolder holder = new ViewHolder(
|
||||
view.findViewById(android.R.id.text1),
|
||||
view.findViewById(android.R.id.text2)
|
||||
);
|
||||
view.setTag(holder);
|
||||
}
|
||||
ViewHolder holder = (ViewHolder) view.getTag();
|
||||
holder.text.setText(layer.getClass().getSimpleName());
|
||||
holder.subText.setText(layer.getId());
|
||||
return view;
|
||||
}
|
||||
|
||||
private static class ViewHolder {
|
||||
final TextView text;
|
||||
final TextView subText;
|
||||
|
||||
ViewHolder(TextView text, TextView subText) {
|
||||
this.text = text;
|
||||
this.subText = subText;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.maplayout;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.maps.UiSettings;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.utils.MapFragmentUtils;
|
||||
|
||||
/**
|
||||
* Test activity showcasing having 2 maps on top of each other.
|
||||
* <p>
|
||||
* The small map is using the `mapbox_enableZMediaOverlay="true"` configuration
|
||||
* </p>
|
||||
*/
|
||||
public class DoubleMapActivity extends AppCompatActivity {
|
||||
|
||||
private static final String TAG_FRAGMENT = "map";
|
||||
private static final LatLng MACHU_PICCHU = new LatLng(-13.1650709, -72.5447154);
|
||||
private static final double ZOOM_IN = 12;
|
||||
private static final double ZOOM_OUT = 4;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_map_fragment);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
MapboxMapOptions options = MapboxMapOptions.createFromAttributes(this, null);
|
||||
options.camera(new CameraPosition.Builder()
|
||||
.target(MACHU_PICCHU)
|
||||
.zoom(ZOOM_IN)
|
||||
.build()
|
||||
);
|
||||
|
||||
DoubleMapFragment doubleMapFragment = new DoubleMapFragment();
|
||||
doubleMapFragment.setArguments(MapFragmentUtils.createFragmentArgs(options));
|
||||
|
||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||
transaction.add(R.id.fragment_container, doubleMapFragment, TAG_FRAGMENT);
|
||||
transaction.commit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom fragment containing 2 MapViews.
|
||||
*/
|
||||
public static class DoubleMapFragment extends Fragment {
|
||||
|
||||
private MapView mapView;
|
||||
private MapView mapViewMini;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_double_map, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
// MapView large
|
||||
mapView = new MapView(view.getContext(), MapFragmentUtils.resolveArgs(view.getContext(), getArguments()));
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(mapboxMap -> mapboxMap.setStyle(Style.MAPBOX_STREETS));
|
||||
((ViewGroup) view.findViewById(R.id.container)).addView(mapView, 0);
|
||||
|
||||
// MapView mini
|
||||
mapViewMini = view.findViewById(R.id.mini_map);
|
||||
mapViewMini.onCreate(savedInstanceState);
|
||||
mapViewMini.getMapAsync(mapboxMap -> {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
|
||||
new CameraPosition.Builder().target(MACHU_PICCHU)
|
||||
.zoom(ZOOM_OUT)
|
||||
.build()
|
||||
)
|
||||
);
|
||||
mapboxMap.setStyle(new Style.Builder().fromUri(Style.LIGHT));
|
||||
|
||||
UiSettings uiSettings = mapboxMap.getUiSettings();
|
||||
uiSettings.setAllGesturesEnabled(false);
|
||||
uiSettings.setCompassEnabled(false);
|
||||
uiSettings.setAttributionEnabled(false);
|
||||
uiSettings.setLogoEnabled(false);
|
||||
|
||||
mapboxMap.addOnMapClickListener(point -> {
|
||||
// test if we can open 2 activities after each other
|
||||
Toast.makeText(mapViewMini.getContext(), "Creating a new Activity instance", Toast.LENGTH_SHORT).show();
|
||||
startActivity(new Intent(mapViewMini.getContext(), DoubleMapActivity.class));
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
mapViewMini.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
mapViewMini.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
mapViewMini.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
mapViewMini.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
mapView.onDestroy();
|
||||
mapViewMini.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
mapViewMini.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
// Mini map view is not interactive in this case, so we shouldn't save the instance.
|
||||
// If we'd like to support state saving for both maps, they'd have to be kept in separate fragments.
|
||||
//mapViewMini.onSaveInstanceState(outState);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.maplayout
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import com.mapbox.mapboxsdk.maps.MapView
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import kotlinx.android.synthetic.main.activity_recyclerview.*
|
||||
|
||||
/**
|
||||
* TestActivity showcasing how to integrate multiple GLSurfaceView MapViews in a RecyclerView.
|
||||
* <p>
|
||||
* It requires calling the correct lifecycle methods when detaching and attaching the View to
|
||||
* the RecyclerView with onViewAttachedToWindow and onViewDetachedFromWindow.
|
||||
* </p>
|
||||
*/
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
open class GLSurfaceRecyclerViewActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_recyclerview)
|
||||
recyclerView.layoutManager = LinearLayoutManager(this)
|
||||
recyclerView.adapter = ItemAdapter(this, LayoutInflater.from(this))
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
// to release memory, we need to call MapView#onLowMemory
|
||||
(recyclerView.adapter as ItemAdapter).onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
// to perform cleanup, we need to call MapView#onDestroy
|
||||
(recyclerView.adapter as ItemAdapter).onDestroy()
|
||||
}
|
||||
|
||||
open fun getMapItemLayoutId(): Int {
|
||||
return R.layout.item_map_gl
|
||||
}
|
||||
|
||||
class ItemAdapter(private val activity: GLSurfaceRecyclerViewActivity, private val inflater: LayoutInflater) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
private val items = listOf(
|
||||
"one", "two", "three", MapItem(Style.MAPBOX_STREETS), "four", "five", MapItem(Style.DARK), "seven", "eight", "nine", "ten",
|
||||
"eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen",
|
||||
"nineteen", "twenty", "twenty-one"
|
||||
)
|
||||
|
||||
private var mapHolders: MutableList<MapHolder> = mutableListOf()
|
||||
|
||||
companion object {
|
||||
const val TYPE_MAP = 0
|
||||
const val TYPE_TEXT = 1
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return if (viewType == TYPE_MAP) {
|
||||
val mapView = inflater.inflate(activity.getMapItemLayoutId(), parent, false) as MapView
|
||||
val mapHolder = MapHolder(mapView)
|
||||
mapHolders.add(mapHolder)
|
||||
return mapHolder
|
||||
} else {
|
||||
TextHolder(inflater.inflate(android.R.layout.simple_list_item_1, parent, false) as TextView)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
|
||||
super.onViewAttachedToWindow(holder)
|
||||
if (holder is MapHolder) {
|
||||
val mapView = holder.mapView
|
||||
mapView.onStart()
|
||||
mapView.onResume()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
|
||||
super.onViewDetachedFromWindow(holder)
|
||||
if (holder is MapHolder) {
|
||||
val mapView = holder.mapView
|
||||
mapView.onPause()
|
||||
mapView.onStop()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return items.count()
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is TextHolder) {
|
||||
holder.bind(items[position] as String)
|
||||
} else if (holder is MapHolder) {
|
||||
holder.bind(items[position] as MapItem)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (items[position] is MapItem) {
|
||||
TYPE_MAP
|
||||
} else {
|
||||
TYPE_TEXT
|
||||
}
|
||||
}
|
||||
|
||||
fun onLowMemory() {
|
||||
for (mapHolder in mapHolders) {
|
||||
mapHolder.mapView.onLowMemory()
|
||||
}
|
||||
}
|
||||
|
||||
fun onDestroy() {
|
||||
for (mapHolder in mapHolders) {
|
||||
mapHolder.mapView.let {
|
||||
it.onPause()
|
||||
it.onStop()
|
||||
it.onDestroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class MapItem(val style: String)
|
||||
class MapHolder(val mapView: MapView) : RecyclerView.ViewHolder(mapView) {
|
||||
|
||||
init {
|
||||
// unfortunately, if there are multiple maps hosted in one activity, state saving is not possible
|
||||
mapView.onCreate(null)
|
||||
mapView.setOnTouchListener { view, motionEvent ->
|
||||
// Disallow the touch request for recyclerView scroll
|
||||
view.parent.requestDisallowInterceptTouchEvent(true)
|
||||
mapView.onTouchEvent(motionEvent)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fun bind(mapItem: MapItem) {
|
||||
mapView.getMapAsync { mapboxMap -> mapboxMap.setStyle(mapItem.style) }
|
||||
}
|
||||
}
|
||||
|
||||
class TextHolder(val textView: TextView) : RecyclerView.ViewHolder(textView) {
|
||||
fun bind(item: String) {
|
||||
textView.text = item
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.maplayout;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Gravity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import com.mapbox.mapboxsdk.annotations.PolygonOptions;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
/**
|
||||
* Test activity showcasing restricting user gestures to a bounds around Iceland, almost worldview and IDL.
|
||||
*/
|
||||
public class LatLngBoundsForCameraActivity extends AppCompatActivity implements OnMapReadyCallback {
|
||||
|
||||
private static final LatLngBounds ICELAND_BOUNDS = new LatLngBounds.Builder()
|
||||
.include(new LatLng(66.852863, -25.985652))
|
||||
.include(new LatLng(62.985661, -12.626277))
|
||||
.build();
|
||||
|
||||
private static final LatLngBounds ALMOST_WORLD_BOUNDS = new LatLngBounds.Builder()
|
||||
.include(new LatLng(20.0, 170.0))
|
||||
.include(new LatLng(-20, -170.0))
|
||||
.build();
|
||||
|
||||
private static final LatLngBounds CROSS_IDL_BOUNDS = new LatLngBounds.Builder()
|
||||
.include(new LatLng(20.0, 170.0))
|
||||
.include(new LatLng(-20, 190.0))
|
||||
.build();
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_restricted_bounds);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull MapboxMap mapboxMap) {
|
||||
this.mapboxMap = mapboxMap;
|
||||
mapboxMap.setStyle(Style.SATELLITE_STREETS);
|
||||
mapboxMap.setMinZoomPreference(2);
|
||||
mapboxMap.getUiSettings().setFlingVelocityAnimationEnabled(false);
|
||||
showCrosshair();
|
||||
setupBounds(ICELAND_BOUNDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_bounds, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_action_allmost_world_bounds:
|
||||
setupBounds(ALMOST_WORLD_BOUNDS);
|
||||
return true;
|
||||
case R.id.menu_action_cross_idl:
|
||||
setupBounds(CROSS_IDL_BOUNDS);
|
||||
return true;
|
||||
case R.id.menu_action_reset:
|
||||
setupBounds(null);
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void setupBounds(@Nullable LatLngBounds bounds) {
|
||||
mapboxMap.setLatLngBoundsForCameraTarget(bounds);
|
||||
showBoundsArea(bounds);
|
||||
}
|
||||
|
||||
private void showBoundsArea(@Nullable LatLngBounds bounds) {
|
||||
mapboxMap.clear();
|
||||
if (bounds != null) {
|
||||
PolygonOptions boundsArea = new PolygonOptions()
|
||||
.add(bounds.getNorthWest())
|
||||
.add(bounds.getNorthEast())
|
||||
.add(bounds.getSouthEast())
|
||||
.add(bounds.getSouthWest());
|
||||
boundsArea.alpha(0.25f);
|
||||
boundsArea.fillColor(Color.RED);
|
||||
mapboxMap.addPolygon(boundsArea);
|
||||
}
|
||||
}
|
||||
|
||||
private void showCrosshair() {
|
||||
View crosshair = new View(this);
|
||||
crosshair.setLayoutParams(new FrameLayout.LayoutParams(10, 10, Gravity.CENTER));
|
||||
crosshair.setBackgroundColor(Color.BLUE);
|
||||
mapView.addView(crosshair);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.maplayout;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
/**
|
||||
* Test activity that displays the city of Suzhou with a mixture of server-generated
|
||||
* latin glyphs and CJK glyphs generated locally using "Droid Sans" as a font family.
|
||||
*/
|
||||
public class LocalGlyphActivity extends AppCompatActivity {
|
||||
private MapView mapView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_local_glyph);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(mapboxMap -> {
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS);
|
||||
// Set initial position to Suzhou
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
|
||||
new CameraPosition.Builder()
|
||||
.target(new LatLng(31.3003, 120.7457))
|
||||
.zoom(11)
|
||||
.bearing(0)
|
||||
.tilt(0)
|
||||
.build()));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.maplayout;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Test activity showcasing how to listen to map change events.
|
||||
*/
|
||||
public class MapChangeActivity extends AppCompatActivity {
|
||||
|
||||
private MapView mapView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_map_simple);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.addOnCameraIsChangingListener(() -> Timber.v("OnCameraIsChanging"));
|
||||
mapView.addOnCameraDidChangeListener(animated -> Timber.v("OnCamaraDidChange: animated: %s", animated));
|
||||
mapView.addOnCameraWillChangeListener(animated -> Timber.v("OnCameraWilChange: animated: %s", animated));
|
||||
mapView.addOnDidFailLoadingMapListener(errorMessage -> Timber.v("OnDidFailLoadingMap: %s", errorMessage));
|
||||
mapView.addOnDidFinishLoadingMapListener(() -> Timber.v("OnDidFinishLoadingMap"));
|
||||
mapView.addOnDidFinishLoadingStyleListener(() -> Timber.v("OnDidFinishLoadingStyle"));
|
||||
mapView.addOnDidFinishRenderingFrameListener(fully -> Timber.v("OnDidFinishRenderingFrame: fully: %s", fully));
|
||||
mapView.addOnDidFinishRenderingMapListener(fully -> Timber.v("OnDidFinishRenderingMap: fully: %s", fully));
|
||||
mapView.addOnDidBecomeIdleListener(() -> Timber.v("OnDidBecomeIdle"));
|
||||
mapView.addOnSourceChangedListener(sourceId -> Timber.v("OnSourceChangedListener: source with id: %s", sourceId));
|
||||
mapView.addOnWillStartLoadingMapListener(() -> Timber.v("OnWillStartLoadingMap"));
|
||||
mapView.addOnWillStartRenderingFrameListener(() -> Timber.v("OnWillStartRenderingFrame"));
|
||||
mapView.addOnWillStartRenderingMapListener(() -> Timber.v("OnWillStartRenderingMap"));
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(mapboxMap -> {
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS);
|
||||
mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
|
||||
new LatLng(55.754020, 37.620948), 12), 9000);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.maplayout;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
/**
|
||||
* Test activity showcasing showing a Map inside of a DialogFragment.
|
||||
*/
|
||||
public class MapInDialogActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_map_in_dialog);
|
||||
|
||||
Button button = findViewById(R.id.button_open_dialog);
|
||||
button.setOnClickListener(view -> {
|
||||
FragmentManager fm = getSupportFragmentManager();
|
||||
MapDialogFragment editNameDialogFragment = MapDialogFragment.newInstance("Map Dialog");
|
||||
editNameDialogFragment.show(fm, "fragment_dialog_map");
|
||||
});
|
||||
}
|
||||
|
||||
public static class MapDialogFragment extends DialogFragment {
|
||||
|
||||
private MapView mapView;
|
||||
|
||||
public MapDialogFragment() {
|
||||
}
|
||||
|
||||
public static MapDialogFragment newInstance(String title) {
|
||||
MapDialogFragment frag = new MapDialogFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString("title", title);
|
||||
frag.setArguments(args);
|
||||
return frag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_dialog_map, container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mapView = view.findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(mapboxMap -> mapboxMap.setStyle(Style.OUTDOORS));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
mapView.onDestroy();
|
||||
mapView = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
if (mapView != null) {
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (mapView != null) {
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.maplayout;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.maps.UiSettings;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
/**
|
||||
* Test activity showcasing using the map padding API.
|
||||
*/
|
||||
public class MapPaddingActivity extends AppCompatActivity {
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_map_padding);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.setTag(true);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
|
||||
mapView.getMapAsync(mapboxMap -> {
|
||||
MapPaddingActivity.this.mapboxMap = mapboxMap;
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS);
|
||||
|
||||
int paddingLeft = (int) getResources().getDimension(R.dimen.map_padding_left);
|
||||
int paddingBottom = (int) getResources().getDimension(R.dimen.map_padding_bottom);
|
||||
int paddingRight = (int) getResources().getDimension(R.dimen.map_padding_right);
|
||||
int paddingTop = (int) getResources().getDimension(R.dimen.map_padding_top);
|
||||
mapboxMap.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
|
||||
|
||||
UiSettings settings = mapboxMap.getUiSettings();
|
||||
settings.setLogoMargins(paddingLeft, 0, 0, paddingBottom);
|
||||
settings.setCompassMargins(0, paddingTop, paddingRight, 0);
|
||||
settings.setAttributionEnabled(false);
|
||||
|
||||
moveToBangalore();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_padding, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void moveToBangalore() {
|
||||
LatLng bangalore = new LatLng(12.9810816, 77.6368034);
|
||||
CameraPosition cameraPosition = new CameraPosition.Builder()
|
||||
.zoom(16)
|
||||
.target(bangalore)
|
||||
.bearing(40)
|
||||
.tilt(45)
|
||||
.build();
|
||||
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
|
||||
mapboxMap.addMarker(new MarkerOptions().title("Center map").position(bangalore));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
|
||||
case R.id.action_bangalore:
|
||||
if (mapboxMap != null) {
|
||||
moveToBangalore();
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.maplayout
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.graphics.*
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.view.View
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import kotlinx.android.synthetic.main.activity_overlay.*
|
||||
|
||||
/**
|
||||
* Test overlaying a Map with a View that uses a radial gradient shader.
|
||||
*/
|
||||
class OverlayMapActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_overlay)
|
||||
mapView.onCreate(savedInstanceState)
|
||||
parentView.addView(OverlayView(this))
|
||||
mapView.getMapAsync {
|
||||
it.setStyle(Style.MAPBOX_STREETS)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle?) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState?.let {
|
||||
mapView.onSaveInstanceState(it)
|
||||
}
|
||||
}
|
||||
|
||||
class OverlayView(context: Context) : View(context) {
|
||||
|
||||
private lateinit var paint: Paint
|
||||
|
||||
@SuppressLint("DrawAllocation") // only happens once
|
||||
override fun onDraw(canvas: Canvas?) {
|
||||
super.onDraw(canvas)
|
||||
|
||||
canvas?.let {
|
||||
if (!::paint.isInitialized) {
|
||||
paint = Paint()
|
||||
paint.color = Color.BLACK
|
||||
paint.strokeWidth = 1.0f
|
||||
paint.style = Paint.Style.FILL_AND_STROKE
|
||||
paint.shader = RadialGradient(width / 2.0f, height / 2.0f,
|
||||
height / 3.0f, Color.TRANSPARENT, Color.BLACK, Shader.TileMode.CLAMP)
|
||||
}
|
||||
it.drawRect(0.0f, 0.0f, width.toFloat(), height.toFloat(), paint)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.maplayout;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.MenuItem;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.NavUtils;
|
||||
|
||||
/**
|
||||
* Test activity showcasing a simple MapView without any MapboxMap interaction.
|
||||
*/
|
||||
public class SimpleMapActivity extends AppCompatActivity {
|
||||
|
||||
private MapView mapView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_map_simple);
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(mapboxMap -> mapboxMap.setStyle(
|
||||
new Style.Builder().fromUri(Style.MAPBOX_STREETS)
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
// activity uses singleInstance for testing purposes
|
||||
// code below provides a default navigation when using the app
|
||||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
// activity uses singleInstance for testing purposes
|
||||
// code below provides a default navigation when using the app
|
||||
NavUtils.navigateHome(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.maplayout
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
|
||||
/**
|
||||
* TestActivity showcasing how to integrate multiple TexureView MapViews in a RecyclerView.
|
||||
*/
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
class TextureRecyclerViewActivity : GLSurfaceRecyclerViewActivity() {
|
||||
|
||||
override fun getMapItemLayoutId(): Int {
|
||||
return R.layout.item_map_texture
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.maplayout;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
/**
|
||||
* Test activity showcasing visibility changes to the mapview.
|
||||
*/
|
||||
public class VisibilityChangeActivity extends AppCompatActivity {
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private Handler handler = new Handler();
|
||||
private Runnable runnable;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_map_visibility);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(map -> {
|
||||
mapboxMap = map;
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS);
|
||||
mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
|
||||
new LatLng(55.754020, 37.620948), 12), 9000);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
handler.post(runnable = new VisibilityRunner(mapView, findViewById(R.id.viewParent), handler));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
private static class VisibilityRunner implements Runnable {
|
||||
|
||||
private MapView mapView;
|
||||
private View viewParent;
|
||||
private Handler handler;
|
||||
private int currentStep;
|
||||
|
||||
VisibilityRunner(MapView mapView, View viewParent, Handler handler) {
|
||||
this.mapView = mapView;
|
||||
this.viewParent = viewParent;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (isViewHiearchyReady()) {
|
||||
if (isEvenStep()) {
|
||||
viewParent.setVisibility(View.VISIBLE);
|
||||
mapView.setVisibility(View.VISIBLE);
|
||||
} else if (isFirstOrThirdStep()) {
|
||||
mapView.setVisibility(getVisibilityForStep());
|
||||
} else if (isFifthOrSeventhStep()) {
|
||||
viewParent.setVisibility(getVisibilityForStep());
|
||||
}
|
||||
updateStep();
|
||||
}
|
||||
handler.postDelayed(this, 1500);
|
||||
}
|
||||
|
||||
private void updateStep() {
|
||||
if (currentStep == 7) {
|
||||
currentStep = 0;
|
||||
} else {
|
||||
currentStep++;
|
||||
}
|
||||
}
|
||||
|
||||
private int getVisibilityForStep() {
|
||||
return (currentStep == 1 || currentStep == 5) ? View.GONE : View.INVISIBLE;
|
||||
}
|
||||
|
||||
private boolean isFifthOrSeventhStep() {
|
||||
return currentStep == 5 || currentStep == 7;
|
||||
}
|
||||
|
||||
private boolean isFirstOrThirdStep() {
|
||||
return currentStep == 1 || currentStep == 3;
|
||||
}
|
||||
|
||||
private boolean isEvenStep() {
|
||||
return currentStep == 0 || currentStep % 2 == 0;
|
||||
}
|
||||
|
||||
private boolean isViewHiearchyReady() {
|
||||
return mapView != null && viewParent != null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
if (runnable != null) {
|
||||
handler.removeCallbacks(runnable);
|
||||
runnable = null;
|
||||
}
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.offline
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.BaseAdapter
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import com.mapbox.mapboxsdk.log.Logger
|
||||
import com.mapbox.mapboxsdk.offline.OfflineManager
|
||||
import com.mapbox.mapboxsdk.offline.OfflineRegion
|
||||
import com.mapbox.mapboxsdk.storage.FileSource
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import java.io.File
|
||||
import kotlinx.android.synthetic.main.activity_change_resources_cache_path.*
|
||||
|
||||
class ChangeResourcesCachePathActivity : AppCompatActivity(),
|
||||
AdapterView.OnItemClickListener,
|
||||
FileSource.ResourcesCachePathChangeCallback {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "Mbgl-ChangeResourcesCachePathActivity"
|
||||
}
|
||||
|
||||
private lateinit var adapter: PathAdapter
|
||||
|
||||
private lateinit var offlineManager: OfflineManager
|
||||
|
||||
private val callback = PathChangeCallback(this)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_change_resources_cache_path)
|
||||
|
||||
adapter = PathAdapter(this, obtainExternalFilesPaths())
|
||||
listView.adapter = adapter
|
||||
listView.emptyView = empty
|
||||
listView.onItemClickListener = this
|
||||
|
||||
offlineManager = OfflineManager.getInstance(this)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val path: String? = FileSource.getResourcesCachePath(this)
|
||||
Toast.makeText(this, "Current path: $path", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
callback.onActivityDestroy()
|
||||
}
|
||||
|
||||
override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
listView.onItemClickListener = null
|
||||
val path: String = adapter.getItem(position) as String
|
||||
FileSource.setResourcesCachePath(path, callback)
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
listView.onItemClickListener = this
|
||||
Toast.makeText(this, "Error: $message", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
override fun onSuccess(path: String) {
|
||||
listView.onItemClickListener = this
|
||||
Toast.makeText(this, "New path: $path", Toast.LENGTH_LONG).show()
|
||||
|
||||
offlineManager.listOfflineRegions(object : OfflineManager.ListOfflineRegionsCallback {
|
||||
override fun onList(offlineRegions: Array<out OfflineRegion>?) {
|
||||
Logger.i(TAG, "Number of saved offline regions in the new path: ${offlineRegions?.size}")
|
||||
}
|
||||
|
||||
override fun onError(error: String?) {
|
||||
Logger.e(TAG, error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun Context.obtainExternalFilesPaths(): List<String> {
|
||||
val paths = ArrayList<String>()
|
||||
paths.add(this.filesDir.absolutePath)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
paths.addAll(obtainExternalFilesPathsKitKat())
|
||||
} else {
|
||||
paths.addAll(obtainExternalFilesPathsLegacy())
|
||||
}
|
||||
paths.add("${File.separator}invalid${File.separator}cache${File.separator}path")
|
||||
return paths
|
||||
}
|
||||
|
||||
private fun Context.obtainExternalFilesPathsLegacy(): List<String> {
|
||||
val postFix =
|
||||
"${File.separator}Android${File.separator}data${File.separator}${this.packageName}${File.separator}files"
|
||||
val paths = ArrayList<String>()
|
||||
val externalStorage = System.getenv("EXTERNAL_STORAGE")
|
||||
val secondaryStorage = System.getenv("SECONDARY_STORAGE")
|
||||
if (externalStorage != null) {
|
||||
paths.add(externalStorage + postFix)
|
||||
}
|
||||
if (secondaryStorage != null) {
|
||||
val secPaths = secondaryStorage.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
for (path in secPaths) {
|
||||
paths.add(path + postFix)
|
||||
}
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
private fun Context.obtainExternalFilesPathsKitKat(): List<String> {
|
||||
val paths = ArrayList<String>()
|
||||
val extDirs = this.getExternalFilesDirs(null)
|
||||
for (dir in extDirs) {
|
||||
if (dir != null) {
|
||||
paths.add(dir.absolutePath)
|
||||
}
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
private class PathChangeCallback(private var activity: ChangeResourcesCachePathActivity?) : FileSource.ResourcesCachePathChangeCallback {
|
||||
|
||||
override fun onSuccess(path: String) {
|
||||
activity?.onSuccess(path)
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
activity?.onError(message)
|
||||
}
|
||||
|
||||
fun onActivityDestroy() {
|
||||
activity = null
|
||||
}
|
||||
}
|
||||
|
||||
class PathAdapter(private val context: Context, private val paths: List<String>) : BaseAdapter() {
|
||||
|
||||
override fun getItem(position: Int): Any {
|
||||
return paths[position]
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
return position.toLong()
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return paths.size
|
||||
}
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
|
||||
val viewHolder: ViewHolder
|
||||
val view: View
|
||||
|
||||
if (convertView == null) {
|
||||
viewHolder = ViewHolder()
|
||||
view = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, parent, false)
|
||||
viewHolder.textView = view.findViewById(android.R.id.text1)
|
||||
view?.tag = viewHolder
|
||||
} else {
|
||||
view = convertView
|
||||
viewHolder = view.tag as ViewHolder
|
||||
}
|
||||
|
||||
viewHolder.textView?.text = paths[position]
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
class ViewHolder {
|
||||
var textView: TextView? = null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.offline;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import com.mapbox.mapboxsdk.offline.OfflineManager;
|
||||
import com.mapbox.mapboxsdk.offline.OfflineRegion;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.OfflineUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Test activity showing integration of deleting an OfflineRegion.
|
||||
*/
|
||||
public class DeleteRegionActivity extends AppCompatActivity implements AdapterView.OnItemClickListener,
|
||||
AdapterView.OnItemLongClickListener {
|
||||
|
||||
private OfflineRegionAdapter adapter;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_offline_region_delete);
|
||||
|
||||
ListView listView = findViewById(R.id.listView);
|
||||
listView.setAdapter(adapter = new OfflineRegionAdapter(this));
|
||||
listView.setEmptyView(findViewById(android.R.id.empty));
|
||||
listView.setOnItemClickListener(this);
|
||||
listView.setOnItemLongClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
final OfflineRegion region = adapter.getItem(position);
|
||||
String metadata = OfflineUtils.convertRegionName(region.getMetadata());
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle("Delete region");
|
||||
|
||||
final TextView input = new TextView(this);
|
||||
input.setText(metadata);
|
||||
builder.setView(input);
|
||||
|
||||
builder.setPositiveButton("OK", (dialog, which) -> delete(region));
|
||||
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
|
||||
|
||||
builder.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
final OfflineRegion region = adapter.getItem(position);
|
||||
region.invalidate(new OfflineRegion.OfflineRegionInvalidateCallback() {
|
||||
@Override
|
||||
public void onInvalidate() {
|
||||
Toast.makeText(DeleteRegionActivity.this, "Invalidate region success", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String error) {
|
||||
Toast.makeText(DeleteRegionActivity.this, "Error:" + error, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private void delete(OfflineRegion region) {
|
||||
region.delete(new OfflineRegion.OfflineRegionDeleteCallback() {
|
||||
@Override
|
||||
public void onDelete() {
|
||||
Toast.makeText(
|
||||
DeleteRegionActivity.this,
|
||||
"Region deleted",
|
||||
Toast.LENGTH_SHORT
|
||||
).show();
|
||||
loadOfflineRegions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String error) {
|
||||
Toast.makeText(
|
||||
DeleteRegionActivity.this,
|
||||
"Region deletion failed with " + error,
|
||||
Toast.LENGTH_LONG
|
||||
).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
loadOfflineRegions();
|
||||
}
|
||||
|
||||
private void loadOfflineRegions() {
|
||||
OfflineManager.getInstance(this).listOfflineRegions(new OfflineManager.ListOfflineRegionsCallback() {
|
||||
@Override
|
||||
public void onList(OfflineRegion[] offlineRegions) {
|
||||
if (offlineRegions != null && offlineRegions.length > 0) {
|
||||
adapter.setOfflineRegions(Arrays.asList(offlineRegions));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String error) {
|
||||
Toast.makeText(DeleteRegionActivity.this, "Error loading regions " + error, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static class OfflineRegionAdapter extends BaseAdapter {
|
||||
|
||||
private Context context;
|
||||
private List<OfflineRegion> offlineRegions;
|
||||
|
||||
OfflineRegionAdapter(Context ctx) {
|
||||
context = ctx;
|
||||
offlineRegions = new ArrayList<>();
|
||||
}
|
||||
|
||||
void setOfflineRegions(List<OfflineRegion> offlineRegions) {
|
||||
this.offlineRegions = offlineRegions;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return offlineRegions.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflineRegion getItem(int position) {
|
||||
return offlineRegions.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
ViewHolder holder;
|
||||
|
||||
if (convertView == null) {
|
||||
holder = new ViewHolder();
|
||||
convertView = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, parent, false);
|
||||
holder.text = (TextView) convertView.findViewById(android.R.id.text1);
|
||||
convertView.setTag(holder);
|
||||
} else {
|
||||
holder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
|
||||
holder.text.setText(OfflineUtils.convertRegionName(getItem(position).getMetadata()));
|
||||
return convertView;
|
||||
}
|
||||
|
||||
static class ViewHolder {
|
||||
TextView text;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.offline
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.view.View
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import com.mapbox.mapboxsdk.constants.MapboxConstants
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng
|
||||
import com.mapbox.mapboxsdk.geometry.LatLngBounds
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.offline.*
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlinx.android.synthetic.main.activity_region_download.*
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Example showcasing how to download an offline region headless, allows to test pausing and resuming the download.
|
||||
*/
|
||||
class DownloadRegionActivity : AppCompatActivity(), OfflineRegion.OfflineRegionObserver {
|
||||
|
||||
companion object {
|
||||
const val STATUS_UPDATE_TIMEOUT_MS = 10_000L
|
||||
}
|
||||
|
||||
private val handler: Handler = Handler()
|
||||
private lateinit var offlineManager: OfflineManager
|
||||
private var offlineRegion: OfflineRegion? = null
|
||||
private var downloading = false
|
||||
private var previousCompletedResourceCount: Long = 0
|
||||
private var previousUpdateTimestamp: Long = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_region_download)
|
||||
|
||||
offlineManager = OfflineManager.getInstance(this)
|
||||
offlineManager.setOfflineMapboxTileCountLimit(Long.MAX_VALUE)
|
||||
initUi()
|
||||
|
||||
deleteOldOfflineRegions {
|
||||
container.visibility = View.VISIBLE
|
||||
fab.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
offlineRegion?.setObserver(null)
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun createOfflineRegion() {
|
||||
val latitudeNorth = editTextLatNorth.text.toString().toDouble()
|
||||
val longitudeEast = editTextLonEast.text.toString().toDouble()
|
||||
val latitudeSouth = editTextLatSouth.text.toString().toDouble()
|
||||
val longitudeWest = editTextLonWest.text.toString().toDouble()
|
||||
val styleUrl = spinnerStyleUrl.selectedItem as String
|
||||
val maxZoom = seekbarMaxZoom.progress.toFloat()
|
||||
val minZoom = seekbarMinZoom.progress.toFloat()
|
||||
|
||||
if (!validCoordinates(latitudeNorth, longitudeEast, latitudeSouth, longitudeWest)) {
|
||||
Toast.makeText(this, "coordinates need to be in valid range", Toast.LENGTH_LONG).show()
|
||||
return
|
||||
}
|
||||
|
||||
// create offline definition from data
|
||||
val definition = OfflineTilePyramidRegionDefinition(
|
||||
styleUrl,
|
||||
LatLngBounds.Builder()
|
||||
.include(LatLng(latitudeNorth, longitudeEast))
|
||||
.include(LatLng(latitudeSouth, longitudeWest))
|
||||
.build(),
|
||||
minZoom.toDouble(),
|
||||
maxZoom.toDouble(),
|
||||
resources.displayMetrics.density
|
||||
)
|
||||
|
||||
logMessage("Creating offline region")
|
||||
offlineManager.createOfflineRegion(definition, byteArrayOf(), object : OfflineManager.CreateOfflineRegionCallback {
|
||||
override fun onCreate(region: OfflineRegion) {
|
||||
logMessage("Region with id ${region.id} created")
|
||||
offlineRegion = region
|
||||
startDownload(region)
|
||||
fab.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
override fun onError(error: String) {
|
||||
logMessage("Failed to create offline region: $error")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun startDownload(region: OfflineRegion) {
|
||||
downloading = true
|
||||
fab.setImageResource(R.drawable.ic_pause_black_24dp)
|
||||
logMessage("Downloading...")
|
||||
|
||||
region.setObserver(this)
|
||||
region.setDownloadState(OfflineRegion.STATE_ACTIVE)
|
||||
|
||||
previousUpdateTimestamp = System.currentTimeMillis()
|
||||
handler.postDelayed(object : Runnable {
|
||||
override fun run() {
|
||||
if (System.currentTimeMillis() > previousUpdateTimestamp + STATUS_UPDATE_TIMEOUT_MS) {
|
||||
logMessage("FAILURE! No progress in ${TimeUnit.MILLISECONDS.toSeconds(STATUS_UPDATE_TIMEOUT_MS)} seconds")
|
||||
} else {
|
||||
handler.postDelayed(this, 1000)
|
||||
}
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
private fun pauseDownload(region: OfflineRegion) {
|
||||
downloading = false
|
||||
fab.setImageResource(R.drawable.ic_play_arrow_black_24dp)
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
region.setDownloadState(OfflineRegion.STATE_INACTIVE)
|
||||
"Paused".let {
|
||||
logMessage(it)
|
||||
download_status.text = it
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStatusChanged(status: OfflineRegionStatus) {
|
||||
if (status.isComplete) {
|
||||
"Completed".let {
|
||||
logMessage("SUCCESS! $it")
|
||||
download_status.text = it
|
||||
}
|
||||
fab.setImageResource(R.drawable.ic_play_arrow_black_24dp)
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
offlineRegion?.setObserver(null)
|
||||
offlineRegion?.setDownloadState(OfflineRegion.STATE_INACTIVE)
|
||||
} else {
|
||||
val statusText = "Downloaded ${status.completedResourceCount}/${status.requiredResourceCount}"
|
||||
statusText.let {
|
||||
logMessage(it)
|
||||
download_status.text = it
|
||||
}
|
||||
|
||||
if (status.completedResourceCount > status.requiredResourceCount &&
|
||||
previousCompletedResourceCount <= status.requiredResourceCount
|
||||
) {
|
||||
logMessage("FAILURE! Completed > required")
|
||||
}
|
||||
}
|
||||
|
||||
previousCompletedResourceCount = status.completedResourceCount
|
||||
previousUpdateTimestamp = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
override fun onError(error: OfflineRegionError) {
|
||||
logMessage("Error: $error")
|
||||
}
|
||||
|
||||
override fun mapboxTileCountLimitExceeded(limit: Long) {
|
||||
logMessage("Error: tile count limit exceeded")
|
||||
}
|
||||
|
||||
protected fun logMessage(message: String) {
|
||||
Timber.d(message)
|
||||
logView.append(message)
|
||||
logView.append("\n")
|
||||
}
|
||||
|
||||
fun deleteOldOfflineRegions(onCompleted: () -> Unit) {
|
||||
offlineManager.listOfflineRegions(object : OfflineManager.ListOfflineRegionsCallback {
|
||||
override fun onList(offlineRegions: Array<out OfflineRegion>) {
|
||||
val count = offlineRegions.size
|
||||
var remainingCount = count
|
||||
if (count > 0) {
|
||||
logMessage("Deleting $count old region...")
|
||||
offlineRegions.forEach {
|
||||
it.delete(object : OfflineRegion.OfflineRegionDeleteCallback {
|
||||
override fun onDelete() {
|
||||
Timber.d("Deleted region with id ${it.id}")
|
||||
onProcessed()
|
||||
}
|
||||
|
||||
override fun onError(error: String) {
|
||||
Timber.e("Failed to delete region: $error")
|
||||
onProcessed()
|
||||
}
|
||||
|
||||
private fun onProcessed() {
|
||||
remainingCount--
|
||||
if (remainingCount == 0) {
|
||||
logMessage("Done deleting")
|
||||
onCompleted()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
onCompleted()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(error: String) {
|
||||
logMessage("Failed to list offline regions: $error")
|
||||
onCompleted()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// ui
|
||||
|
||||
private val logView: TextView by lazy {
|
||||
findViewById<TextView>(R.id.log_text)
|
||||
}
|
||||
|
||||
private fun initUi() {
|
||||
initEditTexts()
|
||||
initSeekbars()
|
||||
initSpinner()
|
||||
initZoomLevelTextviews()
|
||||
initSeekbarListeners()
|
||||
initFab()
|
||||
}
|
||||
|
||||
private fun initEditTexts() {
|
||||
editTextLatNorth.setText("62.0")
|
||||
editTextLonEast.setText("24.0")
|
||||
editTextLatSouth.setText("60.0")
|
||||
editTextLonWest.setText("22.5")
|
||||
}
|
||||
|
||||
private fun initSeekbars() {
|
||||
val maxZoom = MapboxConstants.MAXIMUM_ZOOM.toInt()
|
||||
seekbarMinZoom.max = maxZoom
|
||||
seekbarMinZoom.progress = 1
|
||||
seekbarMaxZoom.max = maxZoom
|
||||
seekbarMaxZoom.progress = 15
|
||||
}
|
||||
|
||||
private fun initSpinner() {
|
||||
val styles = ArrayList<String>()
|
||||
styles.add(Style.MAPBOX_STREETS)
|
||||
styles.add(Style.DARK)
|
||||
styles.add(Style.LIGHT)
|
||||
styles.add(Style.OUTDOORS)
|
||||
val spinnerArrayAdapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, styles)
|
||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
spinnerStyleUrl.adapter = spinnerArrayAdapter
|
||||
}
|
||||
|
||||
private fun initZoomLevelTextviews() {
|
||||
textViewMaxText.text = String.format("Max zoom: %s", seekbarMaxZoom.progress)
|
||||
textViewMinText.text = String.format("Min zoom: %s", seekbarMinZoom.progress)
|
||||
}
|
||||
|
||||
private fun initFab() {
|
||||
fab.setOnClickListener {
|
||||
container.visibility = View.GONE
|
||||
if (offlineRegion == null) {
|
||||
fab.visibility = View.GONE
|
||||
createOfflineRegion()
|
||||
} else {
|
||||
offlineRegion?.let {
|
||||
if (downloading) {
|
||||
pauseDownload(it)
|
||||
} else {
|
||||
startDownload(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initSeekbarListeners() {
|
||||
seekbarMaxZoom.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
textViewMaxText.text = String.format("Max zoom: %s", progress)
|
||||
}
|
||||
|
||||
override fun onStartTrackingTouch(seekBar: SeekBar) {
|
||||
}
|
||||
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar) {
|
||||
}
|
||||
})
|
||||
|
||||
seekbarMinZoom.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
textViewMinText.text = String.format("Min zoom: %s", progress)
|
||||
}
|
||||
|
||||
override fun onStartTrackingTouch(seekBar: SeekBar) {
|
||||
}
|
||||
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun validCoordinates(
|
||||
latitudeNorth: Double,
|
||||
longitudeEast: Double,
|
||||
latitudeSouth: Double,
|
||||
longitudeWest: Double
|
||||
): Boolean {
|
||||
if (latitudeNorth < -90 || latitudeNorth > 90) {
|
||||
return false
|
||||
} else if (longitudeEast < -180 || longitudeEast > 180) {
|
||||
return false
|
||||
} else if (latitudeSouth < -90 || latitudeSouth > 90) {
|
||||
return false
|
||||
} else if (longitudeWest < -180 || longitudeWest > 180) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.offline
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.widget.Toast
|
||||
import com.mapbox.mapboxsdk.Mapbox
|
||||
import com.mapbox.mapboxsdk.log.Logger
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.offline.OfflineManager
|
||||
import com.mapbox.mapboxsdk.offline.OfflineRegion
|
||||
import com.mapbox.mapboxsdk.storage.FileSource
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import com.mapbox.mapboxsdk.testapp.utils.FileUtils
|
||||
import kotlinx.android.synthetic.main.activity_merge_offline_regions.*
|
||||
|
||||
class MergeOfflineRegionsActivity : AppCompatActivity() {
|
||||
companion object {
|
||||
private const val LOG_TAG = "Mbgl-MergeOfflineRegionsActivity"
|
||||
private const val TEST_DB_FILE_NAME = "offline_test.db"
|
||||
private const val TEST_STYLE = Style.SATELLITE
|
||||
}
|
||||
|
||||
private val onFileCopiedListener = object : FileUtils.OnFileCopiedFromAssetsListener {
|
||||
override fun onFileCopiedFromAssets() {
|
||||
Toast.makeText(
|
||||
this@MergeOfflineRegionsActivity,
|
||||
String.format("OnFileCopied."),
|
||||
Toast.LENGTH_LONG).show()
|
||||
mergeDb()
|
||||
}
|
||||
|
||||
override fun onError() {
|
||||
Toast.makeText(
|
||||
this@MergeOfflineRegionsActivity,
|
||||
String.format("Error copying DB file."),
|
||||
Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
|
||||
private val onRegionMergedListener = object : OfflineManager.MergeOfflineRegionsCallback {
|
||||
override fun onMerge(offlineRegions: Array<OfflineRegion>) {
|
||||
mapView.getMapAsync {
|
||||
it.setStyle(Style.Builder().fromUri(TEST_STYLE))
|
||||
}
|
||||
Toast.makeText(
|
||||
this@MergeOfflineRegionsActivity,
|
||||
String.format("Merged %d regions.", offlineRegions.size),
|
||||
Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
override fun onError(error: String) {
|
||||
Toast.makeText(
|
||||
this@MergeOfflineRegionsActivity,
|
||||
String.format("Offline DB merge error."),
|
||||
Toast.LENGTH_LONG).show()
|
||||
Logger.e(LOG_TAG, error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Since we expect from the results of the offline merge callback to interact with the hosting activity,
|
||||
* we need to ensure that we are not interacting with a destroyed activity.
|
||||
*/
|
||||
private class MergeCallback(private var activityCallback: OfflineManager.MergeOfflineRegionsCallback?) : OfflineManager.MergeOfflineRegionsCallback {
|
||||
|
||||
override fun onMerge(offlineRegions: Array<out OfflineRegion>?) {
|
||||
activityCallback?.onMerge(offlineRegions)
|
||||
}
|
||||
|
||||
override fun onError(error: String?) {
|
||||
activityCallback?.onError(error)
|
||||
}
|
||||
|
||||
fun onActivityDestroy() {
|
||||
activityCallback = null
|
||||
}
|
||||
}
|
||||
|
||||
private val mergeCallback = MergeCallback(onRegionMergedListener)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_merge_offline_regions)
|
||||
|
||||
// forcing offline state
|
||||
Mapbox.setConnected(false)
|
||||
|
||||
mapView.onCreate(savedInstanceState)
|
||||
load_region_btn.setOnClickListener {
|
||||
copyAsset()
|
||||
}
|
||||
mapView.getMapAsync {
|
||||
it.isDebugActive = true
|
||||
it.setStyle(Style.Builder().fromUri(TEST_STYLE))
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyAsset() {
|
||||
// copy db asset to internal memory
|
||||
FileUtils.CopyFileFromAssetsTask(this, onFileCopiedListener).execute(TEST_DB_FILE_NAME, FileSource.getResourcesCachePath(this))
|
||||
}
|
||||
|
||||
private fun mergeDb() {
|
||||
OfflineManager.getInstance(this).mergeOfflineRegions(
|
||||
FileSource.getResourcesCachePath(this) + "/" + TEST_DB_FILE_NAME, mergeCallback
|
||||
)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mergeCallback.onActivityDestroy()
|
||||
mapView.onDestroy()
|
||||
|
||||
// restoring connectivity state
|
||||
Mapbox.setConnected(null)
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.offline;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.mapbox.mapboxsdk.Mapbox;
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.offline.OfflineManager;
|
||||
import com.mapbox.mapboxsdk.offline.OfflineRegion;
|
||||
import com.mapbox.mapboxsdk.offline.OfflineRegionError;
|
||||
import com.mapbox.mapboxsdk.offline.OfflineRegionStatus;
|
||||
import com.mapbox.mapboxsdk.offline.OfflineTilePyramidRegionDefinition;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.testapp.model.other.OfflineDownloadRegionDialog;
|
||||
import com.mapbox.mapboxsdk.testapp.model.other.OfflineListRegionsDialog;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.OfflineUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Test activity showcasing the Offline API.
|
||||
* <p>
|
||||
* Shows a map of Manhattan and allows the user to download and name a region.
|
||||
* </p>
|
||||
*/
|
||||
public class OfflineActivity extends AppCompatActivity
|
||||
implements OfflineDownloadRegionDialog.DownloadRegionDialogListener {
|
||||
|
||||
// JSON encoding/decoding
|
||||
public static final String JSON_CHARSET = "UTF-8";
|
||||
public static final String JSON_FIELD_REGION_NAME = "FIELD_REGION_NAME";
|
||||
|
||||
// Style URL
|
||||
public static final String STYLE_URL = Style.MAPBOX_STREETS;
|
||||
|
||||
/*
|
||||
* UI elements
|
||||
*/
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private ProgressBar progressBar;
|
||||
private Button downloadRegion;
|
||||
private Button listRegions;
|
||||
|
||||
private boolean isEndNotified;
|
||||
|
||||
/*
|
||||
* Offline objects
|
||||
*/
|
||||
private OfflineManager offlineManager;
|
||||
private OfflineRegion offlineRegion;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_offline);
|
||||
|
||||
// You can use Mapbox.setConnected(Boolean) to manually set the connectivity
|
||||
// state of your app. This will override any checks performed via the ConnectivityManager.
|
||||
// Mapbox.getInstance().setConnected(false);
|
||||
Boolean connected = Mapbox.isConnected();
|
||||
Timber.d("Mapbox is connected: %s", connected);
|
||||
|
||||
// Set up map
|
||||
mapView = (MapView) findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(mapboxMap -> {
|
||||
Timber.d("Map is ready");
|
||||
OfflineActivity.this.mapboxMap = mapboxMap;
|
||||
mapboxMap.setStyle(new Style.Builder().fromUri(STYLE_URL));
|
||||
// Set initial position to UNHQ in NYC
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
|
||||
new CameraPosition.Builder()
|
||||
.target(new LatLng(40.749851, -73.967966))
|
||||
.zoom(14)
|
||||
.bearing(0)
|
||||
.tilt(0)
|
||||
.build()));
|
||||
});
|
||||
|
||||
// The progress bar
|
||||
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
|
||||
|
||||
// Set up button listeners
|
||||
downloadRegion = (Button) findViewById(R.id.button_download_region);
|
||||
downloadRegion.setOnClickListener(view -> handleDownloadRegion());
|
||||
|
||||
listRegions = (Button) findViewById(R.id.button_list_regions);
|
||||
listRegions.setOnClickListener(view -> handleListRegions());
|
||||
|
||||
// Set up the OfflineManager
|
||||
offlineManager = OfflineManager.getInstance(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
/*
|
||||
* Buttons logic
|
||||
*/
|
||||
private void handleDownloadRegion() {
|
||||
Timber.d("handleDownloadRegion");
|
||||
|
||||
// Show dialog
|
||||
OfflineDownloadRegionDialog offlineDownloadRegionDialog = new OfflineDownloadRegionDialog();
|
||||
offlineDownloadRegionDialog.show(getSupportFragmentManager(), "download");
|
||||
}
|
||||
|
||||
private void handleListRegions() {
|
||||
Timber.d("handleListRegions");
|
||||
|
||||
// Query the DB asynchronously
|
||||
offlineManager.listOfflineRegions(new OfflineManager.ListOfflineRegionsCallback() {
|
||||
@Override
|
||||
public void onList(OfflineRegion[] offlineRegions) {
|
||||
// Check result
|
||||
if (offlineRegions == null || offlineRegions.length == 0) {
|
||||
Toast.makeText(OfflineActivity.this, "You have no regions yet.", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get regions info
|
||||
ArrayList<String> offlineRegionsNames = new ArrayList<>();
|
||||
for (OfflineRegion offlineRegion : offlineRegions) {
|
||||
offlineRegionsNames.add(OfflineUtils.convertRegionName(offlineRegion.getMetadata()));
|
||||
}
|
||||
|
||||
// Create args
|
||||
Bundle args = new Bundle();
|
||||
args.putStringArrayList(OfflineListRegionsDialog.ITEMS, offlineRegionsNames);
|
||||
|
||||
// Show dialog
|
||||
OfflineListRegionsDialog offlineListRegionsDialog = new OfflineListRegionsDialog();
|
||||
offlineListRegionsDialog.setArguments(args);
|
||||
offlineListRegionsDialog.show(getSupportFragmentManager(), "list");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String error) {
|
||||
Timber.e("Error: %s" , error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Dialogs
|
||||
*/
|
||||
@Override
|
||||
public void onDownloadRegionDialogPositiveClick(final String regionName) {
|
||||
if (TextUtils.isEmpty(regionName)) {
|
||||
Toast.makeText(OfflineActivity.this, "Region name cannot be empty.", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
// Start progress bar
|
||||
Timber.d("Download started: %s", regionName);
|
||||
startProgress();
|
||||
|
||||
// Definition
|
||||
LatLngBounds bounds = mapboxMap.getProjection().getVisibleRegion().latLngBounds;
|
||||
double minZoom = mapboxMap.getCameraPosition().zoom;
|
||||
double maxZoom = mapboxMap.getMaxZoomLevel();
|
||||
float pixelRatio = this.getResources().getDisplayMetrics().density;
|
||||
OfflineTilePyramidRegionDefinition definition = new OfflineTilePyramidRegionDefinition(
|
||||
STYLE_URL, bounds, minZoom, maxZoom, pixelRatio);
|
||||
|
||||
// Sample way of encoding metadata from a JSONObject
|
||||
byte[] metadata = OfflineUtils.convertRegionName(regionName);
|
||||
|
||||
// Create region
|
||||
offlineManager.createOfflineRegion(definition, metadata, new OfflineManager.CreateOfflineRegionCallback() {
|
||||
@Override
|
||||
public void onCreate(OfflineRegion offlineRegion) {
|
||||
Timber.d("Offline region created: %s" , regionName);
|
||||
OfflineActivity.this.offlineRegion = offlineRegion;
|
||||
launchDownload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String error) {
|
||||
Timber.e("Error: %s", error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void launchDownload() {
|
||||
// Set an observer
|
||||
offlineRegion.setObserver(new OfflineRegion.OfflineRegionObserver() {
|
||||
@Override
|
||||
public void onStatusChanged(OfflineRegionStatus status) {
|
||||
// Compute a percentage
|
||||
double percentage = status.getRequiredResourceCount() >= 0
|
||||
? (100.0 * status.getCompletedResourceCount() / status.getRequiredResourceCount()) :
|
||||
0.0;
|
||||
|
||||
if (status.isComplete()) {
|
||||
// Download complete
|
||||
endProgress("Region downloaded successfully.");
|
||||
offlineRegion.setDownloadState(OfflineRegion.STATE_INACTIVE);
|
||||
offlineRegion.setObserver(null);
|
||||
return;
|
||||
} else if (status.isRequiredResourceCountPrecise()) {
|
||||
// Switch to determinate state
|
||||
setPercentage((int) Math.round(percentage));
|
||||
}
|
||||
|
||||
// Debug
|
||||
Timber.d("%s/%s resources; %s bytes downloaded.",
|
||||
String.valueOf(status.getCompletedResourceCount()),
|
||||
String.valueOf(status.getRequiredResourceCount()),
|
||||
String.valueOf(status.getCompletedResourceSize()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(OfflineRegionError error) {
|
||||
Timber.e("onError: %s, %s", error.getReason(), error.getMessage());
|
||||
offlineRegion.setDownloadState(OfflineRegion.STATE_INACTIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mapboxTileCountLimitExceeded(long limit) {
|
||||
Timber.e("Mapbox tile count limit exceeded: %s", limit);
|
||||
offlineRegion.setDownloadState(OfflineRegion.STATE_INACTIVE);
|
||||
}
|
||||
});
|
||||
|
||||
// Change the region state
|
||||
offlineRegion.setDownloadState(OfflineRegion.STATE_ACTIVE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Progress bar
|
||||
*/
|
||||
private void startProgress() {
|
||||
// Disable buttons
|
||||
downloadRegion.setEnabled(false);
|
||||
listRegions.setEnabled(false);
|
||||
|
||||
// Start and show the progress bar
|
||||
isEndNotified = false;
|
||||
progressBar.setIndeterminate(true);
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void setPercentage(final int percentage) {
|
||||
progressBar.setIndeterminate(false);
|
||||
progressBar.setProgress(percentage);
|
||||
}
|
||||
|
||||
private void endProgress(final String message) {
|
||||
// Don't notify more than once
|
||||
if (isEndNotified) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable buttons
|
||||
downloadRegion.setEnabled(true);
|
||||
listRegions.setEnabled(true);
|
||||
|
||||
// Stop and hide the progress bar
|
||||
isEndNotified = true;
|
||||
progressBar.setIndeterminate(false);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
|
||||
// Show a toast
|
||||
Toast.makeText(OfflineActivity.this, message, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.offline;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.InputType;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.offline.OfflineManager;
|
||||
import com.mapbox.mapboxsdk.offline.OfflineRegion;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.OfflineUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Test activity showing integration of updating metadata of an OfflineRegion.
|
||||
*/
|
||||
public class UpdateMetadataActivity extends AppCompatActivity implements AdapterView.OnItemClickListener,
|
||||
AdapterView.OnItemLongClickListener {
|
||||
|
||||
private OfflineRegionMetadataAdapter adapter;
|
||||
|
||||
private MapView mapView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_metadata_update);
|
||||
|
||||
ListView listView = findViewById(R.id.listView);
|
||||
listView.setAdapter(adapter = new OfflineRegionMetadataAdapter(this));
|
||||
listView.setEmptyView(findViewById(android.R.id.empty));
|
||||
listView.setOnItemClickListener(this);
|
||||
listView.setOnItemLongClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
final OfflineRegion region = adapter.getItem(position);
|
||||
String metadata = OfflineUtils.convertRegionName(region.getMetadata());
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle("Rename metadata");
|
||||
|
||||
final EditText input = new EditText(this);
|
||||
input.setText(metadata);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||
if (metadata != null) {
|
||||
input.setSelection(metadata.length());
|
||||
}
|
||||
builder.setView(input);
|
||||
|
||||
builder.setPositiveButton("OK", (dialog, which) ->
|
||||
updateMetadata(region, OfflineUtils.convertRegionName(input.getText().toString()))
|
||||
);
|
||||
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
|
||||
|
||||
builder.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
ViewGroup container = findViewById(R.id.container);
|
||||
container.removeAllViews();
|
||||
container.addView(mapView = new MapView(view.getContext()));
|
||||
mapView.onCreate(null);
|
||||
mapView.getMapAsync(map -> map.setOfflineRegionDefinition(adapter.getItem(position).getDefinition()));
|
||||
mapView.onStart();
|
||||
mapView.onResume();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateMetadata(OfflineRegion region, byte[] metadata) {
|
||||
region.updateMetadata(metadata, new OfflineRegion.OfflineRegionUpdateMetadataCallback() {
|
||||
@Override
|
||||
public void onUpdate(byte[] metadata) {
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String error) {
|
||||
Toast.makeText(
|
||||
UpdateMetadataActivity.this,
|
||||
"Region metadata update failed with " + error,
|
||||
Toast.LENGTH_LONG
|
||||
).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
loadOfflineRegions();
|
||||
}
|
||||
|
||||
private void loadOfflineRegions() {
|
||||
OfflineManager.getInstance(this).listOfflineRegions(new OfflineManager.ListOfflineRegionsCallback() {
|
||||
@Override
|
||||
public void onList(OfflineRegion[] offlineRegions) {
|
||||
if (offlineRegions != null && offlineRegions.length > 0) {
|
||||
adapter.setOfflineRegions(Arrays.asList(offlineRegions));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String error) {
|
||||
Toast.makeText(UpdateMetadataActivity.this, "Error loading regions " + error, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mapView != null) {
|
||||
mapView.onPause();
|
||||
mapView.onStop();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
private static class OfflineRegionMetadataAdapter extends BaseAdapter {
|
||||
|
||||
private Context context;
|
||||
private List<OfflineRegion> offlineRegions;
|
||||
|
||||
OfflineRegionMetadataAdapter(Context ctx) {
|
||||
context = ctx;
|
||||
offlineRegions = new ArrayList<>();
|
||||
}
|
||||
|
||||
void setOfflineRegions(List<OfflineRegion> offlineRegions) {
|
||||
this.offlineRegions = offlineRegions;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return offlineRegions.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflineRegion getItem(int position) {
|
||||
return offlineRegions.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
ViewHolder holder;
|
||||
|
||||
if (convertView == null) {
|
||||
holder = new ViewHolder();
|
||||
convertView = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, parent, false);
|
||||
holder.text = (TextView) convertView.findViewById(android.R.id.text1);
|
||||
convertView.setTag(holder);
|
||||
} else {
|
||||
holder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
|
||||
holder.text.setText(OfflineUtils.convertRegionName(getItem(position).getMetadata()));
|
||||
return convertView;
|
||||
}
|
||||
|
||||
static class ViewHolder {
|
||||
TextView text;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.render;
|
||||
|
||||
import android.content.res.AssetManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Gravity;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter;
|
||||
import okio.BufferedSource;
|
||||
import okio.Okio;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Activity that generates map snapshots based on the node render test suite.
|
||||
*/
|
||||
public class RenderTestActivity extends AppCompatActivity {
|
||||
|
||||
private static final String TEST_BASE_PATH = "integration";
|
||||
private static final String RENDER_TEST_BASE_PATH = TEST_BASE_PATH + "/render-tests";
|
||||
|
||||
// We additionally read out excluded tests from `/platform/node/test/ignore.json`
|
||||
private static final List<String> EXCLUDED_TESTS = new ArrayList<String>() {
|
||||
{
|
||||
add("overlay,background-opacity");
|
||||
add("collision-lines-pitched,debug");
|
||||
add("1024-circle,extent");
|
||||
add("empty,empty");
|
||||
add("rotation-alignment-map,icon-pitch-scaling");
|
||||
add("rotation-alignment-viewport,icon-pitch-scaling");
|
||||
add("pitch15,line-pitch");
|
||||
add("pitch30,line-pitch");
|
||||
add("line-placement-true-pitched,text-keep-upright");
|
||||
add("180,raster-rotation");
|
||||
add("45,raster-rotation");
|
||||
add("90,raster-rotation");
|
||||
add("overlapping,raster-masking");
|
||||
add("missing,raster-loading");
|
||||
add("pitchAndBearing,line-pitch");
|
||||
add("overdraw,sparse-tileset");
|
||||
}
|
||||
};
|
||||
|
||||
private final Map<RenderTestDefinition, Bitmap> renderResultMap = new HashMap<>();
|
||||
private List<RenderTestDefinition> renderTestDefinitions;
|
||||
private OnRenderTestCompletionListener onRenderTestCompletionListener;
|
||||
private MapSnapshotter mapSnapshotter;
|
||||
private ImageView imageView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(imageView = new ImageView(RenderTestActivity.this));
|
||||
imageView.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
if (mapSnapshotter != null) {
|
||||
mapSnapshotter.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Loads the ignore tests from assets folder
|
||||
//
|
||||
private static class LoadRenderIgnoreTask extends AsyncTask<Void, Void, List<String>> {
|
||||
|
||||
private WeakReference<RenderTestActivity> renderTestActivityWeakReference;
|
||||
|
||||
LoadRenderIgnoreTask(RenderTestActivity renderTestActivity) {
|
||||
this.renderTestActivityWeakReference = new WeakReference<>(renderTestActivity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> doInBackground(Void... voids) {
|
||||
return loadIgnoreList(renderTestActivityWeakReference.get().getAssets());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<String> strings) {
|
||||
super.onPostExecute(strings);
|
||||
if (renderTestActivityWeakReference.get() != null) {
|
||||
renderTestActivityWeakReference.get().onLoadIgnoreList(strings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Loads the render test definitions from assets folder
|
||||
//
|
||||
private static class LoadRenderDefinitionTask extends AsyncTask<Void, Void, List<RenderTestDefinition>> {
|
||||
|
||||
private WeakReference<RenderTestActivity> renderTestActivityWeakReference;
|
||||
|
||||
LoadRenderDefinitionTask(RenderTestActivity renderTestActivity) {
|
||||
this.renderTestActivityWeakReference = new WeakReference<>(renderTestActivity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<RenderTestDefinition> doInBackground(Void... voids) {
|
||||
List<RenderTestDefinition> definitions = new ArrayList<>();
|
||||
AssetManager assetManager = renderTestActivityWeakReference.get().getAssets();
|
||||
String[] categories = new String[0];
|
||||
try {
|
||||
categories = assetManager.list(RENDER_TEST_BASE_PATH);
|
||||
} catch (IOException exception) {
|
||||
Timber.e(exception);
|
||||
}
|
||||
for (int counter = categories.length - 1; counter >= 0; counter--) {
|
||||
try {
|
||||
String[] tests = assetManager.list(String.format("%s/%s", RENDER_TEST_BASE_PATH, categories[counter]));
|
||||
for (String test : tests) {
|
||||
String styleJson = loadStyleJson(assetManager, categories[counter], test);
|
||||
RenderTestStyleDefinition renderTestStyleDefinition = new Gson()
|
||||
.fromJson(styleJson, RenderTestStyleDefinition.class);
|
||||
RenderTestDefinition definition = new RenderTestDefinition(
|
||||
categories[counter], test, styleJson, renderTestStyleDefinition);
|
||||
if (!definition.hasOperations()) {
|
||||
if (!EXCLUDED_TESTS.contains(definition.getName() + "," + definition.getCategory())) {
|
||||
definitions.add(definition);
|
||||
}
|
||||
} else {
|
||||
Timber.e("could not add test, test requires operations: %s from %s", test, categories[counter]);
|
||||
}
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
Timber.e(exception);
|
||||
}
|
||||
}
|
||||
return definitions;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<RenderTestDefinition> renderTestDefinitions) {
|
||||
super.onPostExecute(renderTestDefinitions);
|
||||
RenderTestActivity renderTestActivity = renderTestActivityWeakReference.get();
|
||||
if (renderTestActivity != null) {
|
||||
renderTestActivity.startRenderTests(renderTestDefinitions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> loadIgnoreList(AssetManager assets) {
|
||||
List<String> ignores = new ArrayList<>();
|
||||
try (InputStream input = assets.open(String.format("%s/ignores.json", TEST_BASE_PATH))) {
|
||||
BufferedSource source = Okio.buffer(Okio.source(input));
|
||||
String styleJson = source.readByteString().string(Charset.forName("utf-8"));
|
||||
JsonObject object = new Gson().fromJson(styleJson, JsonObject.class);
|
||||
for (Map.Entry<String, JsonElement> stringJsonElementEntry : object.entrySet()) {
|
||||
String[] parts = stringJsonElementEntry.getKey().split("/");
|
||||
ignores.add(String.format("%s,%s", parts[2], parts[1]));
|
||||
}
|
||||
} catch (IOException exception) {
|
||||
Timber.e(exception);
|
||||
}
|
||||
return ignores;
|
||||
}
|
||||
|
||||
private static String loadStyleJson(AssetManager assets, String category, String test) {
|
||||
String styleJson = null;
|
||||
try (InputStream input = assets.open(String.format("%s/%s/%s/style.json", RENDER_TEST_BASE_PATH, category, test))) {
|
||||
BufferedSource source = Okio.buffer(Okio.source(input));
|
||||
styleJson = source.readByteString().string(Charset.forName("utf-8"));
|
||||
} catch (IOException exception) {
|
||||
Timber.e(exception);
|
||||
}
|
||||
return styleJson;
|
||||
}
|
||||
|
||||
private void startRenderTests(List<RenderTestDefinition> renderTestDefinitions) {
|
||||
this.renderTestDefinitions = renderTestDefinitions;
|
||||
if (!renderTestDefinitions.isEmpty()) {
|
||||
render(renderTestDefinitions.get(0), renderTestDefinitions.size());
|
||||
} else {
|
||||
// no definitions, finish test without rendering
|
||||
onRenderTestCompletionListener.onFinish();
|
||||
}
|
||||
}
|
||||
|
||||
private void render(final RenderTestDefinition renderTestDefinition, final int testSize) {
|
||||
Timber.d("Render test %s,%s", renderTestDefinition.getName(), renderTestDefinition.getCategory());
|
||||
mapSnapshotter = new RenderTestSnapshotter(this, renderTestDefinition.toOptions());
|
||||
mapSnapshotter.start(result -> {
|
||||
Bitmap snapshot = result.getBitmap();
|
||||
imageView.setImageBitmap(snapshot);
|
||||
renderResultMap.put(renderTestDefinition, snapshot);
|
||||
if (renderResultMap.size() != testSize) {
|
||||
continueTesting(renderTestDefinition);
|
||||
} else {
|
||||
finishTesting();
|
||||
}
|
||||
}, error -> Timber.e(error));
|
||||
}
|
||||
|
||||
private void continueTesting(RenderTestDefinition renderTestDefinition) {
|
||||
int next = renderTestDefinitions.indexOf(renderTestDefinition) + 1;
|
||||
Timber.d("Next test: %s / %s", next, renderTestDefinitions.size());
|
||||
render(renderTestDefinitions.get(next), renderTestDefinitions.size());
|
||||
}
|
||||
|
||||
private void finishTesting() {
|
||||
new SaveResultToDiskTask(onRenderTestCompletionListener, renderResultMap).execute();
|
||||
}
|
||||
|
||||
//
|
||||
// Save tests results to disk
|
||||
//
|
||||
private static class SaveResultToDiskTask extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
private OnRenderTestCompletionListener onRenderTestCompletionListener;
|
||||
private Map<RenderTestDefinition, Bitmap> renderResultMap;
|
||||
|
||||
SaveResultToDiskTask(OnRenderTestCompletionListener onRenderTestCompletionListener,
|
||||
Map<RenderTestDefinition, Bitmap> renderResultMap) {
|
||||
this.onRenderTestCompletionListener = onRenderTestCompletionListener;
|
||||
this.renderResultMap = renderResultMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
if (isExternalStorageWritable()) {
|
||||
try {
|
||||
File testResultDir = FileUtils.createTestResultRootFolder();
|
||||
String basePath = testResultDir.getAbsolutePath();
|
||||
for (Map.Entry<RenderTestDefinition, Bitmap> testResult : renderResultMap.entrySet()) {
|
||||
writeResultToDisk(basePath, testResult);
|
||||
}
|
||||
} catch (final Exception exception) {
|
||||
Timber.e(exception);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void writeResultToDisk(String path, Map.Entry<RenderTestDefinition, Bitmap> result) {
|
||||
RenderTestDefinition definition = result.getKey();
|
||||
String categoryName = definition.getCategory();
|
||||
String categoryPath = String.format("%s/%s", path, categoryName);
|
||||
FileUtils.createCategoryDirectory(categoryPath);
|
||||
String testName = result.getKey().getName();
|
||||
String testDir = FileUtils.createTestDirectory(categoryPath, testName);
|
||||
FileUtils.writeTestResultToDisk(testDir, result.getValue());
|
||||
}
|
||||
|
||||
private boolean isExternalStorageWritable() {
|
||||
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
super.onPostExecute(aVoid);
|
||||
if (onRenderTestCompletionListener != null) {
|
||||
onRenderTestCompletionListener.onFinish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Callback configuration to notify test executor of test finishing
|
||||
//
|
||||
public interface OnRenderTestCompletionListener {
|
||||
void onFinish();
|
||||
}
|
||||
|
||||
public void setOnRenderTestCompletionListener(OnRenderTestCompletionListener listener) {
|
||||
this.onRenderTestCompletionListener = listener;
|
||||
new LoadRenderIgnoreTask(this).execute();
|
||||
}
|
||||
|
||||
public void onLoadIgnoreList(List<String> ignoreList) {
|
||||
Timber.e("We loaded %s of tests to be ignored", ignoreList.size());
|
||||
EXCLUDED_TESTS.addAll(ignoreList);
|
||||
new LoadRenderDefinitionTask(this).execute();
|
||||
}
|
||||
|
||||
//
|
||||
// FileUtils
|
||||
//
|
||||
|
||||
private static class FileUtils {
|
||||
|
||||
private static void createCategoryDirectory(String catPath) {
|
||||
File testResultDir = new File(catPath);
|
||||
if (testResultDir.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!testResultDir.mkdirs()) {
|
||||
throw new RuntimeException("can't create root test directory");
|
||||
}
|
||||
}
|
||||
|
||||
private static File createTestResultRootFolder() {
|
||||
File testResultDir = new File(Environment.getExternalStorageDirectory()
|
||||
+ File.separator + "mapbox" + File.separator + "render");
|
||||
if (testResultDir.exists()) {
|
||||
// cleanup old files
|
||||
deleteRecursive(testResultDir);
|
||||
}
|
||||
|
||||
if (!testResultDir.mkdirs()) {
|
||||
throw new RuntimeException("can't create root test directory");
|
||||
}
|
||||
return testResultDir;
|
||||
}
|
||||
|
||||
private static void deleteRecursive(File fileOrDirectory) {
|
||||
if (fileOrDirectory.isDirectory()) {
|
||||
File[] files = fileOrDirectory.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
deleteRecursive(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!fileOrDirectory.delete()) {
|
||||
Timber.e("can't delete directory");
|
||||
}
|
||||
}
|
||||
|
||||
private static String createTestDirectory(String basePath, String testName) {
|
||||
File testDir = new File(basePath + "/" + testName);
|
||||
if (!testDir.exists()) {
|
||||
if (!testDir.mkdir()) {
|
||||
throw new RuntimeException("can't create sub directory for " + testName);
|
||||
}
|
||||
}
|
||||
return testDir.getAbsolutePath();
|
||||
}
|
||||
|
||||
private static void writeTestResultToDisk(String testPath, Bitmap testResult) {
|
||||
String filePath = testPath + "/actual.png";
|
||||
try (FileOutputStream out = new FileOutputStream(filePath)) {
|
||||
testResult.compress(Bitmap.CompressFormat.PNG, 100, out);
|
||||
} catch (IOException exception) {
|
||||
Timber.e(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.render;
|
||||
|
||||
import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter;
|
||||
|
||||
public class RenderTestDefinition {
|
||||
|
||||
private static final int DEFAULT_WIDTH = 512;
|
||||
private static final int DEFAULT_HEIGHT = 512;
|
||||
|
||||
private String category; // eg. background-color
|
||||
private String name; // eg. colorSpace-hcl
|
||||
private String styleJson;
|
||||
private RenderTestStyleDefinition definition;
|
||||
|
||||
RenderTestDefinition(String category, String name, String styleJson, RenderTestStyleDefinition definition) {
|
||||
this.category = category;
|
||||
this.name = name;
|
||||
this.styleJson = styleJson;
|
||||
this.definition = definition;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
RenderTestStyleDefinition.Test test = getTest();
|
||||
if (test != null) {
|
||||
Integer testWidth = test.getWidth();
|
||||
if (testWidth != null && testWidth > 0) {
|
||||
return testWidth;
|
||||
}
|
||||
}
|
||||
return DEFAULT_WIDTH;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
RenderTestStyleDefinition.Test test = getTest();
|
||||
if (test != null) {
|
||||
Integer testHeight = test.getHeight();
|
||||
if (testHeight != null && testHeight > 0) {
|
||||
return testHeight;
|
||||
}
|
||||
}
|
||||
return DEFAULT_HEIGHT;
|
||||
}
|
||||
|
||||
public float getPixelRatio() {
|
||||
RenderTestStyleDefinition.Test test = getTest();
|
||||
if (test != null) {
|
||||
Float pixelRatio = test.getPixelRatio();
|
||||
if (pixelRatio != null && pixelRatio > 0) {
|
||||
return pixelRatio;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public String getStyleJson() {
|
||||
return styleJson;
|
||||
}
|
||||
|
||||
public boolean hasOperations() {
|
||||
return getTest().getOperations() != null;
|
||||
}
|
||||
|
||||
public RenderTestStyleDefinition.Test getTest() {
|
||||
return definition.getMetadata().getTest();
|
||||
}
|
||||
|
||||
public MapSnapshotter.Options toOptions() {
|
||||
return new MapSnapshotter
|
||||
.Options(getWidth(), getHeight())
|
||||
.withStyleJson(styleJson)
|
||||
.withPixelRatio(getPixelRatio())
|
||||
.withLogo(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RenderTestDefinition{"
|
||||
+ "category='" + category + '\''
|
||||
+ ", name='" + name + '\''
|
||||
+ ", styleJson='" + styleJson + '\''
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.render;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import com.mapbox.mapboxsdk.snapshotter.MapSnapshot;
|
||||
import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter;
|
||||
|
||||
public class RenderTestSnapshotter extends MapSnapshotter {
|
||||
|
||||
RenderTestSnapshotter(@NonNull Context context, @NonNull Options options) {
|
||||
super(context, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addOverlay(MapSnapshot mapSnapshot) {
|
||||
// don't add an overlay
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.render;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class RenderTestStyleDefinition {
|
||||
|
||||
private Integer version;
|
||||
private Metadata metadata;
|
||||
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
|
||||
|
||||
public Integer getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(Integer version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public Metadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void setMetadata(Metadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public Map<String, Object> getAdditionalProperties() {
|
||||
return this.additionalProperties;
|
||||
}
|
||||
|
||||
public void setAdditionalProperty(String name, Object value) {
|
||||
this.additionalProperties.put(name, value);
|
||||
}
|
||||
|
||||
public class Metadata {
|
||||
|
||||
private Test test;
|
||||
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
|
||||
|
||||
public Test getTest() {
|
||||
return test;
|
||||
}
|
||||
|
||||
public void setTest(Test test) {
|
||||
this.test = test;
|
||||
}
|
||||
|
||||
public Map<String, Object> getAdditionalProperties() {
|
||||
return this.additionalProperties;
|
||||
}
|
||||
|
||||
public void setAdditionalProperty(String name, Object value) {
|
||||
this.additionalProperties.put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public class Test {
|
||||
|
||||
private Integer width;
|
||||
private Integer height;
|
||||
private Float pixelRatio;
|
||||
private List<Integer> center = null;
|
||||
private Integer zoom;
|
||||
private Double diff;
|
||||
private List<List<String>> operations = null;
|
||||
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
|
||||
|
||||
public Integer getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public void setWidth(Integer width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public Integer getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setHeight(Integer height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public Float getPixelRatio() {
|
||||
return pixelRatio;
|
||||
}
|
||||
|
||||
public List<Integer> getCenter() {
|
||||
return center;
|
||||
}
|
||||
|
||||
public void setCenter(List<Integer> center) {
|
||||
this.center = center;
|
||||
}
|
||||
|
||||
public Integer getZoom() {
|
||||
return zoom;
|
||||
}
|
||||
|
||||
public void setZoom(Integer zoom) {
|
||||
this.zoom = zoom;
|
||||
}
|
||||
|
||||
public Double getDiff() {
|
||||
return diff;
|
||||
}
|
||||
|
||||
public void setDiff(Double diff) {
|
||||
this.diff = diff;
|
||||
}
|
||||
|
||||
public List<List<String>> getOperations() {
|
||||
return operations;
|
||||
}
|
||||
|
||||
public void setOperations(List<List<String>> operations) {
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
public Map<String, Object> getAdditionalProperties() {
|
||||
return this.additionalProperties;
|
||||
}
|
||||
|
||||
public void setAdditionalProperty(String name, Object value) {
|
||||
this.additionalProperties.put(name, value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.snapshot;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.GridLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition;
|
||||
import com.mapbox.mapboxsdk.constants.MapboxConstants;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
|
||||
import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Test activity showing how to use a the {@link com.mapbox.mapboxsdk.snapshotter.MapSnapshotter}
|
||||
*/
|
||||
public class MapSnapshotterActivity extends AppCompatActivity {
|
||||
|
||||
private GridLayout grid;
|
||||
private List<MapSnapshotter> snapshotters = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_map_snapshotter);
|
||||
|
||||
// Find the grid view and start snapshotting as soon
|
||||
// as the view is measured
|
||||
grid = findViewById(R.id.snapshot_grid);
|
||||
grid.getViewTreeObserver()
|
||||
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
//noinspection deprecation
|
||||
grid.getViewTreeObserver().removeGlobalOnLayoutListener(this);
|
||||
addSnapshots();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void addSnapshots() {
|
||||
Timber.i("Creating snapshotters");
|
||||
|
||||
for (int row = 0; row < grid.getRowCount(); row++) {
|
||||
for (int column = 0; column < grid.getColumnCount(); column++) {
|
||||
startSnapShot(row, column);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startSnapShot(final int row, final int column) {
|
||||
|
||||
// Define the dimensions
|
||||
MapSnapshotter.Options options = new MapSnapshotter.Options(
|
||||
grid.getMeasuredWidth() / grid.getColumnCount(),
|
||||
grid.getMeasuredHeight() / grid.getRowCount()
|
||||
)
|
||||
// Optionally the pixel ratio
|
||||
.withPixelRatio(1)
|
||||
|
||||
// Optionally the style
|
||||
.withStyle((column + row) % 2 == 0 ? Style.MAPBOX_STREETS : Style.DARK)
|
||||
.withLocalIdeographFontFamily(MapboxConstants.DEFAULT_FONT);
|
||||
|
||||
// Optionally the visible region
|
||||
if (row % 2 == 0) {
|
||||
options.withRegion(new LatLngBounds.Builder()
|
||||
.include(new LatLng(randomInRange(-80, 80), randomInRange(-160, 160)))
|
||||
.include(new LatLng(randomInRange(-80, 80), randomInRange(-160, 160)))
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
// Optionally the camera options
|
||||
if (column % 2 == 0) {
|
||||
options.withCameraPosition(new CameraPosition.Builder()
|
||||
.target(options.getRegion() != null
|
||||
? options.getRegion().getCenter()
|
||||
: new LatLng(randomInRange(-80, 80), randomInRange(-160, 160)))
|
||||
.bearing(randomInRange(0, 360))
|
||||
.tilt(randomInRange(0, 60))
|
||||
.zoom(randomInRange(0, 20))
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
MapSnapshotter snapshotter = new MapSnapshotter(MapSnapshotterActivity.this, options);
|
||||
|
||||
snapshotter.start(snapshot -> {
|
||||
Timber.i("Got the snapshot");
|
||||
ImageView imageView = new ImageView(MapSnapshotterActivity.this);
|
||||
imageView.setImageBitmap(snapshot.getBitmap());
|
||||
grid.addView(
|
||||
imageView,
|
||||
new GridLayout.LayoutParams(GridLayout.spec(row), GridLayout.spec(column))
|
||||
);
|
||||
});
|
||||
snapshotters.add(snapshotter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
// Make sure to stop the snapshotters on pause
|
||||
for (MapSnapshotter snapshotter : snapshotters) {
|
||||
snapshotter.cancel();
|
||||
}
|
||||
snapshotters.clear();
|
||||
}
|
||||
|
||||
private static Random random = new Random();
|
||||
|
||||
public static float randomInRange(float min, float max) {
|
||||
return (random.nextFloat() * (max - min)) + min;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.snapshot;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.ImageView;
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.snapshotter.MapSnapshot;
|
||||
import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Test activity showing how to use a the MapSnapshotter with a local style
|
||||
*/
|
||||
public class MapSnapshotterLocalStyleActivity extends AppCompatActivity
|
||||
implements MapSnapshotter.SnapshotReadyCallback {
|
||||
|
||||
private MapSnapshotter mapSnapshotter;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_map_snapshotter_marker);
|
||||
|
||||
final View container = findViewById(R.id.container);
|
||||
container.getViewTreeObserver()
|
||||
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
//noinspection deprecation
|
||||
container.getViewTreeObserver().removeGlobalOnLayoutListener(this);
|
||||
|
||||
String styleJson;
|
||||
try {
|
||||
styleJson = ResourceUtils.readRawResource(MapSnapshotterLocalStyleActivity.this, R.raw.sat_style);
|
||||
} catch (IOException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
|
||||
Timber.i("Starting snapshot");
|
||||
mapSnapshotter = new MapSnapshotter(
|
||||
getApplicationContext(),
|
||||
new MapSnapshotter
|
||||
.Options(Math.min(container.getMeasuredWidth(), 1024), Math.min(container.getMeasuredHeight(), 1024))
|
||||
.withStyleJson(styleJson)
|
||||
.withCameraPosition(new CameraPosition.Builder().target(new LatLng(52.090737, 5.121420)).zoom(18).build())
|
||||
);
|
||||
mapSnapshotter.start(MapSnapshotterLocalStyleActivity.this, error -> Timber.e(error));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapSnapshotter.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSnapshotReady(MapSnapshot snapshot) {
|
||||
Timber.i("Snapshot ready");
|
||||
ImageView imageView = (ImageView) findViewById(R.id.snapshot_image);
|
||||
imageView.setImageBitmap(snapshot.getBitmap());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.snapshot;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PointF;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.ImageView;
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.snapshotter.MapSnapshot;
|
||||
import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Test activity showing how to use a the {@link MapSnapshotter} and overlay
|
||||
* {@link android.graphics.Bitmap}s on top.
|
||||
*/
|
||||
public class MapSnapshotterMarkerActivity extends AppCompatActivity implements MapSnapshotter.SnapshotReadyCallback {
|
||||
|
||||
private MapSnapshotter mapSnapshotter;
|
||||
private MapSnapshot mapSnapshot;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_map_snapshotter_marker);
|
||||
|
||||
final View container = findViewById(R.id.container);
|
||||
container.getViewTreeObserver()
|
||||
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
//noinspection deprecation
|
||||
container.getViewTreeObserver().removeGlobalOnLayoutListener(this);
|
||||
|
||||
Timber.i("Starting snapshot");
|
||||
|
||||
mapSnapshotter = new MapSnapshotter(
|
||||
getApplicationContext(),
|
||||
new MapSnapshotter
|
||||
.Options(Math.min(container.getMeasuredWidth(), 1024), Math.min(container.getMeasuredHeight(), 1024))
|
||||
.withStyle(Style.OUTDOORS)
|
||||
.withCameraPosition(new CameraPosition.Builder().target(new LatLng(52.090737, 5.121420)).zoom(15).build())
|
||||
);
|
||||
mapSnapshotter.start(MapSnapshotterMarkerActivity.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapSnapshotter.cancel();
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public void onSnapshotReady(MapSnapshot snapshot) {
|
||||
this.mapSnapshot = snapshot;
|
||||
Timber.i("Snapshot ready");
|
||||
ImageView imageView = (ImageView) findViewById(R.id.snapshot_image);
|
||||
Bitmap image = addMarker(snapshot);
|
||||
imageView.setImageBitmap(image);
|
||||
imageView.setOnTouchListener((v, event) -> {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
LatLng latLng = snapshot.latLngForPixel(new PointF(event.getX(), event.getY()));
|
||||
Timber.e("Clicked LatLng is %s", latLng);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
private Bitmap addMarker(MapSnapshot snapshot) {
|
||||
Canvas canvas = new Canvas(snapshot.getBitmap());
|
||||
Bitmap marker = BitmapFactory.decodeResource(getResources(), R.drawable.mapbox_marker_icon_default, null);
|
||||
// Dom toren
|
||||
PointF markerLocation = snapshot.pixelForLatLng(new LatLng(52.090649433011315, 5.121310651302338));
|
||||
canvas.drawBitmap(marker,
|
||||
/* Subtract half of the width so we center the bitmap correctly */
|
||||
markerLocation.x - marker.getWidth() / 2,
|
||||
/* Subtract half of the height so we align the bitmap bottom correctly */
|
||||
markerLocation.y - marker.getHeight() / 2,
|
||||
null
|
||||
);
|
||||
return snapshot.getBitmap();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@Nullable
|
||||
public MapSnapshot getMapSnapshot() {
|
||||
return mapSnapshot;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.snapshot;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
|
||||
import com.mapbox.mapboxsdk.snapshotter.MapSnapshot;
|
||||
import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Test activity showing how to use a the {@link MapSnapshotter}
|
||||
*/
|
||||
public class MapSnapshotterReuseActivity extends AppCompatActivity implements MapSnapshotter.SnapshotReadyCallback {
|
||||
|
||||
private MapSnapshotter mapSnapshotter;
|
||||
private View fab;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_map_snapshotter_reuse);
|
||||
|
||||
fab = findViewById(R.id.fab);
|
||||
fab.setVisibility(View.INVISIBLE);
|
||||
fab.setOnClickListener(v -> {
|
||||
fab.setVisibility(View.INVISIBLE);
|
||||
|
||||
mapSnapshotter.setStyleUrl(getRandomStyle());
|
||||
if (random.nextInt(2) == 0) {
|
||||
mapSnapshotter.setCameraPosition(getRandomCameraPosition());
|
||||
} else {
|
||||
mapSnapshotter.setRegion(getRandomBounds());
|
||||
}
|
||||
if (random.nextInt(2) == 0) {
|
||||
mapSnapshotter.setSize(512, 512);
|
||||
} else {
|
||||
mapSnapshotter.setSize(256, 256);
|
||||
}
|
||||
mapSnapshotter.start(MapSnapshotterReuseActivity.this);
|
||||
});
|
||||
|
||||
mapSnapshotter = new MapSnapshotter(
|
||||
getApplicationContext(),
|
||||
new MapSnapshotter.Options(512, 512)
|
||||
);
|
||||
|
||||
mapSnapshotter.start(MapSnapshotterReuseActivity.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSnapshotReady(MapSnapshot snapshot) {
|
||||
fab.setVisibility(View.VISIBLE);
|
||||
ImageView imageView = findViewById(R.id.snapshot_image);
|
||||
imageView.setImageBitmap(snapshot.getBitmap());
|
||||
}
|
||||
|
||||
private LatLngBounds getRandomBounds() {
|
||||
return new LatLngBounds.Builder()
|
||||
.include(new LatLng(randomInRange(5, 10), randomInRange(-5, 5)))
|
||||
.include(new LatLng(randomInRange(-5, 5), randomInRange(5, 10)))
|
||||
.build();
|
||||
}
|
||||
|
||||
private CameraPosition getRandomCameraPosition() {
|
||||
return new CameraPosition.Builder()
|
||||
.target(new LatLng(randomInRange(-80, 80), randomInRange(-160, 160)))
|
||||
.zoom(randomInRange(2, 10))
|
||||
.bearing(randomInRange(0, 90))
|
||||
.build();
|
||||
}
|
||||
|
||||
public String getRandomStyle() {
|
||||
switch (random.nextInt(5)) {
|
||||
case 0:
|
||||
return Style.DARK;
|
||||
case 1:
|
||||
return Style.LIGHT;
|
||||
case 2:
|
||||
return Style.MAPBOX_STREETS;
|
||||
case 3:
|
||||
return Style.OUTDOORS;
|
||||
case 4:
|
||||
return Style.SATELLITE_STREETS;
|
||||
default:
|
||||
return Style.TRAFFIC_DAY;
|
||||
}
|
||||
}
|
||||
|
||||
private static Random random = new Random();
|
||||
|
||||
public static float randomInRange(float min, float max) {
|
||||
return (random.nextFloat() * (max - min)) + min;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.storage
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Looper
|
||||
import android.support.design.widget.Snackbar
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import com.mapbox.mapboxsdk.offline.OfflineManager
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import kotlinx.android.synthetic.main.activity_cache_management.*
|
||||
|
||||
/**
|
||||
* Test activity showcasing the cache management APIs
|
||||
*/
|
||||
class CacheManagementActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_cache_management)
|
||||
|
||||
val fileSource = OfflineManager.getInstance(this)
|
||||
resetDatabaseButton.setOnClickListener {
|
||||
fileSource.resetDatabase(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
showSnackbar("Reset database success")
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
showSnackbar("Reset database fail: $message")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
invalidateAmbientCacheButton.setOnClickListener {
|
||||
fileSource.invalidateAmbientCache(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
showSnackbar("Invalidate ambient cache success")
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
showSnackbar("Invalidate ambient cache fail: $message")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
clearAmbientCacheButton.setOnClickListener {
|
||||
fileSource.clearAmbientCache(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
showSnackbar("Clear ambient cache success")
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
showSnackbar("Clear ambient cache fail: $message")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
setMaximumAmbientCacheSizeButton.setOnClickListener {
|
||||
fileSource.setMaximumAmbientCacheSize(5000000, object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
showSnackbar("Set maximum ambient cache size success")
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
showSnackbar("Set maximum ambient cache size fail: $message")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun showSnackbar(message: String) {
|
||||
// validate that all callbacks occur on main thread
|
||||
assert(Looper.myLooper() == Looper.getMainLooper())
|
||||
|
||||
// show snackbar
|
||||
Snackbar.make(container, message, Snackbar.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.storage;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.storage.FileSource;
|
||||
import com.mapbox.mapboxsdk.storage.Resource;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Test activity showcasing the url transform
|
||||
*/
|
||||
public class UrlTransformActivity extends AppCompatActivity {
|
||||
|
||||
private MapView mapView;
|
||||
|
||||
/**
|
||||
* Be sure to use an isolated class so the activity is not leaked when
|
||||
* the activity goes out of scope (static class in this case).
|
||||
* <p>
|
||||
* Alternatively, unregister the callback in {@link Activity#onDestroy()}
|
||||
*/
|
||||
private static final class Transform implements FileSource.ResourceTransformCallback {
|
||||
@Override
|
||||
public String onURL(@Resource.Kind int kind, String url) {
|
||||
Timber.i("[%s] Could be rewriting %s", Thread.currentThread().getName(), url);
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_data_driven_style);
|
||||
|
||||
// Initialize map as normal
|
||||
mapView = (MapView) findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
|
||||
// Get a handle to the file source and set the resource transform
|
||||
FileSource.getInstance(UrlTransformActivity.this).setResourceTransform(new Transform());
|
||||
|
||||
mapView.getMapAsync(map -> {
|
||||
Timber.i("Map loaded");
|
||||
map.setStyle(Style.MAPBOX_STREETS);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
// Example of how to reset the transform callback
|
||||
FileSource.getInstance(UrlTransformActivity.this).setResourceTransform(null);
|
||||
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.style;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import com.mapbox.mapboxsdk.Mapbox;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLngQuad;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.style.layers.RasterLayer;
|
||||
import com.mapbox.mapboxsdk.style.sources.ImageSource;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.utils.BitmapUtils;
|
||||
|
||||
/**
|
||||
* Test activity showing how to use a series of images to create an animation
|
||||
* with an ImageSource
|
||||
* <p>
|
||||
* GL-native equivalent of https://www.mapbox.com/mapbox-gl-js/example/animate-images/
|
||||
* </p>
|
||||
*/
|
||||
public class AnimatedImageSourceActivity extends AppCompatActivity implements OnMapReadyCallback {
|
||||
|
||||
private static final String ID_IMAGE_SOURCE = "animated_image_source";
|
||||
private static final String ID_IMAGE_LAYER = "animated_image_layer";
|
||||
|
||||
private MapView mapView;
|
||||
private final Handler handler = new Handler();
|
||||
private Runnable runnable;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_animated_image_source);
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapReady(@NonNull final MapboxMap map) {
|
||||
LatLngQuad quad = new LatLngQuad(
|
||||
new LatLng(46.437, -80.425),
|
||||
new LatLng(46.437, -71.516),
|
||||
new LatLng(37.936, -71.516),
|
||||
new LatLng(37.936, -80.425));
|
||||
|
||||
final ImageSource imageSource = new ImageSource(ID_IMAGE_SOURCE, quad, R.drawable.southeast_radar_0);
|
||||
final RasterLayer layer = new RasterLayer(ID_IMAGE_LAYER, ID_IMAGE_SOURCE);
|
||||
map.setStyle(new Style.Builder()
|
||||
.fromUri(Style.MAPBOX_STREETS)
|
||||
.withSource(imageSource)
|
||||
.withLayer(layer), style -> {
|
||||
runnable = new RefreshImageRunnable(imageSource, handler);
|
||||
handler.postDelayed(runnable, 100);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
handler.removeCallbacks(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
private static class RefreshImageRunnable implements Runnable {
|
||||
|
||||
private ImageSource imageSource;
|
||||
private Handler handler;
|
||||
private Bitmap[] drawables;
|
||||
private int drawableIndex;
|
||||
|
||||
Bitmap getBitmap(int resourceId) {
|
||||
Context context = Mapbox.getApplicationContext();
|
||||
Drawable drawable = BitmapUtils.getDrawableFromRes(context, resourceId);
|
||||
if (drawable instanceof BitmapDrawable) {
|
||||
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
|
||||
return bitmapDrawable.getBitmap();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
RefreshImageRunnable(ImageSource imageSource, Handler handler) {
|
||||
this.imageSource = imageSource;
|
||||
this.handler = handler;
|
||||
drawables = new Bitmap[4];
|
||||
drawables[0] = getBitmap(R.drawable.southeast_radar_0);
|
||||
drawables[1] = getBitmap(R.drawable.southeast_radar_1);
|
||||
drawables[2] = getBitmap(R.drawable.southeast_radar_2);
|
||||
drawables[3] = getBitmap(R.drawable.southeast_radar_3);
|
||||
drawableIndex = 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
imageSource.setImage(drawables[drawableIndex++]);
|
||||
if (drawableIndex > 3) {
|
||||
drawableIndex = 0;
|
||||
}
|
||||
handler.postDelayed(this, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.style;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.style.expressions.Expression;
|
||||
import com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer;
|
||||
import com.mapbox.mapboxsdk.style.layers.Property;
|
||||
import com.mapbox.mapboxsdk.style.light.Light;
|
||||
import com.mapbox.mapboxsdk.style.light.Position;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.utils.ColorUtils;
|
||||
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionBase;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionColor;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionHeight;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionOpacity;
|
||||
|
||||
/**
|
||||
* Test activity showing 3D buildings with a FillExtrusion Layer
|
||||
*/
|
||||
public class BuildingFillExtrusionActivity extends AppCompatActivity {
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private Light light;
|
||||
|
||||
private boolean isMapAnchorLight;
|
||||
private boolean isLowIntensityLight;
|
||||
private boolean isRedColor;
|
||||
private boolean isInitPosition;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_building_layer);
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(map -> {
|
||||
mapboxMap = map;
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS, style -> {
|
||||
setupBuildings(style);
|
||||
setupLight();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void setupBuildings(Style style) {
|
||||
FillExtrusionLayer fillExtrusionLayer = new FillExtrusionLayer("3d-buildings", "composite");
|
||||
fillExtrusionLayer.setSourceLayer("building");
|
||||
fillExtrusionLayer.setFilter(eq(get("extrude"), literal("true")));
|
||||
fillExtrusionLayer.setMinZoom(15);
|
||||
fillExtrusionLayer.setProperties(
|
||||
fillExtrusionColor(Color.LTGRAY),
|
||||
fillExtrusionHeight(Expression.get("height")),
|
||||
fillExtrusionBase(Expression.get("min_height")),
|
||||
fillExtrusionOpacity(0.9f)
|
||||
);
|
||||
style.addLayer(fillExtrusionLayer);
|
||||
}
|
||||
|
||||
private void setupLight() {
|
||||
light = mapboxMap.getStyle().getLight();
|
||||
|
||||
findViewById(R.id.fabLightPosition).setOnClickListener(v -> {
|
||||
isInitPosition = !isInitPosition;
|
||||
if (isInitPosition) {
|
||||
light.setPosition(new Position(1.5f, 90, 80));
|
||||
} else {
|
||||
light.setPosition(new Position(1.15f, 210, 30));
|
||||
}
|
||||
});
|
||||
|
||||
findViewById(R.id.fabLightColor).setOnClickListener(v -> {
|
||||
isRedColor = !isRedColor;
|
||||
light.setColor(ColorUtils.colorToRgbaString(isRedColor ? Color.RED : Color.BLUE));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_building, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (light != null) {
|
||||
int id = item.getItemId();
|
||||
if (id == R.id.menu_action_anchor) {
|
||||
isMapAnchorLight = !isMapAnchorLight;
|
||||
light.setAnchor(isMapAnchorLight ? Property.ANCHOR_MAP : Property.ANCHOR_VIEWPORT);
|
||||
} else if (id == R.id.menu_action_intensity) {
|
||||
isLowIntensityLight = !isLowIntensityLight;
|
||||
light.setIntensity(isLowIntensityLight ? 0.35f : 1.0f);
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.style;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.content.res.ResourcesCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.style.expressions.Expression;
|
||||
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
|
||||
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
|
||||
import com.mapbox.mapboxsdk.style.sources.GeoJsonOptions;
|
||||
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.all;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.gt;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.gte;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.has;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.lt;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.toNumber;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleColor;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleRadius;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAllowOverlap;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textColor;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textField;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textIgnorePlacement;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textSize;
|
||||
|
||||
|
||||
/**
|
||||
* Test activity showcasing adding a Circle Layer to the Map
|
||||
* <p>
|
||||
* Uses bus stop data from Singapore as a source and allows to filter into 1 specific route with a line layer.
|
||||
* </p>
|
||||
*/
|
||||
public class CircleLayerActivity extends AppCompatActivity implements View.OnClickListener {
|
||||
|
||||
public static final String SOURCE_ID = "bus_stop";
|
||||
public static final String SOURCE_ID_CLUSTER = "bus_stop_cluster";
|
||||
public static final String URL_BUS_ROUTES = "https://raw.githubusercontent.com/cheeaun/busrouter-sg/master/data/2/bus-stops.geojson";
|
||||
public static final String LAYER_ID = "stops_layer";
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
|
||||
private FloatingActionButton styleFab;
|
||||
private FloatingActionButton routeFab;
|
||||
|
||||
private CircleLayer layer;
|
||||
private GeoJsonSource source;
|
||||
|
||||
private int currentStyleIndex = 0;
|
||||
private boolean isLoadingStyle = true;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_circle_layer);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(map -> {
|
||||
mapboxMap = map;
|
||||
mapboxMap.setStyle(Style.SATELLITE_STREETS);
|
||||
mapView.addOnDidFinishLoadingStyleListener(() -> {
|
||||
Style style = mapboxMap.getStyle();
|
||||
addBusStopSource(style);
|
||||
addBusStopCircleLayer(style);
|
||||
initFloatingActionButtons();
|
||||
isLoadingStyle = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void addBusStopSource(Style style) {
|
||||
try {
|
||||
source = new GeoJsonSource(SOURCE_ID, new URI(URL_BUS_ROUTES));
|
||||
} catch (URISyntaxException exception) {
|
||||
Timber.e(exception, "That's not an url... ");
|
||||
}
|
||||
style.addSource(source);
|
||||
}
|
||||
|
||||
private void addBusStopCircleLayer(Style style) {
|
||||
layer = new CircleLayer(LAYER_ID, SOURCE_ID);
|
||||
layer.setProperties(
|
||||
circleColor(Color.parseColor("#FF9800")),
|
||||
circleRadius(2.0f)
|
||||
);
|
||||
style.addLayerBelow(layer, "waterway-label");
|
||||
}
|
||||
|
||||
private void initFloatingActionButtons() {
|
||||
routeFab = findViewById(R.id.fab_route);
|
||||
routeFab.setColorFilter(ContextCompat.getColor(CircleLayerActivity.this, R.color.primary));
|
||||
routeFab.setOnClickListener(CircleLayerActivity.this);
|
||||
|
||||
styleFab = findViewById(R.id.fab_style);
|
||||
styleFab.setOnClickListener(CircleLayerActivity.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (isLoadingStyle) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (view.getId() == R.id.fab_route) {
|
||||
showBusCluster();
|
||||
} else if (view.getId() == R.id.fab_style) {
|
||||
changeMapStyle();
|
||||
}
|
||||
}
|
||||
|
||||
private void showBusCluster() {
|
||||
removeFabs();
|
||||
removeOldSource();
|
||||
addClusteredSource();
|
||||
}
|
||||
|
||||
private void removeOldSource() {
|
||||
mapboxMap.getStyle().removeSource(SOURCE_ID);
|
||||
mapboxMap.getStyle().removeLayer(LAYER_ID);
|
||||
}
|
||||
|
||||
private void addClusteredSource() {
|
||||
try {
|
||||
mapboxMap.getStyle().addSource(
|
||||
new GeoJsonSource(SOURCE_ID_CLUSTER,
|
||||
new URI(URL_BUS_ROUTES),
|
||||
new GeoJsonOptions()
|
||||
.withCluster(true)
|
||||
.withClusterMaxZoom(14)
|
||||
.withClusterRadius(50)
|
||||
)
|
||||
);
|
||||
} catch (URISyntaxException malformedUrlException) {
|
||||
Timber.e(malformedUrlException, "That's not an url... ");
|
||||
}
|
||||
|
||||
// Add unclustered layer
|
||||
int[][] layers = new int[][] {
|
||||
new int[] {150, ResourcesCompat.getColor(getResources(), R.color.redAccent, getTheme())},
|
||||
new int[] {20, ResourcesCompat.getColor(getResources(), R.color.greenAccent, getTheme())},
|
||||
new int[] {0, ResourcesCompat.getColor(getResources(), R.color.blueAccent, getTheme())}
|
||||
};
|
||||
|
||||
SymbolLayer unclustered = new SymbolLayer("unclustered-points", SOURCE_ID_CLUSTER);
|
||||
unclustered.setProperties(
|
||||
iconImage("bus-15")
|
||||
);
|
||||
|
||||
mapboxMap.getStyle().addLayer(unclustered);
|
||||
|
||||
for (int i = 0; i < layers.length; i++) {
|
||||
// Add some nice circles
|
||||
CircleLayer circles = new CircleLayer("cluster-" + i, SOURCE_ID_CLUSTER);
|
||||
circles.setProperties(
|
||||
circleColor(layers[i][1]),
|
||||
circleRadius(18f)
|
||||
);
|
||||
|
||||
Expression pointCount = toNumber(get("point_count"));
|
||||
circles.setFilter(
|
||||
i == 0
|
||||
? all(has("point_count"),
|
||||
gte(pointCount, literal(layers[i][0]))
|
||||
) : all(has("point_count"),
|
||||
gt(pointCount, literal(layers[i][0])),
|
||||
lt(pointCount, literal(layers[i - 1][0]))
|
||||
)
|
||||
);
|
||||
mapboxMap.getStyle().addLayer(circles);
|
||||
}
|
||||
|
||||
// Add the count labels
|
||||
SymbolLayer count = new SymbolLayer("count", SOURCE_ID_CLUSTER);
|
||||
count.setProperties(
|
||||
textField(Expression.toString(get("point_count"))),
|
||||
textSize(12f),
|
||||
textColor(Color.WHITE),
|
||||
textIgnorePlacement(true),
|
||||
textAllowOverlap(true)
|
||||
);
|
||||
mapboxMap.getStyle().addLayer(count);
|
||||
}
|
||||
|
||||
private void removeFabs() {
|
||||
routeFab.setVisibility(View.GONE);
|
||||
styleFab.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private void changeMapStyle() {
|
||||
isLoadingStyle = true;
|
||||
removeBusStop();
|
||||
loadNewStyle();
|
||||
}
|
||||
|
||||
private void removeBusStop() {
|
||||
mapboxMap.getStyle().removeLayer(layer);
|
||||
mapboxMap.getStyle().removeSource(source);
|
||||
}
|
||||
|
||||
private void loadNewStyle() {
|
||||
mapboxMap.setStyle(new Style.Builder().fromUri(getNextStyle()));
|
||||
}
|
||||
|
||||
private void addBusStop() {
|
||||
mapboxMap.getStyle().addLayer(layer);
|
||||
mapboxMap.getStyle().addSource(source);
|
||||
}
|
||||
|
||||
private String getNextStyle() {
|
||||
currentStyleIndex++;
|
||||
if (currentStyleIndex == Data.STYLES.length) {
|
||||
currentStyleIndex = 0;
|
||||
}
|
||||
return Data.STYLES[currentStyleIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
private static class Data {
|
||||
private static final String[] STYLES = new String[] {
|
||||
Style.MAPBOX_STREETS,
|
||||
Style.OUTDOORS,
|
||||
Style.LIGHT,
|
||||
Style.DARK,
|
||||
Style.SATELLITE,
|
||||
Style.SATELLITE_STREETS
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.style;
|
||||
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
|
||||
import com.mapbox.geojson.Feature;
|
||||
import com.mapbox.geojson.FeatureCollection;
|
||||
import com.mapbox.geojson.Point;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.style.layers.Layer;
|
||||
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
|
||||
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
|
||||
|
||||
/**
|
||||
* Test activity showcasing adding a sprite image and use it in a Symbol Layer
|
||||
*/
|
||||
public class CustomSpriteActivity extends AppCompatActivity {
|
||||
|
||||
private static final String CUSTOM_ICON = "custom-icon";
|
||||
|
||||
private GeoJsonSource source;
|
||||
private MapboxMap mapboxMap;
|
||||
private MapView mapView;
|
||||
private Layer layer;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_add_sprite);
|
||||
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(map -> {
|
||||
mapboxMap = map;
|
||||
|
||||
map.setStyle(Style.MAPBOX_STREETS, style -> {
|
||||
final FloatingActionButton fab = findViewById(R.id.fab);
|
||||
fab.setColorFilter(ContextCompat.getColor(CustomSpriteActivity.this, R.color.primary));
|
||||
fab.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
private Point point;
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (point == null) {
|
||||
Timber.i("First click -> Car");
|
||||
// Add an icon to reference later
|
||||
style.addImage(CUSTOM_ICON, BitmapFactory.decodeResource(getResources(), R.drawable.ic_car_top));
|
||||
|
||||
// Add a source with a geojson point
|
||||
point = Point.fromLngLat(13.400972d, 52.519003d);
|
||||
source = new GeoJsonSource(
|
||||
"point",
|
||||
FeatureCollection.fromFeatures(new Feature[] {Feature.fromGeometry(point)})
|
||||
);
|
||||
mapboxMap.getStyle().addSource(source);
|
||||
|
||||
// Add a symbol layer that references that point source
|
||||
layer = new SymbolLayer("layer", "point");
|
||||
layer.setProperties(
|
||||
// Set the id of the sprite to use
|
||||
iconImage(CUSTOM_ICON),
|
||||
iconAllowOverlap(true),
|
||||
iconIgnorePlacement(true)
|
||||
);
|
||||
|
||||
// lets add a circle below labels!
|
||||
mapboxMap.getStyle().addLayerBelow(layer, "waterway-label");
|
||||
|
||||
fab.setImageResource(R.drawable.ic_directions_car_black);
|
||||
} else {
|
||||
// Update point
|
||||
point = Point.fromLngLat(point.longitude() + 0.001,
|
||||
point.latitude() + 0.001);
|
||||
source.setGeoJson(FeatureCollection.fromFeatures(new Feature[] {Feature.fromGeometry(point)}));
|
||||
|
||||
// Move the camera as well
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(
|
||||
point.latitude(), point.longitude())));
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,472 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.style;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.Style;
|
||||
import com.mapbox.mapboxsdk.style.layers.FillLayer;
|
||||
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
|
||||
import com.mapbox.mapboxsdk.style.sources.Source;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.IdleZoomListener;
|
||||
import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.exponential;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.linear;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.match;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.rgb;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.rgba;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.step;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.stop;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.zoom;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.color;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillAntialias;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillColor;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillOpacity;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillOutlineColor;
|
||||
|
||||
/**
|
||||
* Test activity showcasing the data driven runtime style API.
|
||||
*/
|
||||
public class DataDrivenStyleActivity extends AppCompatActivity {
|
||||
|
||||
public static final String AMSTERDAM_PARKS_LAYER = "amsterdam-parks-layer";
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private IdleZoomListener idleListener;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_data_driven_style);
|
||||
|
||||
// Initialize map as normal
|
||||
mapView = findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
|
||||
mapView.getMapAsync(map -> {
|
||||
// Store for later
|
||||
mapboxMap = map;
|
||||
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS, style -> {
|
||||
// Add a parks layer
|
||||
addParksLayer();
|
||||
|
||||
// Add debug overlay
|
||||
setupDebugZoomView();
|
||||
});
|
||||
|
||||
// Center and Zoom (Amsterdam, zoomed to streets)
|
||||
mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.379189, 4.899431), 14));
|
||||
});
|
||||
}
|
||||
|
||||
private void setupDebugZoomView() {
|
||||
final TextView textView = (TextView) findViewById(R.id.textZoom);
|
||||
mapboxMap.addOnCameraIdleListener(idleListener = new IdleZoomListener(mapboxMap, textView));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_data_driven_style, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mapboxMap != null && idleListener != null) {
|
||||
mapboxMap.removeOnCameraIdleListener(idleListener);
|
||||
}
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_add_exponential_zoom_function:
|
||||
addExponentialZoomFunction();
|
||||
return true;
|
||||
case R.id.action_add_interval_zoom_function:
|
||||
addIntervalZoomFunction();
|
||||
return true;
|
||||
case R.id.action_add_categorical_source_function:
|
||||
addCategoricalSourceFunction();
|
||||
return true;
|
||||
case R.id.action_add_exponential_source_function:
|
||||
addExponentialSourceFunction();
|
||||
return true;
|
||||
case R.id.action_add_identity_source_function:
|
||||
addIdentitySourceFunction();
|
||||
return true;
|
||||
case R.id.action_add_interval_source_function:
|
||||
addIntervalSourceFunction();
|
||||
return true;
|
||||
case R.id.action_add_composite_categorical_function:
|
||||
addCompositeCategoricalFunction();
|
||||
return true;
|
||||
case R.id.action_add_composite_exponential_function:
|
||||
addCompositeExponentialFunction();
|
||||
return true;
|
||||
case R.id.action_add_composite_interval_function:
|
||||
addCompositeIntervalFunction();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void addExponentialZoomFunction() {
|
||||
Timber.i("Add exponential zoom function");
|
||||
FillLayer layer = mapboxMap.getStyle().getLayerAs("water");
|
||||
assert layer != null;
|
||||
layer.setProperties(
|
||||
fillColor(
|
||||
interpolate(
|
||||
exponential(0.5f), zoom(),
|
||||
stop(1, color(Color.RED)),
|
||||
stop(5, color(Color.BLUE)),
|
||||
stop(10, color(Color.GREEN))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
Timber.i("Fill color: %s", layer.getFillColor());
|
||||
}
|
||||
|
||||
private void addIntervalZoomFunction() {
|
||||
Timber.i("Add interval zoom function");
|
||||
FillLayer layer = mapboxMap.getStyle().getLayerAs("water");
|
||||
assert layer != null;
|
||||
layer.setProperties(
|
||||
fillColor(
|
||||
step(zoom(),
|
||||
rgba(0.0f, 255.0f, 255.0f, 1.0f),
|
||||
stop(1, rgba(255.0f, 0.0f, 0.0f, 1.0f)),
|
||||
stop(5, rgba(0.0f, 0.0f, 255.0f, 1.0f)),
|
||||
stop(10, rgba(0.0f, 255.0f, 0.0f, 1.0f))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
Timber.i("Fill color: %s", layer.getFillColor());
|
||||
}
|
||||
|
||||
private void addExponentialSourceFunction() {
|
||||
Timber.i("Add exponential source function");
|
||||
FillLayer layer = mapboxMap.getStyle().getLayerAs(AMSTERDAM_PARKS_LAYER);
|
||||
assert layer != null;
|
||||
layer.setProperties(
|
||||
fillColor(
|
||||
interpolate(
|
||||
exponential(0.5f),
|
||||
get("stroke-width"),
|
||||
stop(1f, rgba(255.0f, 0.0f, 0.0f, 1.0f)),
|
||||
stop(5f, rgba(0.0f, 0.0f, 255.0f, 1.0f)),
|
||||
stop(10f, rgba(0.0f, 255.0f, 0.0f, 1.0f))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
Timber.i("Fill color: %s", layer.getFillColor());
|
||||
}
|
||||
|
||||
private void addCategoricalSourceFunction() {
|
||||
Timber.i("Add categorical source function");
|
||||
FillLayer layer = mapboxMap.getStyle().getLayerAs(AMSTERDAM_PARKS_LAYER);
|
||||
assert layer != null;
|
||||
layer.setProperties(
|
||||
fillColor(
|
||||
match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
|
||||
literal("Jordaan"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
|
||||
literal("Prinseneiland"), rgba(0.0f, 255.0f, 0.0f, 1.0f),
|
||||
rgba(0.0f, 255.0f, 255.0f, 1.0f)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
Timber.i("Fill color: %s", layer.getFillColor());
|
||||
}
|
||||
|
||||
private void addIdentitySourceFunction() {
|
||||
Timber.i("Add identity source function");
|
||||
FillLayer layer = mapboxMap.getStyle().getLayerAs(AMSTERDAM_PARKS_LAYER);
|
||||
assert layer != null;
|
||||
layer.setProperties(
|
||||
fillOpacity(
|
||||
get("fill-opacity")
|
||||
)
|
||||
);
|
||||
|
||||
Timber.i("Fill opacity: %s", layer.getFillOpacity());
|
||||
}
|
||||
|
||||
private void addIntervalSourceFunction() {
|
||||
Timber.i("Add interval source function");
|
||||
FillLayer layer = mapboxMap.getStyle().getLayerAs(AMSTERDAM_PARKS_LAYER);
|
||||
assert layer != null;
|
||||
layer.setProperties(
|
||||
fillColor(
|
||||
step(
|
||||
get("stroke-width"),
|
||||
rgba(0.0f, 255.0f, 255.0f, 1.0f),
|
||||
stop(1f, rgba(255.0f, 0.0f, 0.0f, 1.0f)),
|
||||
stop(2f, rgba(0.0f, 0.0f, 255.0f, 1.0f)),
|
||||
stop(3f, rgba(0.0f, 255.0f, 0.0f, 1.0f))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
Timber.i("Fill color: %s", layer.getFillColor());
|
||||
}
|
||||
|
||||
private void addCompositeExponentialFunction() {
|
||||
Timber.i("Add composite exponential function");
|
||||
FillLayer layer = mapboxMap.getStyle().getLayerAs(AMSTERDAM_PARKS_LAYER);
|
||||
assert layer != null;
|
||||
layer.setProperties(
|
||||
fillColor(
|
||||
interpolate(
|
||||
exponential(1f),
|
||||
zoom(),
|
||||
stop(12, step(
|
||||
get("stroke-width"),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f),
|
||||
stop(1f, rgba(255.0f, 0.0f, 0.0f, 1.0f)),
|
||||
stop(2f, rgba(0.0f, 0.0f, 0.0f, 1.0f)),
|
||||
stop(3f, rgba(0.0f, 0.0f, 255.0f, 1.0f))
|
||||
)),
|
||||
stop(15, step(
|
||||
get("stroke-width"),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f),
|
||||
stop(1f, rgba(255.0f, 255.0f, 0.0f, 1.0f)),
|
||||
stop(2f, rgba(211.0f, 211.0f, 211.0f, 1.0f)),
|
||||
stop(3f, rgba(0.0f, 255.0f, 255.0f, 1.0f))
|
||||
)),
|
||||
stop(18, step(
|
||||
get("stroke-width"),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f),
|
||||
stop(1f, rgba(0.0f, 0.0f, 0.0f, 1.0f)),
|
||||
stop(2f, rgba(128.0f, 128.0f, 128.0f, 1.0f)),
|
||||
stop(3f, rgba(0.0f, 255.0f, 0.0f, 1.0f)))
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
Timber.i("Fill color: %s", layer.getFillColor());
|
||||
}
|
||||
|
||||
private void addCompositeIntervalFunction() {
|
||||
Timber.i("Add composite interval function");
|
||||
FillLayer layer = mapboxMap.getStyle().getLayerAs(AMSTERDAM_PARKS_LAYER);
|
||||
assert layer != null;
|
||||
layer.setProperties(
|
||||
fillColor(
|
||||
interpolate(
|
||||
linear(),
|
||||
zoom(),
|
||||
stop(12, step(
|
||||
get("stroke-width"),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f),
|
||||
stop(1f, rgba(255.0f, 0.0f, 0.0f, 1.0f)),
|
||||
stop(2f, rgba(0.0f, 0.0f, 0.0f, 1.0f)),
|
||||
stop(3f, rgba(0.0f, 0.0f, 255.0f, 1.0f))
|
||||
)),
|
||||
stop(15, step(
|
||||
get("stroke-width"),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f),
|
||||
stop(1f, rgba(255.0f, 255.0f, 0.0f, 1.0f)),
|
||||
stop(2f, rgba(211.0f, 211.0f, 211.0f, 1.0f)),
|
||||
stop(3f, rgba(0.0f, 255.0f, 255.0f, 1.0f))
|
||||
)),
|
||||
stop(18, step(
|
||||
get("stroke-width"),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f),
|
||||
stop(1f, rgba(0.0f, 0.0f, 0.0f, 1.0f)),
|
||||
stop(2f, rgba(128.0f, 128.0f, 128.0f, 1.0f)),
|
||||
stop(3f, rgba(0.0f, 255.0f, 0.0f, 1.0f))
|
||||
))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
Timber.i("Fill color: %s", layer.getFillColor());
|
||||
}
|
||||
|
||||
private void addCompositeCategoricalFunction() {
|
||||
Timber.i("Add composite categorical function");
|
||||
FillLayer layer = mapboxMap.getStyle().getLayerAs(AMSTERDAM_PARKS_LAYER);
|
||||
assert layer != null;
|
||||
layer.setProperties(
|
||||
fillColor(
|
||||
step(zoom(),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f),
|
||||
stop(7f, match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f)
|
||||
)),
|
||||
stop(8f, match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f)
|
||||
)),
|
||||
stop(9f, match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f)
|
||||
)),
|
||||
stop(10f, match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f)
|
||||
)),
|
||||
stop(11f, match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f)
|
||||
)),
|
||||
stop(12f, match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f)
|
||||
)),
|
||||
stop(13f, match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f)
|
||||
)),
|
||||
stop(14f, match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
|
||||
literal("Jordaan"), rgba(0.0f, 255.0f, 0.0f, 1.0f),
|
||||
literal("PrinsenEiland"), rgba(0.0f, 0.0f, 0.0f, 1.0f),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f)
|
||||
)),
|
||||
stop(15f, match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f)
|
||||
)),
|
||||
stop(16f, match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f)
|
||||
)),
|
||||
stop(17f, match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f)
|
||||
)),
|
||||
stop(18f, match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
|
||||
literal("Jordaan"), rgba(0.0f, 255.0f, 255.0f, 1.0f),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f)
|
||||
)),
|
||||
stop(19f, match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f)
|
||||
)),
|
||||
stop(20f, match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f)
|
||||
)),
|
||||
stop(21f, match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f)
|
||||
)),
|
||||
stop(22f, match(
|
||||
get("name"),
|
||||
literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
|
||||
rgba(255.0f, 255.0f, 255.0f, 1.0f)
|
||||
))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
Timber.i("Fill color: %s", layer.getFillColor());
|
||||
}
|
||||
|
||||
private void addParksLayer() {
|
||||
// Add a source
|
||||
Source source;
|
||||
try {
|
||||
source = new GeoJsonSource("amsterdam-parks-source", ResourceUtils.readRawResource(this, R.raw.amsterdam));
|
||||
mapboxMap.getStyle().addSource(source);
|
||||
} catch (IOException ioException) {
|
||||
Toast.makeText(
|
||||
DataDrivenStyleActivity.this,
|
||||
"Couldn't add source: " + ioException.getMessage(),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
// Add a fill layer
|
||||
mapboxMap.getStyle().addLayer(new FillLayer(AMSTERDAM_PARKS_LAYER, source.getId())
|
||||
.withProperties(
|
||||
fillColor(color(Color.GREEN)),
|
||||
fillOutlineColor(rgb(0, 0, 255)),
|
||||
fillAntialias(true)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,331 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.style
|
||||
|
||||
import android.graphics.PointF
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.Snackbar
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import com.mapbox.android.gestures.AndroidGesturesManager
|
||||
import com.mapbox.android.gestures.MoveGestureDetector
|
||||
import com.mapbox.geojson.Feature
|
||||
import com.mapbox.geojson.FeatureCollection
|
||||
import com.mapbox.geojson.Point
|
||||
import com.mapbox.mapboxsdk.annotations.IconFactory
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng
|
||||
import com.mapbox.mapboxsdk.maps.MapView
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.style.layers.PropertyFactory.*
|
||||
import com.mapbox.mapboxsdk.style.layers.SymbolLayer
|
||||
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import kotlinx.android.synthetic.main.activity_draggable_marker.*
|
||||
|
||||
/**
|
||||
* An Activity that showcases how to make symbols draggable.
|
||||
*/
|
||||
class DraggableMarkerActivity : AppCompatActivity() {
|
||||
companion object {
|
||||
private const val sourceId = "source_draggable"
|
||||
private const val layerId = "layer_draggable"
|
||||
private const val markerImageId = "marker_icon_draggable"
|
||||
|
||||
private var latestId: Long = 0
|
||||
fun generateMarkerId(): String {
|
||||
if (latestId == Long.MAX_VALUE) {
|
||||
throw RuntimeException("You've added too many markers.")
|
||||
}
|
||||
return latestId++.toString()
|
||||
}
|
||||
}
|
||||
|
||||
private val actionBarHeight: Int by lazy {
|
||||
supportActionBar?.height ?: 0
|
||||
}
|
||||
|
||||
// View property is required for activity sanity tests
|
||||
// we perform reflection on this requires using findViewById
|
||||
private lateinit var mapView: MapView
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private val featureCollection = FeatureCollection.fromFeatures(mutableListOf())
|
||||
private val source = GeoJsonSource(sourceId, featureCollection)
|
||||
private val layer = SymbolLayer(layerId, sourceId)
|
||||
.withProperties(
|
||||
iconImage(markerImageId),
|
||||
iconAllowOverlap(true),
|
||||
iconIgnorePlacement(true))
|
||||
|
||||
private var draggableSymbolsManager: DraggableSymbolsManager? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_draggable_marker)
|
||||
|
||||
mapView = findViewById(R.id.mapView)
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync { mapboxMap ->
|
||||
this.mapboxMap = mapboxMap
|
||||
|
||||
mapboxMap.setStyle(
|
||||
Style.Builder()
|
||||
.fromUri(Style.MAPBOX_STREETS)
|
||||
.withImage(markerImageId, IconFactory.getInstance(this).defaultMarker().bitmap)
|
||||
.withSource(source)
|
||||
.withLayer(layer)
|
||||
)
|
||||
|
||||
// Add initial markers
|
||||
addMarker(LatLng(52.407210, 16.924324))
|
||||
addMarker(LatLng(41.382679, 2.181555))
|
||||
addMarker(LatLng(51.514886, -0.112589))
|
||||
|
||||
// Initial camera position
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
|
||||
LatLng(45.0, 8.0), 3.0
|
||||
))
|
||||
|
||||
mapboxMap.addOnMapClickListener {
|
||||
// Adding a marker on map click
|
||||
val features = mapboxMap.queryRenderedSymbols(it, layerId)
|
||||
if (features.isEmpty()) {
|
||||
addMarker(it)
|
||||
} else {
|
||||
// Displaying marker info on marker click
|
||||
Snackbar.make(
|
||||
mapView,
|
||||
"Marker's position: %.4f, %.4f".format(it.latitude, it.longitude),
|
||||
Snackbar.LENGTH_LONG)
|
||||
.show()
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
draggableSymbolsManager = DraggableSymbolsManager(
|
||||
mapView, mapboxMap, featureCollection, source, layerId, actionBarHeight, 0)
|
||||
|
||||
// Adding symbol drag listeners
|
||||
draggableSymbolsManager?.addOnSymbolDragListener(object : DraggableSymbolsManager.OnSymbolDragListener {
|
||||
override fun onSymbolDragStarted(id: String) {
|
||||
draggedMarkerPositionTv.visibility = View.VISIBLE
|
||||
Snackbar.make(
|
||||
mapView,
|
||||
"Marker drag started (%s)".format(id),
|
||||
Snackbar.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onSymbolDrag(id: String) {
|
||||
val point = featureCollection.features()?.find {
|
||||
it.id() == id
|
||||
}?.geometry() as Point
|
||||
draggedMarkerPositionTv.text = "Dragged marker's position: %.4f, %.4f".format(point.latitude(), point.longitude())
|
||||
}
|
||||
|
||||
override fun onSymbolDragFinished(id: String) {
|
||||
draggedMarkerPositionTv.visibility = View.GONE
|
||||
Snackbar.make(
|
||||
mapView,
|
||||
"Marker drag finished (%s)".format(id),
|
||||
Snackbar.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun addMarker(latLng: LatLng) {
|
||||
featureCollection.features()?.add(
|
||||
Feature.fromGeometry(Point.fromLngLat(latLng.longitude, latLng.latitude), null, generateMarkerId()))
|
||||
source.setGeoJson(featureCollection)
|
||||
}
|
||||
|
||||
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
|
||||
// Dispatching parent's touch events to the manager
|
||||
draggableSymbolsManager?.onParentTouchEvent(ev)
|
||||
return super.dispatchTouchEvent(ev)
|
||||
}
|
||||
|
||||
/**
|
||||
* A manager, that allows dragging symbols after they are long clicked.
|
||||
* Since this manager lives outside of the Maps SDK, we need to intercept parent's motion events
|
||||
* and pass them with [DraggableSymbolsManager.onParentTouchEvent].
|
||||
* If we were to try and overwrite [AppCompatActivity.onTouchEvent], those events would've been
|
||||
* consumed by the map.
|
||||
*
|
||||
* We also need to setup a [DraggableSymbolsManager.androidGesturesManager],
|
||||
* because after disabling map's gestures and starting the drag process
|
||||
* we still need to listen for move gesture events which map won't be able to provide anymore.
|
||||
*
|
||||
* @param mapView the mapView
|
||||
* @param mapboxMap the mapboxMap
|
||||
* @param symbolsCollection the collection that contains all the symbols that we want to be draggable
|
||||
* @param symbolsSource the source that contains the [symbolsCollection]
|
||||
* @param symbolsLayerId the ID of the layer that the symbols are displayed on
|
||||
* @param touchAreaShiftX X-axis padding that is applied to the parent's window motion event,
|
||||
* as that window can be bigger than the [mapView].
|
||||
* @param touchAreaShiftY Y-axis padding that is applied to the parent's window motion event,
|
||||
* as that window can be bigger than the [mapView].
|
||||
* @param touchAreaMaxX maximum value of X-axis motion event
|
||||
* @param touchAreaMaxY maximum value of Y-axis motion event
|
||||
*/
|
||||
class DraggableSymbolsManager(
|
||||
mapView: MapView,
|
||||
private val mapboxMap: MapboxMap,
|
||||
private val symbolsCollection: FeatureCollection,
|
||||
private val symbolsSource: GeoJsonSource,
|
||||
private val symbolsLayerId: String,
|
||||
private val touchAreaShiftY: Int = 0,
|
||||
private val touchAreaShiftX: Int = 0,
|
||||
private val touchAreaMaxX: Int = mapView.width,
|
||||
private val touchAreaMaxY: Int = mapView.height
|
||||
) {
|
||||
|
||||
private val androidGesturesManager: AndroidGesturesManager = AndroidGesturesManager(mapView.context, false)
|
||||
private var draggedSymbolId: String? = null
|
||||
private val onSymbolDragListeners: MutableList<OnSymbolDragListener> = mutableListOf<OnSymbolDragListener>()
|
||||
|
||||
init {
|
||||
mapboxMap.addOnMapLongClickListener {
|
||||
// Starting the drag process on long click
|
||||
draggedSymbolId = mapboxMap.queryRenderedSymbols(it, symbolsLayerId).firstOrNull()?.id()?.also { id ->
|
||||
mapboxMap.uiSettings.setAllGesturesEnabled(false)
|
||||
mapboxMap.gesturesManager.moveGestureDetector.interrupt()
|
||||
notifyOnSymbolDragListeners {
|
||||
onSymbolDragStarted(id)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
androidGesturesManager.setMoveGestureListener(MyMoveGestureListener())
|
||||
}
|
||||
|
||||
inner class MyMoveGestureListener : MoveGestureDetector.OnMoveGestureListener {
|
||||
override fun onMoveBegin(detector: MoveGestureDetector): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onMove(detector: MoveGestureDetector, distanceX: Float, distanceY: Float): Boolean {
|
||||
if (detector.pointersCount > 1) {
|
||||
// Stopping the drag when we don't work with a simple, on-pointer move anymore
|
||||
stopDragging()
|
||||
return true
|
||||
}
|
||||
|
||||
// Updating symbol's position
|
||||
draggedSymbolId?.also { draggedSymbolId ->
|
||||
val moveObject = detector.getMoveObject(0)
|
||||
val point = PointF(moveObject.currentX - touchAreaShiftX, moveObject.currentY - touchAreaShiftY)
|
||||
|
||||
if (point.x < 0 || point.y < 0 || point.x > touchAreaMaxX || point.y > touchAreaMaxY) {
|
||||
stopDragging()
|
||||
}
|
||||
|
||||
val latLng = mapboxMap.projection.fromScreenLocation(point)
|
||||
|
||||
symbolsCollection.features()?.indexOfFirst {
|
||||
it.id() == draggedSymbolId
|
||||
}?.also { index ->
|
||||
symbolsCollection.features()?.get(index)?.also { oldFeature ->
|
||||
val properties = oldFeature.properties()
|
||||
val newFeature = Feature.fromGeometry(
|
||||
Point.fromLngLat(latLng.longitude, latLng.latitude),
|
||||
properties,
|
||||
draggedSymbolId
|
||||
)
|
||||
symbolsCollection.features()?.set(index, newFeature)
|
||||
symbolsSource.setGeoJson(symbolsCollection)
|
||||
notifyOnSymbolDragListeners {
|
||||
onSymbolDrag(draggedSymbolId)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onMoveEnd(detector: MoveGestureDetector, velocityX: Float, velocityY: Float) {
|
||||
// Stopping the drag when move ends
|
||||
stopDragging()
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopDragging() {
|
||||
mapboxMap.uiSettings.setAllGesturesEnabled(true)
|
||||
draggedSymbolId?.let {
|
||||
notifyOnSymbolDragListeners {
|
||||
onSymbolDragFinished(it)
|
||||
}
|
||||
}
|
||||
draggedSymbolId = null
|
||||
}
|
||||
|
||||
fun onParentTouchEvent(ev: MotionEvent?) {
|
||||
androidGesturesManager.onTouchEvent(ev)
|
||||
}
|
||||
|
||||
private fun notifyOnSymbolDragListeners(action: OnSymbolDragListener.() -> Unit) {
|
||||
onSymbolDragListeners.forEach(action)
|
||||
}
|
||||
|
||||
fun addOnSymbolDragListener(listener: OnSymbolDragListener) {
|
||||
onSymbolDragListeners.add(listener)
|
||||
}
|
||||
|
||||
fun removeOnSymbolDragListener(listener: OnSymbolDragListener) {
|
||||
onSymbolDragListeners.remove(listener)
|
||||
}
|
||||
|
||||
interface OnSymbolDragListener {
|
||||
fun onSymbolDragStarted(id: String)
|
||||
fun onSymbolDrag(id: String)
|
||||
fun onSymbolDragFinished(id: String)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle?) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState?.let {
|
||||
mapView.onSaveInstanceState(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun MapboxMap.queryRenderedSymbols(latLng: LatLng, layerId: String): List<Feature> {
|
||||
return this.queryRenderedFeatures(this.projection.toScreenLocation(latLng), layerId)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user