Initialiser MapFragment par programmation avec Maps API v2

J’essaie d’append un MapFragment à mon fragment actuel. L’utilisation de fragments nesteds est limitée à FragmentTransactions, vous ne pouvez pas utiliser la balise XML dans votre présentation. De plus, je souhaite qu’il soit ajouté au fragment principal lorsque l’utilisateur appuie sur un bouton. Donc, je crée le MapFragment par programmation avec getInstance() lorsque l’utilisateur appuie sur ce bouton et l’ajoute à l’endroit approprié. Il est montré correctement, jusqu’ici tout va bien.

Le problème est que, après avoir attaché le MapFragment, je dois obtenir une référence à GoogleMap pour placer un marqueur , mais la méthode getMap() renvoie null (car onCreateView() du fragment n’a pas encore été appelé).

J’ai regardé l’exemple de code démo et j’ai trouvé que la solution utilisée était l’initialisation de MapFragment dans onCreate() et l’obtention de la référence à GoogleMap dans onResume() , après l’ onCreateView() de onCreateView() .

Je dois obtenir la référence à GoogleMap juste après l’initialisation de MapFragment, car je veux que les utilisateurs puissent afficher ou masquer la carte avec un bouton. Je sais qu’une solution possible serait de créer la carte au début comme indiqué ci-dessus et de simplement régler sa visibilité, mais je souhaite que la carte soit désactivée par défaut afin de ne pas utiliser la bande passante de l’utilisateur pour ça.

J’ai essayé avec MapsInitializer , mais ne fonctionne pas non plus. Je suis un peu coincé. Des idées? Voici mon code de test jusqu’ici:

 public class ParadaInfoFragment extends BaseDBFragment { // BaseDBFragment is just a SherlockFragment with custom utility methods. private static final Ssortingng MAP_FRAGMENT_TAG = "map"; private GoogleMap mMap; private SupportMapFragment mMapFragment; private TextView mToggleMapa; private boolean isMapVisible = false; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_parada_info, container, false); mToggleMapa = (TextView) v.findViewById(R.id.parada_info_map_button); return v; } @Override public void onStart() { super.onStart(); mToggleMapa.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!isMapVisible) { openMap(); } else { closeMap(); } isMapVisible = !isMapVisible; } }); } private void openMap() { // Creates initial configuration for the map GoogleMapOptions options = new GoogleMapOptions().camera(CameraPosition.fromLatLngZoom(new LatLng(37.4005502611301, -5.98233461380005), 16)) .compassEnabled(false).mapType(GoogleMap.MAP_TYPE_NORMAL).rotateGesturesEnabled(false).scrollGesturesEnabled(false).tiltGesturesEnabled(false) .zoomControlsEnabled(false).zoomGesturesEnabled(false); // Modified from the sample code: // It isn't possible to set a fragment's id programmatically so we set a // tag instead and search for it using that. mMapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentByTag(MAP_FRAGMENT_TAG); // We only create a fragment if it doesn't already exist. if (mMapFragment == null) { // To programmatically add the map, we first create a // SupportMapFragment. mMapFragment = SupportMapFragment.newInstance(options); // Then we add it using a FragmentTransaction. FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction(); fragmentTransaction.add(R.id.parada_info_map_container, mMapFragment, MAP_FRAGMENT_TAG); fragmentTransaction.commit(); } // We can't be guaranteed that the map is available because Google Play // services might not be available. setUpMapIfNeeded(); //XXX Here, getMap() returns null so the Marker can't be added // The map is shown with the previous options. } private void closeMap() { FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction(); fragmentTransaction.remove(mMapFragment); fragmentTransaction.commit(); } private void setUpMapIfNeeded() { // Do a null check to confirm that we have not already instantiated the // map. if (mMap == null) { // Try to obtain the map from the SupportMapFragment. mMap = mMapFragment.getMap(); // Check if we were successful in obtaining the map. if (mMap != null) { mMap.addMarker(new MarkerOptions().position(new LatLng(37.4005502611301, -5.98233461380005)).title("Marker")); } } } } 

Merci

Le bon AnderWebs m’a donné une réponse dans Google+ mais il est trop laz … emm occupé à l’écrire ici, alors voici la version courte: Étendre la classe MapFragment et remplacer la méthode onCreateView() . Une fois cette méthode terminée, nous pouvons obtenir une référence non nulle à l’object GoogleMap .

Ceci est ma solution particulière:

 public class MiniMapFragment extends SupportMapFragment { private LatLng mPosFija; public MiniMapFragment() { super(); } public static MiniMapFragment newInstance(LatLng posicion){ MiniMapFragment frag = new MiniMapFragment(); frag.mPosFija = posicion; return frag; } @Override public View onCreateView(LayoutInflater arg0, ViewGroup arg1, Bundle arg2) { View v = super.onCreateView(arg0, arg1, arg2); initMap(); return v; } private void initMap(){ UiSettings settings = getMap().getUiSettings(); settings.setAllGesturesEnabled(false); settings.setMyLocationButtonEnabled(false); getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(mPosFija,16)); getMap().addMarker(new MarkerOptions().position(mPosFija).icon(BitmapDescriptorFactory.fromResource(R.drawable.marker))); } } 

