使用Maps API v2以编程方式初始化MapFragment

我试图添加一个MapFragment到我目前的片段。 嵌套片段的使用仅限于FragmentTransactions,不能在布局中使用xml标签。 另外,当用户按下一个button时,我希望它被添加到主碎片中。 所以,当用户按下button并将其添加到适当的位置时,我使用getInstance()以编程方式创buildMapFragment。 它显示正确,迄今如此好。

问题是,在附加MapFragment之后,我需要获取对GoogleMap的引用来放置标记 ,但getMap()方法返回null(因为片段的onCreateView()尚未被调用)。

我查看了演示示例代码,发现他们使用的解决scheme是在onCreate()初始化MapFragment,然后在调用onCreateView()之后,在onResume()获取对GoogleMap的引用。

我需要在MapFragment初始化后立即获取GoogleMap的引用,因为我希望用户能够使用button显示或隐藏地图。 我知道一个可能的解决scheme是如上所述在开始时创build地图,并且只是将其可见性设置为消失,但是我希望地图在默认情况下是closures的,所以如果没有明确询问,则不需要用户的带宽为了它。

我尝试过使用MapsInitializer ,但也无法正常工作。 我有点卡住了 有任何想法吗? 这是我的testing代码到目前为止:

 public class ParadaInfoFragment extends BaseDBFragment { // BaseDBFragment is just a SherlockFragment with custom utility methods. private static final String MAP_FRAGMENT_TAG = "map"; private GoogleMap mMap; private SupportMapFragment mMapFragment; private TextView mToggleMapa; private boolean isMapVisible = false; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_parada_info, container, false); mToggleMapa = (TextView) v.findViewById(R.id.parada_info_map_button); return v; } @Override public void onStart() { super.onStart(); mToggleMapa.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!isMapVisible) { openMap(); } else { closeMap(); } isMapVisible = !isMapVisible; } }); } private void openMap() { // Creates initial configuration for the map GoogleMapOptions options = new GoogleMapOptions().camera(CameraPosition.fromLatLngZoom(new LatLng(37.4005502611301, -5.98233461380005), 16)) .compassEnabled(false).mapType(GoogleMap.MAP_TYPE_NORMAL).rotateGesturesEnabled(false).scrollGesturesEnabled(false).tiltGesturesEnabled(false) .zoomControlsEnabled(false).zoomGesturesEnabled(false); // Modified from the sample code: // It isn't possible to set a fragment's id programmatically so we set a // tag instead and search for it using that. mMapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentByTag(MAP_FRAGMENT_TAG); // We only create a fragment if it doesn't already exist. if (mMapFragment == null) { // To programmatically add the map, we first create a // SupportMapFragment. mMapFragment = SupportMapFragment.newInstance(options); // Then we add it using a FragmentTransaction. FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction(); fragmentTransaction.add(R.id.parada_info_map_container, mMapFragment, MAP_FRAGMENT_TAG); fragmentTransaction.commit(); } // We can't be guaranteed that the map is available because Google Play // services might not be available. setUpMapIfNeeded(); //XXX Here, getMap() returns null so the Marker can't be added // The map is shown with the previous options. } private void closeMap() { FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction(); fragmentTransaction.remove(mMapFragment); fragmentTransaction.commit(); } private void setUpMapIfNeeded() { // Do a null check to confirm that we have not already instantiated the // map. if (mMap == null) { // Try to obtain the map from the SupportMapFragment. mMap = mMapFragment.getMap(); // Check if we were successful in obtaining the map. if (mMap != null) { mMap.addMarker(new MarkerOptions().position(new LatLng(37.4005502611301, -5.98233461380005)).title("Marker")); } } } } 

谢谢

好AnderWebs给了我一个在Google+中的答案,但他太懒惰了…. emm忙再次写在这里,所以这里是简短的版本:扩展MapFragment类并重写onCreateView()方法。 在完成这个方法之后,我们可以获得一个非空的引用来定位GoogleMap对象。

这是我特别的解决scheme:

 public class MiniMapFragment extends SupportMapFragment { private LatLng mPosFija; public MiniMapFragment() { super(); } public static MiniMapFragment newInstance(LatLng posicion){ MiniMapFragment frag = new MiniMapFragment(); frag.mPosFija = posicion; return frag; } @Override public View onCreateView(LayoutInflater arg0, ViewGroup arg1, Bundle arg2) { View v = super.onCreateView(arg0, arg1, arg2); initMap(); return v; } private void initMap(){ UiSettings settings = getMap().getUiSettings(); settings.setAllGesturesEnabled(false); settings.setMyLocationButtonEnabled(false); getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(mPosFija,16)); getMap().addMarker(new MarkerOptions().position(mPosFija).icon(BitmapDescriptorFactory.fromResource(R.drawable.marker))); } } 

