Теперь, когда окончательный SDK выпущен с API Google, как лучше всего создать фрагмент с помощью MapView? MapView нуждается в MapActivity для правильной работы.
Если Activity управляет фрагментами, унаследованными от MapActivity (плохое решение, потому что оно противоречит идее, что фрагменты являются самодостаточными) и использовать обычный макет на основе xml, не работает. Я получаю исключение NullPointerException в MapActivity.setupMapView ():
E / AndroidRuntime (597): вызвано: java.lang.NullPointerException E / AndroidRuntime (597): в com.google.android.maps.MapActivity.setupMapView (MapActivity.java:400) E / AndroidRuntime (597): на com.google.android.maps.MapView. (MapView.java:289) E / AndroidRuntime (597): в com.google.android.maps.MapView. (MapView.java:264) E / AndroidRuntime (597): на com.google.android.maps.MapView. (MapView.java:247)
Моя вторая идея заключалась в том, чтобы создать MapView программно и передать связанное действие (через getActivity ()) в качестве контекста в конструктор MapView. Не работает:
E / AndroidRuntime (834): вызвано: java.lang.IllegalArgumentException: MapViews можно создавать только внутри экземпляров MapActivity. E / AndroidRuntime (834): в com.google.android.maps.MapView. (MapView.java:291) E / AndroidRuntime (834): в com.google.android.maps.MapView. (MapView.java:235) E / AndroidRuntime (834): в de.foo.FinderMapFragment.onCreateView (FinderMapFragment.java:225) E / AndroidRuntime (834): в android.app.FragmentManagerImpl.moveToState (FragmentManager.java:708) E / AndroidRuntime (834): в android.app.FragmentManagerImpl.moveToState (FragmentManager.java:900) E / AndroidRuntime (834): в android.app.FragmentManagerImpl.addFragment (FragmentManager.java:978) E / AndroidRuntime (834): в android.app.Activity.onCreateView (Activity.java:4090) E / AndroidRuntime (834): в android.view.LayoutInflater.createViewFromTag (LayoutInflater.java:664)
На самом деле должно быть что-то вроде MapFragment, которое заботится о фоновых потоках, которые необходимы MapView, я думаю ... Итак, каковы текущие рекомендации для этого?
Спасибо и привет из Германии, Валентин
Ответы:
По состоянию на 03.12.2012 Google выпустил Google Maps Android API v2 . Теперь вы можете забыть об этих проблемах. https://developers.google.com/maps/documentation/android/
Пример использования нового API - https://developers.google.com/maps/documentation/android/start#add_a_map
Этот API будет работать как минимум для Android API 8, поэтому используйте его;).
Итак, теперь вы можете просто использовать класс фрагмента com.google.android.gms.maps.MapFragment. Он отобразит карту в вашей деятельности. Пример макета по ссылке выше:
<?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"/>
источник
Мне удалось решить эту проблему, используя TabHost во фрагменте.
Вот идея (вкратце):
MainFragmentActivity
extendsFragmentActivity
(из библиотеки поддержки) и имеетMapFragment
.MyMapActivity
расширяетсяMapActivity
и содержитMapView
.LocalActivityManagerFragment
хозяеваLocalActivityManager
MapFragment
расширяетсяLocalActivityManagerFragment
.И
LocalActivityManager
содержитMyMapActivity
в себе активность.Пример реализации: https://github.com/inazaruk/map-fragment .
источник
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
это устарело, но это просто взлом, эта проблема должна быть решена должным образом, когда они решат включить соответствующую поддержку карт во фрагменты.Как обсуждалось в группах Google , Питер Дойл создал специальную библиотеку совместимости, также поддерживающую Google Maps. поддержка Android-v4-googlemaps
Однако есть и обратная сторона:
источник
Просто чтобы уточнить ответ. Я попробовал подход, предложенный inazaruk и ChristophK. На самом деле вы можете запускать во фрагменте любую активность, а не только карты Google. Вот код, который реализует активность карты Google как фрагмент благодаря inazaruk и 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()); } }
источник
LocalActivityManager
(как обсуждается здесь: code.google.com/p/android/issues/detail?id=15347 ), включает расширение всегоFragmentActivities
, что кажется еще менее оптимальным.Отличные новости от Google по этому поводу. Сегодня они выпускают новый Google Maps API с внутренними картами и 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" />
источник
API Карт Google не является частью AOSP. Пока никто из сотрудников Google не отвечает, невозможно сказать, будет ли MapFragment в будущем.
Возможная ограниченная альтернатива - использовать
WebViewFragment
и злоупотреблять им для загрузки настраиваемогоmaps.google.com
URL.источник
Жаль, что Google еще не ответил. FWIW, если вам действительно нужно это сделать, я не нашел другого способа, кроме:
Унаследовать действие управления вкладками от MapActivity, программно создать там MapView, включить в mapfragment.xml ViewGroup и добавить MapView в ViewGroup, используя
Ясно, что это резко противоречит идее, что фрагменты должны быть самодостаточными, но ...
источник
Вот версия очень упрощенного MapFragment для MonoDroid ( Mono для Android ) :
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(); } }
источник
Это решает мою проблему с добавлением MapView во фрагменты. https://github.com/petedoyle/android-support-v4-googlemaps
источник
В новой версии ABS 4.0 нет поддержки для MapFragmentActivity, вот хорошее решение для отображения карты во фрагменте!
https://xrigau.wordpress.com/2012/03/22/howto-actionbarsherlock-mapfragment-listfragment/#comment-21
источник
Могу я получить решение:
источник
Я написал небольшую библиотеку, объединяющую решения на основе LocalActivityManager для проблемы MapFragment (также включает пример приложения, показывающего различные ситуации использования):
https://github.com/coreform/android-tandemactivities
источник