images, boolean sdf) {
validateState("addImages");
new BitmapImageConversionTask(nativeMap, sdf).execute(Builder.ImageWrapper.convertToImageArray(images, sdf));
}
/**
* Removes an image from the map's style.
*
* @param name the name of the image to remove
*/
public void removeImage(@NonNull String name) {
validateState("removeImage");
nativeMap.removeImage(name);
}
/**
* Get an image from the map's style using an id.
*
* @param id the id of the image
* @return the image bitmap
*/
@Nullable
public Bitmap getImage(@NonNull String id) {
validateState("getImage");
return nativeMap.getImage(id);
}
//
// Transition
//
/**
*
* Set the transition options for style changes.
*
* If not set, any changes take effect without animation, besides symbols,
* which will fade in/out with a default duration after symbol collision detection.
*
* To disable symbols fade in/out animation,
* pass transition options with {@link TransitionOptions#enablePlacementTransitions} equal to false.
*
* Both {@link TransitionOptions#duration} and {@link TransitionOptions#delay}
* will also change the behavior of the symbols fade in/out animation if the placement transition is enabled.
*
* @param transitionOptions the transition options
*/
public void setTransition(@NonNull TransitionOptions transitionOptions) {
validateState("setTransition");
nativeMap.setTransitionOptions(transitionOptions);
}
/**
*
* Get the transition options for style changes.
*
* By default, any changes take effect without animation, besides symbols,
* which will fade in/out with a default duration after symbol collision detection.
*
* To disable symbols fade in/out animation,
* pass transition options with {@link TransitionOptions#enablePlacementTransitions} equal to false
* into {@link #setTransition(TransitionOptions)}.
*
* Both {@link TransitionOptions#duration} and {@link TransitionOptions#delay}
* will also change the behavior of the symbols fade in/out animation if the placement transition is enabled.
*
* @return TransitionOptions the transition options
*/
@NonNull
public TransitionOptions getTransition() {
validateState("getTransition");
return nativeMap.getTransitionOptions();
}
//
// Light
//
/**
* Get the light source used to change lighting conditions on extruded fill layers.
*
* @return the global light source
*/
@Nullable
public Light getLight() {
validateState("getLight");
return nativeMap.getLight();
}
//
// State
//
/**
* Called when the underlying map will start loading a new style. This method will clean up this style
* by setting the java sources and layers in a detached state and removing them from core.
*/
void onWillStartLoadingMap() {
fullyLoaded = false;
for (Source source : sources.values()) {
if (source != null) {
source.setDetached();
nativeMap.removeSource(source);
}
}
for (Layer layer : layers.values()) {
if (layer != null) {
layer.setDetached();
nativeMap.removeLayer(layer);
}
}
for (Map.Entry bitmapEntry : images.entrySet()) {
nativeMap.removeImage(bitmapEntry.getKey());
bitmapEntry.getValue().recycle();
}
sources.clear();
layers.clear();
images.clear();
}
/**
* Called when the underlying map has finished loading this style.
* This method will add all components added to the builder that were defined with the 'with' prefix.
*/
void onDidFinishLoadingStyle() {
if (!fullyLoaded) {
fullyLoaded = true;
for (Source source : builder.sources) {
addSource(source);
}
for (Builder.LayerWrapper layerWrapper : builder.layers) {
if (layerWrapper instanceof Builder.LayerAtWrapper) {
addLayerAt(layerWrapper.layer, ((Builder.LayerAtWrapper) layerWrapper).index);
} else if (layerWrapper instanceof Builder.LayerAboveWrapper) {
addLayerAbove(layerWrapper.layer, ((Builder.LayerAboveWrapper) layerWrapper).aboveLayer);
} else if (layerWrapper instanceof Builder.LayerBelowWrapper) {
addLayerBelow(layerWrapper.layer, ((Builder.LayerBelowWrapper) layerWrapper).belowLayer);
} else {
// just add layer to map, but below annotations
addLayerBelow(layerWrapper.layer, MapboxConstants.LAYER_ID_ANNOTATIONS);
}
}
for (Builder.ImageWrapper image : builder.images) {
addImage(image.id, image.bitmap, image.sdf);
}
if (builder.transitionOptions != null) {
setTransition(builder.transitionOptions);
}
}
}
/**
* Returns true if the style is fully loaded. Returns false if style hasn't been fully loaded or a new style is
* underway of being loaded.
*
* @return True if fully loaded, false otherwise
*/
public boolean isFullyLoaded() {
return fullyLoaded;
}
/**
* Validates the style state, throw an IllegalArgumentException on invalid state.
*
* @param methodCall the calling method name
*/
private void validateState(String methodCall) {
if (!fullyLoaded) {
throw new IllegalStateException(
String.format("Calling %s when a newer style is loading/has loaded.", methodCall)
);
}
}
//
// Builder
//
/**
* Builder for composing a style object.
*/
public static class Builder {
private final List sources = new ArrayList<>();
private final List layers = new ArrayList<>();
private final List images = new ArrayList<>();
private TransitionOptions transitionOptions;
private String styleUrl;
private String styleJson;
/**
*
* Will loads a new map style asynchronous from the specified URL.
*
* {@code url} can take the following forms:
*
* {@code Style#StyleUrl}: load one of the bundled styles in {@link Style}.
* {@code mapbox://styles//