Maintenant dans la classe Fragment précédente je fais

 mMapFragment = MiniMapFragment.newInstance(new LatLng(37.4005502611301, -5.98233461380005)); 

Peut-être que ce n’est pas encore parfait, car l’écran clignote lorsque la carte est affichée. Mais je ne sais pas si le problème est dû à ceci ou à autre chose.

Merci, a trouvé cela très utile. J’affiche ma solution légèrement modifiée, car c’était plus propre pour moi d’informer le parent Fragment lorsque la carte était prête. Cette méthode fonctionne également avec un cycle saveInstanceState / restoreInstanceState.

 public class CustomMapFragment extends SupportMapFragment { private static final Ssortingng LOG_TAG = "CustomMapFragment"; public CustomMapFragment() { super(); } public static CustomMapFragment newInstance() { CustomMapFragment fragment = new CustomMapFragment(); return fragment; } @Override public View onCreateView(LayoutInflater arg0, ViewGroup arg1, Bundle arg2) { View v = super.onCreateView(arg0, arg1, arg2); Fragment fragment = getParentFragment(); if (fragment != null && fragment instanceof OnMapReadyListener) { ((OnMapReadyListener) fragment).onMapReady(); } return v; } /** * Listener interface to tell when the map is ready */ public static interface OnMapReadyListener { void onMapReady(); } } 

Utiliser comme fragment nested: –

 public class ParentFragment extends Fragment implements OnMapReadyListener { ... mMapFragment = CustomMapFragment.newInstance(); getChildFragmentManager().beginTransaction().replace(R.id.mapContainer, mMapFragment).commit(); @Override public void onMapReady() { mMap = mMapFragment.getMap(); } ... } 

J’espère que ça aide quelqu’un.

Voici ma solution: je me suis inspiré du code précédemment affiché et je l’ai nettoyé. J’ai également ajouté les méthodes statiques avec et sans les parameters GoogleMapOptions.

 public class GoogleMapFragment extends SupportMapFragment { private static final Ssortingng SUPPORT_MAP_BUNDLE_KEY = "MapOptions"; public static interface OnGoogleMapFragmentListener { void onMapReady(GoogleMap map); } public static GoogleMapFragment newInstance() { return new GoogleMapFragment(); } public static GoogleMapFragment newInstance(GoogleMapOptions options) { Bundle arguments = new Bundle(); arguments.putParcelable(SUPPORT_MAP_BUNDLE_KEY, options); GoogleMapFragment fragment = new GoogleMapFragment(); fragment.setArguments(arguments); return fragment; } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mCallback = (OnGoogleMapFragmentListener) getActivity(); } catch (ClassCastException e) { throw new ClassCastException(getActivity().getClass().getName() + " must implement OnGoogleMapFragmentListener"); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); if (mCallback != null) { mCallback.onMapReady(getMap()); } return view; } private OnGoogleMapFragmentListener mCallback; } 

Le modèle d’utilisation est le suivant:

 public class MyMapActivity implements OnGoogleMapFragmentListener { ... @Override public void onMapReady(GoogleMap map) { mUIGoogleMap = map; ... } ... private GoogleMap mUIGoogleMap; } 

Pas besoin de personnaliser SupportMapFragment vous pouvez le faire directement en utilisant le morceau de code suivant,

 FragmentManager fm = getSupportFragmentManager(); // getChildFragmentManager inside fragments. CameraPosition cp = new CameraPosition.Builder() .target(initialLatLng) // your initial co-ordinates here. like, LatLng initialLatLng .zoom(zoom_level) .build(); SupportMapFragment mapFragment = SupportMapFragment.newInstance(new GoogleMapOptions().camera(cp)); fm.beginTransaction().replace(R.id.rl_map, mapFragment).commit(); 

Ajouter ce morceau de code pour la layout

  

Cela va charger GoogleMap à un Location particulier directement, c’est-à-dire initialiser.