MapView中的片段(蜂窝)

现在,最终的SDK与谷歌apis – 什么是最好的方式来创build一个MapView的片段? MapView需要MapActivity才能正常工作。

让pipe理碎片的活动从MapActivityinheritance(糟糕的解决scheme,因为它违背碎片自包含的想法)并使用常规的基于xml的布局不起作用。 我在MapActivity.setupMapView()中得到一个NullPointerException:

 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)

我的第二个想法是以编程方式创buildMapView,并将相关活动(通过getActivity())作为上下文传递给MapView构造函数。 不起作用:

 E / AndroidRuntime(834):引起:java.lang.IllegalArgumentException:MapViews只能在MapActivity的实例内部创build。
 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需要我猜…那么目前最好的做法是什么呢?

感谢德国Valentin的问候

截至2012年12月3日,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将至less适用于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来解决这个问题。

这个想法(简要):

  1. MainFragmentActivity扩展FragmentActivity (从支持库),并有MapFragment

  2. MyMapActivity扩展了MapActivity并包含MapView

  3. LocalActivityManagerFragment承载LocalActivityManager

  4. MapFragment扩展了LocalActivityManagerFragment

  5. LocalActivityManager包含MyMapActivity活动。

示例实现: https : //github.com/inazaruk/map-fragment 。


在这里输入图像说明

正如Google小组讨论的那样,Peter Doyle也构build了支持Google Maps的自定义兼容性库。 Android的支持-V4-谷歌地图

然而,也有一个缺点:

目前,一个不足之处是扩展FragmentActivity的所有类都是MapActivity。 它可以做一个单独的类(即FragmentMapActivity),但它需要重构的FragmentActivity代码。

只是为了澄清答案。 我尝试了inazaruk和ChristophKbuild议的方法。 其实你可以运行一个片段的任何活动 – 不只是谷歌地图。 这里是用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的一部分。 只要没有Google员工的回应,几乎无法确定将来是否会有MapFragment。

可能有限的替代方法是使用WebViewFragment并滥用它来加载自定义的maps.google.comurl。

呃太糟糕了,谷歌还没有回应。 FWIW如果你真的需要这样做,我发现没有其他办法比:

让选项卡pipe理活动从MapActivityinheritance,以编程方式在其中创buildMapView,让mapfragment.xml包含ViewGroup并使用MapView将ViewView添加到ViewGroup

 ((ViewGroup))getFragmentManager()。findFragmentById(R.id.finder_map_fragment).getView())。addView(mapView);;

显然,这强烈反对这样的想法,即碎片是自足的,但…

这是一个非常简化的MapFragmentMonoDroidMono for 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,这是一个很好的解决scheme,在一个片段的mapview!

https://xrigau.wordpress.com/2012/03/22/howto-actionbarsherlock-mapfragment-listfragment/#comment-21

我可以得到解决scheme:

  1. 创build类TempFragmentActivity扩展了MapActivity
  2. TempFragmentActivity内部有一个MapView对象(就像xml中的普通定义一样)
  3. 删除此MapView对象表单父项(LinearLayout)(void后来的exception)
  4. 把这个MapView对象保存在某个地方(例如:TempFragmentActivity的静态成员)
  5. 在您的Fragment中,使用代码(不要在xml中定义)将此MapView对象添加到某个LinearLayout中

我写了一个小库,将基于LocalActivityManager的解决scheme混合到MapFragment问题中(还包括一个显示各种使用情况的示例应用程序):

https://github.com/coreform/android-tandemactivities