2013-05-01 11 views
10

Sto provando a creare un SupportMapFragment dinamicamente ea metterlo in un contenitore FrameLayout.getMap() di SupportMapFragment restituisce null

Il mio problema è che i rendimenti mMapFragment.getMap()null ...

Chiunque può aiutare?

CenterMapFragment.java

public class CenterMapFragment extends Fragment { 

    private SupportMapFragment mMapFragment; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 

     return inflater.inflate(R.layout.center_map_fragment, container, false); 
    } 

    @Override 
    public void onActivityCreated (Bundle savedInstanceState){ 
     super.onActivityCreated(savedInstanceState); 

     if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity()) == ConnectionResult.SUCCESS) { 
      setUpMapIfNeeded(); 
     } 
    } 


    private void setUpMapIfNeeded() { 

     if (mMapFragment == null) { 

      mMapFragment = SupportMapFragment.newInstance(); 
      FragmentTransaction fragmentTransaction = 
          getChildFragmentManager().beginTransaction(); 
      fragmentTransaction.replace(R.id.map, mMapFragment); 
      fragmentTransaction.commit(); 

      setUpMap(); 
     } 
    } 

    private void setUpMap() {  

     GoogleMap map = mMapFragment.getMap(); 

     // map is null! 

    } 

    @Override 
    public void onResume() 
    { 
     super.onResume(); 
     setUpMapIfNeeded();  
    } 
} 

center_map_fragment.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

    <FrameLayout 
     android:id="@+id/map" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" > 
    </FrameLayout> 

    <Button 
     android:id="@+id/btn_loc" 
     android:layout_width="60dp" 
     android:layout_height="50dp" 
     android:layout_alignParentBottom="true" 
     android:layout_alignParentRight="true" 
     android:background="@drawable/locbtn" /> 

</RelativeLayout> 

risposta

8

commit() su un FragmentTransaction non esegue immediatamente le proprie operazioni. Con il tempo si chiama setUpMap(), onCreateView() non sarà stato invitato il SupportMapFragment, e quindi non ci non saranno ancora una mappa.

Un approccio è di non usare frammenti annidati, eleggendo invece di avere CenterMapFragment estendono SupportMapFragment, nel qual caso getMap() dovrebbe funzionare in qualsiasi momento dopo onCreateView() (ad esempio, onActivityCreated()).

+0

Se 'CenterMapFragment' estende' SupportMapFragment', come posso impostare la mappa per la 'FrameLayout'? Devo cambiare il layout? – jul

+1

@jul: Un approccio avrebbe 'CenterMapFragment' implementare un' onCreateView() 'che ha chiamato' super.onCreateView() 'per ottenere tutto ciò che' SupportMapFragment' crea. Quindi creerebbe il 'FrameLayout' e aggiungerà' View' 'super' creato come figlio di' FrameLayout'. Quindi restituire 'FrameLayout' da' onCreateView() '. Questo avvolge il contenuto di 'SupportMapFragment' in qualunque cosa 'CenterMapFragment' voglia. Oppure, avere 'CenterMapFragment' è solo un ordinario' Fragment' e usa 'MapView' invece di' SupportMapFragment'. Oppure, trova un momento migliore per chiamare 'setUpMap()' con il tuo codice corrente. – CommonsWare

+0

Ok, userò un 'MapView'. – jul

2

Nel seguente link MapView viene utilizzato come suggerisce CommonsWare nell'ultima parte del suo commento:

http://ucla.jamesyxu.com/?p=287

public class MapFragment extends Fragment { 

    MapView m; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
     // inflat and return the layout 
     View v = inflater.inflate(R.layout.map_fragment, container, false); 
     m = (MapView) v.findViewById(R.id.mapView); 
     m.onCreate(savedInstanceState); 

     return v; 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 
     m.onResume(); 
    } 

    @Override 
    public void onPause() { 
     super.onPause(); 
     m.onPause(); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     m.onDestroy(); 
    } 

    @Override 
    public void onLowMemory() { 
     super.onLowMemory(); 
     m.onLowMemory(); 
    } 
} 

Spero che questi saranno utili.

+0

Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il link per riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. – skolima

+0

Ok hai ragione! Grazie – UserK

1

Calling

fragmentTransaction.commit(); 

è asincrona, la mappa non sarà ancora pronta quando si torna da esso. Basta chiamare

getFragmentManager().executePendingTransactions(); 

come la linea successiva, che renderà sincrono e verrà eseguito per la prossima istruzione di far salire la mappa finito tutto bene. Se sei preoccupato per il tempo necessario, imposta l'intera inizializzazione su AsyncTask e mostra un indicatore di avanzamento all'utente durante l'inizializzazione della mappa.