2013-05-01 5 views
10

Ich versuche, ein SupportMapFragment dynamisch zu erstellen und es in einen FrameLayout Container zu setzen.SupportMapFragments getMap() gibt null zurück

Mein Problem ist, dass mMapFragment.getMap() kehrt null ...

Wer kann helfen?

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> 

Antwort

8

commit() auf einem FragmentTransaction führt nicht seinen Betrieb sofort. Wenn Sie setUpMap() anrufen, wird onCreateView() nicht auf der SupportMapFragment aufgerufen, und daher wird noch keine Karte sein.

Ein Ansatz ist nicht verschachtelte Fragmente zu verwenden, anstatt CenterMapFragment erstrecken SupportMapFragment, wobei in diesem Fall haben die Wahl getMap() nach onCreateView() jeder Zeit arbeiten soll (beispielsweise onActivityCreated()).

+0

Wenn 'CenterMapFragment '' SupportMapFragment' erweitert, wie kann ich die Map auf 'FrameLayout' setzen? Ich muss das Layout ändern? – jul

+1

@jul: Ein Ansatz würde 'CenterMapFragment' haben, um ein' onCreateView() 'zu implementieren, das 'super.onCreateView()' zuerst aufruft, um das zu erhalten, was 'SupportMapFragment' erzeugt. Dann würde es das 'FrameLayout' erzeugen und das' Super'-erzeugte 'View' als Kind des' FrameLayout' hinzufügen. Dann würde es 'FrameLayout' von' onCreateView() 'zurückgeben. Dadurch wird der Inhalt von "SupportMapFragment" in "CenterMapFragment" umgewandelt. Oder haben Sie 'CenterMapFragment' nur ein gewöhnliches' Fragment' und verwenden Sie 'MapView' anstatt' SupportMapFragment'. Oder finden Sie einen besseren Zeitpunkt, um 'setUpMap()' mit Ihrem aktuellen Code aufzurufen. – CommonsWare

+0

Ok, ich werde ein 'MapView' verwenden. – jul

2

Im folgenden Link MapView wird als CommonsWare im letzten Teil seines Kommentars schlägt vor:

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(); 
    } 
} 

Ich hoffe, dass diese hilfreich sein wird.

+0

Während dieser Link die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz zur Verfügung zu stellen. Nur-Link-Antworten können ungültig werden, wenn sich die verknüpfte Seite ändert. – skolima

+0

Ok du hast Recht! Vielen Dank – UserK

1

Aufruf

fragmentTransaction.commit(); 

ist asynchron, die Karte wird nicht bereit sein, doch wenn Sie von ihm zurück. Rufen Sie einfach an

getFragmentManager().executePendingTransactions(); 

als die nächste Zeile, die sie synchron und führen Sie es für die nächste Anweisung die fertige Karte in Ordnung zu holen machen. Wenn Sie sich Sorgen um die benötigte Zeit machen, setzen Sie die gesamte Initialisierung in eine AsyncTask und zeigen Sie dem Benutzer eine Fortschrittsanzeige an, während die Karte initialisiert wird.