2013-05-01 13 views
10

Próbuję dynamicznie utworzyć SupportMapFragment i umieścić go w kontenerze FrameLayout.Funkcja getMap() funkcji SupportMapFragment zwraca wartość null

Mój problem jest to, że mMapFragment.getMap() powraca null ...

ktoś może pomóc?

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> 

Odpowiedz

8

commit() na FragmentTransaction nie od razu wykonywać swoje operacje. Zanim zadzwonisz pod numer setUpMap(), onCreateView() nie zostanie wywołany na SupportMapFragment, dlatego też nie będzie jeszcze mapą.

Jednym z rozwiązań jest nie stosować zagnieżdżone fragmentów wyboru, zamiast mieć CenterMapFragment rozciągają SupportMapFragment, w którym to przypadku getMap() powinien pracować w dowolnym czasie po onCreateView() (np onActivityCreated()).

+0

Jeśli 'CenterMapFragment' rozszerza' SupportMapFragment', jak mogę ustawić mapę na 'FrameLayout'? Muszę zmienić układ? – jul

+1

@jul: W jednym podejściu 'CenterMapFragment' zaimplementował' onCreateView() ', który najpierw wywoływał' super.onCreateView() ', aby uzyskać wszystko, co' SupportMapFragment' tworzy. Następnie utworzyłby 'FrameLayout' i dodał utworzony' super' widok 'View' jako element potomny' FrameLayout'. Wtedy zwróciłby 'FrameLayout' z' onCreateView() '. To opakowuje zawartość 'SupportMapFragment' w dowolnym' 'CenterMapFragment" chce. Albo "CenterMapFragment" jest zwykłym 'Fragmentem' i użyj' MapView' zamiast 'SupportMapFragment'. Lub znajdź lepszy czas na wywołanie 'setUpMap()' z twoim aktualnym kodem. – CommonsWare

+0

Ok, użyję 'MapView'. – jul

2

W poniższym linku MapView służy jak sugeruje CommonsWare w ostatniej części swojego komentarza:

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

Mam nadzieję, że będą one pomocne.

+0

Podczas gdy ten link może odpowiedzieć na pytanie, lepiej umieścić tutaj istotne części odpowiedzi i podać link do odsyłacza. Odpowiedzi dotyczące linków mogą stać się nieprawidłowe, jeśli strona z linkami się zmieni. – skolima

+0

OK, masz rację! Dzięki – UserK

1

Wywołanie

fragmentTransaction.commit(); 

jest asynchroniczna, mapa nie będzie gotowy jeszcze po powrocie z niej. Wystarczy zadzwonić

getFragmentManager().executePendingTransactions(); 

jako następnej linii, które uczynią to synchroniczny i wykona go na następnej instrukcji odebrać gotową mapę porządku. Jeśli martwisz się o czas, który zajmuje, przestaw całą inicjalizację na AsyncTask i pokaż wskaźnik postępu dla użytkownika podczas inicjowania mapy.

Powiązane problemy