package com.mapbox.mapboxsdk.maps; import android.app.Fragment; import android.content.Context; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.mapbox.mapboxsdk.utils.MapFragmentUtils; import java.util.ArrayList; import java.util.List; /** * Fragment wrapper around a map view. *

* A Map component in an app. This fragment is the simplest way to place a map in an application. * It's a wrapper around a view of a map to automatically handle the necessary life cycle needs. * Being a fragment, this component can be added to an activity's layout or can dynamically be added * using a FragmentManager. *

*

* To get a reference to the MapView, use {@link #getMapAsync(OnMapReadyCallback)}} *

* * @see #getMapAsync(OnMapReadyCallback) */ public final class MapFragment extends Fragment implements OnMapReadyCallback { private final List mapReadyCallbackList = new ArrayList<>(); private OnMapViewReadyCallback mapViewReadyCallback; private MapboxMap mapboxMap; private MapView map; /** * Creates a default MapFragment instance * * @return MapFragment instantiated */ public static MapFragment newInstance() { return new MapFragment(); } /** * Creates a MapFragment instance * * @param mapboxMapOptions The configuration options to be used. * @return MapFragment instantiated. */ public static MapFragment newInstance(@Nullable MapboxMapOptions mapboxMapOptions) { MapFragment mapFragment = new MapFragment(); mapFragment.setArguments(MapFragmentUtils.createFragmentArgs(mapboxMapOptions)); return mapFragment; } /** * Called when this fragment is inflated, parses XML tag attributes. * * @param context The context inflating this fragment. * @param attrs The XML tag attributes. * @param savedInstanceState The saved instance state for the map fragment. */ @Override public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) { super.onInflate(context, attrs, savedInstanceState); setArguments(MapFragmentUtils.createFragmentArgs(MapboxMapOptions.createFromAttributes(context, attrs))); } /** * Called when the context attaches to this fragment. * * @param context the context attaching */ @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof OnMapViewReadyCallback) { mapViewReadyCallback = (OnMapViewReadyCallback) context; } } /** * Creates the fragment view hierarchy. * * @param inflater Inflater used to inflate content. * @param container The parent layout for the map fragment. * @param savedInstanceState The saved instance state for the map fragment. * @return The view created */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); Context context = inflater.getContext(); map = new MapView(context, MapFragmentUtils.resolveArgs(context, getArguments())); return map; } /** * Called when the fragment view hierarchy is created. * * @param view The content view of the fragment * @param savedInstanceState The saved instance state of the fragment */ @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); map.onCreate(savedInstanceState); map.getMapAsync(this); // notify listeners about mapview creation if (mapViewReadyCallback != null) { mapViewReadyCallback.onMapViewReady(map); } } /** * Called when the style of the map has successfully loaded. * * @param mapboxMap The public api controller of the map */ @Override public void onMapReady(MapboxMap mapboxMap) { this.mapboxMap = mapboxMap; for (OnMapReadyCallback onMapReadyCallback : mapReadyCallbackList) { onMapReadyCallback.onMapReady(mapboxMap); } } /** * Called when the fragment is visible for the users. */ @Override public void onStart() { super.onStart(); map.onStart(); } /** * Called when the fragment is ready to be interacted with. */ @Override public void onResume() { super.onResume(); map.onResume(); } /** * Called when the fragment is pausing. */ @Override public void onPause() { super.onPause(); map.onPause(); } /** * Called when the fragment state needs to be saved. * * @param outState The saved state */ @Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); map.onSaveInstanceState(outState); } /** * Called when the fragment is no longer visible for the user. */ @Override public void onStop() { super.onStop(); map.onStop(); } /** * Called when the fragment receives onLowMemory call from the hosting Activity. */ @Override public void onLowMemory() { super.onLowMemory(); map.onLowMemory(); } /** * Called when the fragment is view hiearchy is being destroyed. */ @Override public void onDestroyView() { super.onDestroyView(); map.onDestroy(); mapReadyCallbackList.clear(); } /** * Sets a callback object which will be triggered when the MapboxMap instance is ready to be used. * * @param onMapReadyCallback The callback to be invoked. */ public void getMapAsync(@NonNull final OnMapReadyCallback onMapReadyCallback) { if (mapboxMap == null) { mapReadyCallbackList.add(onMapReadyCallback); } else { onMapReadyCallback.onMapReady(mapboxMap); } } /** * Callback to be invoked when the map fragment has inflated its MapView. *

* To use this interface the context hosting the fragment must implement this interface. * That instance will be set as part of Fragment#onAttach(Context context). *

*/ public interface OnMapViewReadyCallback { /** * Called when the map has been created. * * @param mapView The created mapview */ void onMapViewReady(MapView mapView); } }