现在在我之前的片段类中

 mMapFragment = MiniMapFragment.newInstance(new LatLng(37.4005502611301, -5.98233461380005)); 

可能还不完美,因为显示地图时屏幕闪烁。 但不知道问题是因为这个还是别的。

谢谢,发现这非常有帮助。 我发布了我稍作修改的解决scheme,因为在地图准备就绪的时候,我告诉父Fragment更清晰。 这个方法也可以在saveInstanceState / restoreInstanceState循环中使用。

 public class CustomMapFragment extends SupportMapFragment { private static final String LOG_TAG = "CustomMapFragment"; public CustomMapFragment() { super(); } public static CustomMapFragment newInstance() { CustomMapFragment fragment = new CustomMapFragment(); return fragment; } @Override public View onCreateView(LayoutInflater arg0, ViewGroup arg1, Bundle arg2) { View v = super.onCreateView(arg0, arg1, arg2); Fragment fragment = getParentFragment(); if (fragment != null && fragment instanceof OnMapReadyListener) { ((OnMapReadyListener) fragment).onMapReady(); } return v; } /** * Listener interface to tell when the map is ready */ public static interface OnMapReadyListener { void onMapReady(); } } 

用作嵌套片段:

 public class ParentFragment extends Fragment implements OnMapReadyListener { ... mMapFragment = CustomMapFragment.newInstance(); getChildFragmentManager().beginTransaction().replace(R.id.mapContainer, mMapFragment).commit(); @Override public void onMapReady() { mMap = mMapFragment.getMap(); } ... } 

希望它可以帮助别人。

这是我的解决scheme,我从之前发布的代码中获取灵感,并将其清理干净。 我还添加了GoogleMapOptions参数的静态方法。

 public class GoogleMapFragment extends SupportMapFragment { private static final String SUPPORT_MAP_BUNDLE_KEY = "MapOptions"; public static interface OnGoogleMapFragmentListener { void onMapReady(GoogleMap map); } public static GoogleMapFragment newInstance() { return new GoogleMapFragment(); } public static GoogleMapFragment newInstance(GoogleMapOptions options) { Bundle arguments = new Bundle(); arguments.putParcelable(SUPPORT_MAP_BUNDLE_KEY, options); GoogleMapFragment fragment = new GoogleMapFragment(); fragment.setArguments(arguments); return fragment; } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mCallback = (OnGoogleMapFragmentListener) getActivity(); } catch (ClassCastException e) { throw new ClassCastException(getActivity().getClass().getName() + " must implement OnGoogleMapFragmentListener"); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); if (mCallback != null) { mCallback.onMapReady(getMap()); } return view; } private OnGoogleMapFragmentListener mCallback; } 

使用模式如下:

 public class MyMapActivity implements OnGoogleMapFragmentListener { ... @Override public void onMapReady(GoogleMap map) { mUIGoogleMap = map; ... } ... private GoogleMap mUIGoogleMap; } 

不需要Cutomize SupportMapFragment你可以直接使用下面这段代码,

 FragmentManager fm = getSupportFragmentManager(); // getChildFragmentManager inside fragments. CameraPosition cp = new CameraPosition.Builder() .target(initialLatLng) // your initial co-ordinates here. like, LatLng initialLatLng .zoom(zoom_level) .build(); SupportMapFragment mapFragment = SupportMapFragment.newInstance(new GoogleMapOptions().camera(cp)); fm.beginTransaction().replace(R.id.rl_map, mapFragment).commit(); 

添加这段代码layout

 <RelativeLayout android:id="@+id/rl_map" android:layout_width="fill_parent" android:layout_height="fill_parent" /> 

这将直接在特定Location加载GoogleMap ,即initialLatLng。