MapView во фрагменте (соты)
теперь, что окончательный пакет SDK с API-интерфейсы Google - что является лучшим способом, чтобы создать фрагмент с Положение? MapView нуждается в MapActivity, чтобы работать правильно.
имея действие, управляющее фрагментами, наследуется от MapActivity (плохое решение, потому что оно противоречит идее, что фрагменты являются автономными) и использовать обычный макет на основе xml не работает. Я получаю NullPointerException в MapActivity.setupMapView ():
E/AndroidRuntime( 597): Caused by: java.lang.NullPointerException E/AndroidRuntime( 597): at com.google.android.maps.MapActivity.setupMapView(MapActivity.java:400) E/AndroidRuntime( 597): at com.google.android.maps.MapView.(MapView.java:289) E/AndroidRuntime( 597): at com.google.android.maps.MapView.(MapView.java:264) E/AndroidRuntime( 597): at com.google.android.maps.MapView.(MapView.java:247)
моя вторая идея состояла в том, чтобы создать MapView программно и передать соответствующее действие (через getActivity ()) в качестве контекста конструктору MapView. Не работает:
E/AndroidRuntime( 834): Caused by: java.lang.IllegalArgumentException: MapViews can only be created inside instances of MapActivity. E/AndroidRuntime( 834): at com.google.android.maps.MapView.(MapView.java:291) E/AndroidRuntime( 834): at com.google.android.maps.MapView.(MapView.java:235) E/AndroidRuntime( 834): at de.foo.FinderMapFragment.onCreateView(FinderMapFragment.java:225) E/AndroidRuntime( 834): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:708) E/AndroidRuntime( 834): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:900) E/AndroidRuntime( 834): at android.app.FragmentManagerImpl.addFragment(FragmentManager.java:978) E/AndroidRuntime( 834): at android.app.Activity.onCreateView(Activity.java:4090) E/AndroidRuntime( 834): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:664)
действительно должно быть что-то вроде MapFragment, который заботится о фоновых потоках MapView, я думаю... Итак, какова текущая лучшая практика для этого?
спасибо и привет из Германии, Валентин
12 ответов:
по состоянию на 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.гуглить.андроид.СБМ.карты.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
выходитFragmentActivity
(из библиотеки поддержки) иMapFragment
.
MyMapActivity
выходитMapActivity
и содержатьMapView
.
LocalActivityManagerFragment
hostsLocalActivityManager
MapFragment
расширяетLocalActivityManagerFragment
.и
LocalActivityManager
содержитMyMapActivity
активность в нем.пример реализации:https://github.com/inazaruk/map-fragment.
Как уже обсуждалось в Группы Google, Питер Дойл построил пользовательскую библиотеку совместимости, поддерживающую Google Maps тоже. android-поддержка-v4-googlemaps
однако, есть и обратная сторона:
В настоящее время одним из недостатков является то, что все классы, расширяющие FragmentActivity, являются MapActivitys. Его можно сделать отдельным классом (т. е. FragmentMapActivity), но это требует некоторого рефакторинга кода FragmentActivity.
просто чтобы уточнить ответ. Я попробовал подход, предложенный иназаруком и Кристофом. На самом деле вы можете запустить любую деятельность в фрагменте - не только google maps. Вот код, который реализует активность google map в виде фрагмента благодаря 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()); } }
отличные новости от 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" />
Google Maps API не является частью AOSP. Пока ни один Гуглер не отвечает, едва ли можно сказать, будет ли MapFragment в будущем.
возможной ограниченной альтернативой является использование
WebViewFragment
и злоупотреблять им, чтобы загрузить пользовательскийmaps.google.com
URL.
хм очень плохо, что Google еще не ответил. FWIW если вам действительно нужно это сделать я не нашел другого способа, чем:
есть вкладка управление деятельностью наследовать от MapActivity, создать MapView там программно, есть mapfragment.xml содержит ViewGroup и добавляет MapView в ViewGroup с помощью
((ViewGroup) getFragmentManager().findFragmentById(R.id.finder_map_fragment).getView()).addView(mapView);;очевидно, что это сильно противоречит идее о том, что фрагменты должны быть самодостаточными, но ...
здесь MonoDroid (Mono для Android) версия очень упрощенный 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(); } }
Это решает мою проблему при добавлении MapView во фрагментах. https://github.com/petedoyle/android-support-v4-googlemaps
с новой версией ABS 4.0, нет support для MapFragmentActivity, вот хорошее решение для того, чтобы иметь mapview во фрагменте!
https://xrigau.wordpress.com/2012/03/22/howto-actionbarsherlock-mapfragment-listfragment/#comment-21
могу я получить решение:
- создать класс TempFragmentActivity расширяет MapActivity
- внутри TempFragmentActivity есть объект MapView (например, normal define в xml)
- снимите этом положение объекта форма родителя(макет)(ничтожными позже исключение)
- держите этот объект MapView где-то(например: Статический член TempFragmentActivity)
- в вашем фрагменте добавьте этот объект MapView с помощью кода (не определяйте в xml) в некоторые LinearLayout