teraz, gdy ostateczny pakiet SDK jest dostępny w Google API - jaki jest najlepszy sposób na utworzenie fragmentu z MapView? MapView potrzebuje MapActivity do prawidłowego działania.
Posiadanie działania zarządzającego fragmentami dziedziczone po MapActivity (złe rozwiązanie, ponieważ jest to sprzeczne z ideą, że fragmenty są samodzielne) i używanie zwykłego układu opartego na XML nie działa. Otrzymuję NullPointerException w MapActivity.setupMapView ():
E / AndroidRuntime (597): spowodowane przez: java.lang.NullPointerException E / AndroidRuntime (597): w com.google.android.maps.MapActivity.setupMapView (MapActivity.java:400) E / AndroidRuntime (597): w com.google.android.maps.MapView. (MapView.java:289) E / AndroidRuntime (597): w com.google.android.maps.MapView. (MapView.java:264) E / AndroidRuntime (597): w com.google.android.maps.MapView. (MapView.java:247)
Moim drugim pomysłem było programowe utworzenie MapView i przekazanie skojarzonego z nim działania (poprzez getActivity ()) jako Context do konstruktora MapView. Nie działa:
E / AndroidRuntime (834): spowodowane przez: java.lang.IllegalArgumentException: MapViews można tworzyć tylko wewnątrz instancji MapActivity. E / AndroidRuntime (834): w com.google.android.maps.MapView. (MapView.java:291) E / AndroidRuntime (834): w com.google.android.maps.MapView. (MapView.java:235) E / AndroidRuntime (834): w de.foo.FinderMapFragment.onCreateView (FinderMapFragment.java:225) E / AndroidRuntime (834): w android.app.FragmentManagerImpl.moveToState (FragmentManager.java:708) E / AndroidRuntime (834): na android.app.FragmentManagerImpl.moveToState (FragmentManager.java:900) E / AndroidRuntime (834): w android.app.FragmentManagerImpl.addFragment (FragmentManager.java:978) E / AndroidRuntime (834): w android.app.Activity.onCreateView (Activity.java:4090) E / AndroidRuntime (834): w android.view.LayoutInflater.createViewFromTag (LayoutInflater.java:664)
Naprawdę powinno istnieć coś takiego jak MapFragment, które zajmie się wątkami w tle, których MapView potrzebuje, tak myślę ... Więc jaka jest obecnie najlepsza praktyka, aby to zrobić?
Dzięki i pozdrowienia z Niemiec Valentin
Odpowiedzi:
Od 03.12.2012 Google udostępnił Google Maps Android API v2 . Teraz możesz zapomnieć o tych problemach. https://developers.google.com/maps/documentation/android/
Przykład z użyciem nowego API - https://developers.google.com/maps/documentation/android/start#add_a_map
Ten interfejs API będzie działał przynajmniej na Android API 8, więc używaj go;).
Teraz możesz po prostu użyć klasy fragmentu „com.google.android.gms.maps.MapFragment”. Wyświetli mapę w Twojej aktywności. Przykład układu z linku powyżej:
<?xml version="1.0" encoding="utf-8"?> <fragment xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" class="com.google.android.gms.maps.MapFragment"/>
źródło
Udało mi się rozwiązać ten problem, używając fragmentu TabHost.
Oto pomysł (krótko):
MainFragmentActivity
rozszerzaFragmentActivity
(z biblioteki wsparcia) i maMapFragment
.MyMapActivity
rozszerzaMapActivity
i zawieraMapView
.LocalActivityManagerFragment
zastępy niebieskieLocalActivityManager
MapFragment
rozciąga sięLocalActivityManagerFragment
.I
LocalActivityManager
zawiera w sobieMyMapActivity
aktywność.Przykładowa implementacja: https://github.com/inazaruk/map-fragment .
źródło
Intent i = new Intent(getActivity().getParent(), MyMapActivity.class); Window w = localActivityManager.startActivity("tag", i); currentView=w.getDecorView(); currentView.setVisibility(View.VISIBLE); currentView.setFocusableInTouchMode(true); ((ViewGroup) currentView).setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); this.contentView.addView(currentView);
LocalActivityManager
jest przestarzały, ale to tylko hack, ten problem zostanie rozwiązany poprawnie, gdy zdecydują się uwzględnić odpowiednie wsparcie dla map w fragmentach.Jak omówiono w Grupach dyskusyjnych Google , Peter Doyle stworzył własną bibliotekę kompatybilności obsługującą również Mapy Google. android-support-v4-googlemaps
Jednak jest też wada:
źródło
Tylko po to, żeby wyjaśnić odpowiedź. Wypróbowałem podejście sugerowane przez inazaruka i ChristophK. Właściwie możesz uruchomić dowolną aktywność we fragmencie - nie tylko mapy Google. Oto kod, który implementuje aktywność mapy google jako fragment dzięki inazaruk i ChristophK.
import com.actionbarsherlock.app.SherlockFragment; import android.view.Window; import android.app.LocalActivityManager; import android.content.Intent; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class MapFragment extends SherlockFragment { private static final String KEY_STATE_BUNDLE = "localActivityManagerState"; private LocalActivityManager mLocalActivityManager; protected LocalActivityManager getLocalActivityManager() { return mLocalActivityManager; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle state = null; if (savedInstanceState != null) { state = savedInstanceState.getBundle(KEY_STATE_BUNDLE); } mLocalActivityManager = new LocalActivityManager(getActivity(), true); mLocalActivityManager.dispatchCreate(state); } public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //This is where you specify you activity class Intent i = new Intent(getActivity(), GMapActivity.class); Window w = mLocalActivityManager.startActivity("tag", i); View currentView=w.getDecorView(); currentView.setVisibility(View.VISIBLE); currentView.setFocusableInTouchMode(true); ((ViewGroup) currentView).setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); return currentView; } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putBundle(KEY_STATE_BUNDLE, mLocalActivityManager.saveInstanceState()); } @Override public void onResume() { super.onResume(); mLocalActivityManager.dispatchResume(); } @Override public void onPause() { super.onPause(); mLocalActivityManager.dispatchPause(getActivity().isFinishing()); } @Override public void onStop() { super.onStop(); mLocalActivityManager.dispatchStop(); } @Override public void onDestroy() { super.onDestroy(); mLocalActivityManager.dispatchDestroy(getActivity().isFinishing()); } }
źródło
LocalActivityManager
(jak omówiono tutaj: code.google.com/p/android/issues/detail?id=15347 ), polega na rozszerzeniu wszystkichFragmentActivities
, co wydaje się jeszcze mniej optymalne.Wspaniałe wiadomości na ten temat od Google. Wydają dziś nowy interfejs API Map Google z mapami obiektów i MapFragment.
With this new API, adding a map to your Activity is as simple as: <fragment android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" class="com.google.android.gms.maps.MapFragment" />
źródło
Interfejs API Map Google nie jest częścią AOSP. Dopóki żaden pracownik Google nie odpowie, trudno będzie stwierdzić, czy w przyszłości pojawi się MapFragment.
Możliwą ograniczoną alternatywą jest użycie
WebViewFragment
i nadużywanie go w celu załadowania niestandardowegomaps.google.com
adresu URL.źródło
Hm szkoda, że Google jeszcze nie odpowiedział. FWIW, jeśli naprawdę musisz to zrobić, nie znalazłem innego sposobu niż:
Niech działanie zarządzania kartami dziedziczy z MapActivity, utwórz tam MapView programowo, niech mapfragment.xml zawiera ViewGroup i dodaj MapView do ViewGroup używając
Jest to oczywiście sprzeczne z ideą, że fragmenty mają być samowystarczalne, ale ...
źródło
Oto wersja MonoDroid ( Mono dla Androida ) bardzo uproszczonej MapFragment :
public class MapFragment : Fragment { // FOLLOW http://stackoverflow.com/questions/5109336/mapview-in-a-fragment-honeycomb private static String KEY_STATE_BUNDLE = "localActivityManagerState"; public override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); Bundle state = null; if (savedInstanceState != null) { state = savedInstanceState.GetBundle(KEY_STATE_BUNDLE); } mLocalActivityManager = new LocalActivityManager(Activity, true); mLocalActivityManager.DispatchCreate(state); } public override Android.Views.View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //This is where you specify you activity class Intent i = new Intent(Activity, typeof(SteamLocationMapActivity)); Window w = mLocalActivityManager.StartActivity("tag", i); View currentView=w.DecorView; currentView.Visibility = ViewStates.Visible; currentView.FocusableInTouchMode = true; ((ViewGroup) currentView).DescendantFocusability = DescendantFocusability.AfterDescendants; return currentView; } private LocalActivityManager mLocalActivityManager; protected LocalActivityManager GetLocalActivityManager() { return mLocalActivityManager; } public override void OnSaveInstanceState(Bundle outState) { base.OnSaveInstanceState(outState); outState.PutBundle(KEY_STATE_BUNDLE,mLocalActivityManager.SaveInstanceState()); } public override void OnResume() { base.OnResume(); mLocalActivityManager.DispatchResume(); } public override void OnPause() { base.OnPause(); mLocalActivityManager.DispatchPause(Activity.IsFinishing); } public override void OnStop() { base.OnStop(); mLocalActivityManager.DispatchStop(); } }
źródło
To rozwiązuje mój problem z dodawaniem MapView we fragmentach. https://github.com/petedoyle/android-support-v4-googlemaps
źródło
W nowej wersji ABS 4.0 nie ma wsparcia dla MapFragmentActivity, tutaj jest dobre rozwiązanie, aby mieć widok mapy we fragmencie!
https://xrigau.wordpress.com/2012/03/22/howto-actionbarsherlock-mapfragment-listfragment/#comment-21
źródło
Czy mogę uzyskać rozwiązanie:
źródło
Napisałem małą bibliotekę, łącząc rozwiązania oparte na LocalActivityManager z problemem MapFragment (zawiera również przykładową aplikację pokazującą różne sytuacje użycia):
https://github.com/coreform/android-tandemactivities
źródło