返回地图时,带有MapFragment黑屏的Android DrawerLayout

时间:2013-10-18 03:23:44

标签: java android android-fragments drawerlayout mapfragment

我一直在试验android.support.v4.widget.DrawerLayout并有4个片段可供抽屉选择。地图最初加载时没有任何问题,但是当我打开抽屉并更换碎片时,我无法返回地图。我只是得到一个黑屏。 Logcat显示片段已重新创建,但我什么都没得到。只是一个空白的黑屏。我可以毫无问题地在其他片段之间切换。我究竟做错了什么?我的项目的Min API为14。

我从ExploreMap加载MainActivity.java(片段):

        if (position == 0){
            ExploreMap exMap = new ExploreMap();
            exMap.setRetainInstance(true);
            getFragmentManager().beginTransaction().replace(R.id.content_frame, exMap).commit();
        }

ExploreMap.java我执行以下操作

public class ExploreMap extends Fragment implements OnInfoWindowClickListener, android.location.LocationListener, OnMapLongClickListener{

 private LocationManager mLocManager;
 private GoogleMap mMap;
 private MapFragment mMapFragment;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        FragmentManager fm = getActivity().getFragmentManager();
        mMapFragment = (MapFragment) fm.findFragmentById(R.id.map);


        if (mMapFragment == null) {
            mMapFragment = MapFragment.newInstance();
            fm.beginTransaction().replace(R.id.map, mMapFragment).commit();
        }


        if (savedInstanceState == null) {
            // First incarnation of this activity.
            mMapFragment.setRetainInstance(true);
        }else {
            // Reincarnated activity. The obtained map is the same map instance in the previous
            // activity life cycle. There is no need to reinitialize it.
            mMap = mMapFragment.getMap();
        }

        createMapIfNeeded();


       return inflater.inflate(R.layout.explore_map_layout, container, false);
    }




    @Override
    public void onResume() {
        super.onResume();
        //create the map
       createMapIfNeeded();  
    }





    private void createMapIfNeeded(){

        if(mLocManager == null){
            mLocManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
            mLocManager.requestLocationUpdates(
                       LocationManager.NETWORK_PROVIDER,
                       MIN_TIME_BW_UPDATES,
                       MIN_DISTANCE_CHANGE_FOR_UPDATES,
                       this);
        }

         //locmanager can return null if no last known locaiton is available.
        location = mLocManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);


        //if a map has not already been instantiated it'll return null
        if(mMap == null){
            //instantiate map
            mMap = mMapFragment.getMap();
            //check it has been instantiated

            if(mMap != null){   
                mMap.setOnMapLongClickListener(this);
                mMap.setOnInfoWindowClickListener(this);
                mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
                mMap.setMyLocationEnabled(true);

                //Manipulate map here (add coordinates/polylines from trip etc etc.)
                UiSettings setting = mMap.getUiSettings();
                setting.setTiltGesturesEnabled(true);
                setting.setRotateGesturesEnabled(true);
                setting.setZoomControlsEnabled(true);
                setting.setMyLocationButtonEnabled(true);

                if(location != null){
                CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 15);
                mMap.animateCamera(cu);
                }
            }
        }  
    }

XML如下

 mainactivity_layout.xml
<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- As the main content view, the view below consumes the entire
         space available using match_parent in both dimensions. -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- android:layout_gravity="start" tells DrawerLayout to treat
         this as a sliding drawer on the left side for left-to-right
         languages and on the right side for right-to-left languages.
         The drawer is given a fixed width in dp and extends the full height of
         the container. A solid background is used for contrast
         with the content view. -->
    <ListView
        android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:background="#111"/>
</android.support.v4.widget.DrawerLayout>

exploremap_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >


        <FrameLayout
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

3 个答案:

答案 0 :(得分:2)

经过几天的撞击我的头后,我发现了问题,或者我应该说问题。 tsp建议使用上面的库也可以使用,但是我想让它与Google提供的android.support.v4.widget.DrawerLayout一起使用。

问题是2倍。

  1. 我正在使用嵌套片段,而在离开ExploreMap片段时我没有删除子(map)片段。我的层次结构是:Activity(DrawerLayout) - &gt; ExploreMap(A Fragment) - &gt; MapFragment。打开抽屉并更换片段时,我没有从ExploreMap(片段)中删除MapFragment。由于setRetainInstance(true),原始MapFragment实例保留在内存中。由于原因,我仍然不完全理解,一旦返回到ExploreMap片段,MapFragment的原始实例就不会重新出现。为了解决这个问题,我在MapFragment最初创建时为其指定了一个名为“mapfrag”的String标记,并将变量设置为public static。接下来在Activity中,抽屉代码用于切换片段,我执行findFragmentByTag()并测试其null,如果它不为null则删除MapFragment。
  2. 然而#1只能让你走到一半,因为当你回到ExploreMap时它会重新出现,但是MapFragment中的基础GoogleMap一直向我返回null而我无法获得地图完全配置。

    2)我发现了这篇文章MapFragment return null。建议扩展自己的MapFragment并实现一个接口,以便在MapFragment创建完成时通知,几乎可以保证非空的GoogleMap。

    和WHAMMY !!你有谷歌抽屉布局工作谷歌地图。这是我完整的工作代码。

    MainActivity.java
     if (position == 0){
                    exMap = new ExploreMap();
                    exMap.setRetainInstance(true);
                    getFragmentManager().beginTransaction().replace(R.id.content_frame, exMap).commit();
                }
                if(position == 1){  
                    //remove map frag here instead of in explore map
                    Fragment f = getFragmentManager().findFragmentByTag("mapfrag");
                    if(f != null){
                         getFragmentManager().beginTransaction().remove(f).commit();
                    }
    
                    Ms fragment = new Ms();
                    getFragmentManager().beginTransaction().replace(R.id.content_frame, fragment).commit(); 
                }
                if(position == 2){
                    Fragment f = getFragmentManager().findFragmentByTag("mapfrag");
                    if(f != null){
                         getFragmentManager().beginTransaction().remove(f).commit();
                    }
                    Settings fragment = new Settings();
                    getFragmentManager().beginTransaction().replace(R.id.content_frame, fragment).commit(); 
                }
                if(position == 3){
                    Fragment f = getFragmentManager().findFragmentByTag("mapfrag");
                    if(f != null){
                         getFragmentManager().beginTransaction().remove(f).commit();
                    }
                    About fragment = new About();
                    getFragmentManager().beginTransaction().replace(R.id.content_frame, fragment).commit(); 
                }
    
    ExploreMap.java

    中的

    public class ExploreMap extends Fragment implements MyMapFragment.MapCallback,  OnInfoWindowClickListener, android.location.LocationListener, OnMapLongClickListener{
    
         private LocationManager mLocManager;
         private GoogleMap mMap;
         public static MyMapFragment mMapFragment;
    
    @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                View v = inflater.inflate(R.layout.explore_map_layout, container, false); 
    
    
                FragmentManager fm = getActivity().getFragmentManager();
                mMapFragment = (MyMapFragment) fm.findFragmentById(R.id.map_framelayout);
    
    
                if (mMapFragment == null) {
                    mMapFragment = new MyMapFragment();
                    mMapFragment.setRetainInstance(true);
                    mMapFragment.setMapCallback(this);
                    fm.beginTransaction().replace(R.id.map_framelayout, mMapFragment,"mapfrag").commit();
                }
    
                createMapIfNeeded();
    
                return v;
            }
    
    
    
            @Override
            public void onMapReady(GoogleMap map) {
                createMapIfNeeded();
            }   
    
    private void createMapIfNeeded(){
    
                if(mLocManager == null){
                    mLocManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
                    mLocManager.requestLocationUpdates(
                               LocationManager.NETWORK_PROVIDER,
                               MIN_TIME_BW_UPDATES,
                               MIN_DISTANCE_CHANGE_FOR_UPDATES,
                               this);
                }
    
                 //locmanager can return null if no last known locaiton is available.
                location = mLocManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
    
    
                //if a map has not already been instantiated it'll return null
                if(mMap == null){
                    //instantiate map
                    mMap = mMapFragment.getMap();
    
    
                    //check it has been instantiated
                    if(mMap != null){
                        mMap.setOnMapLongClickListener(this);
                        mMap.setOnInfoWindowClickListener(this);
                        mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
                        mMap.setMyLocationEnabled(true);
    
                        //Manipulate map here (add coordinates/polylines from trip etc etc.)
                        UiSettings setting = mMap.getUiSettings();
                        setting.setTiltGesturesEnabled(true);
                        setting.setRotateGesturesEnabled(true);
                        setting.setZoomControlsEnabled(true);
                        setting.setMyLocationButtonEnabled(true);
    
                        if(location != null){
                        CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 15);
                        mMap.animateCamera(cu);
                        }
                    }
                }  
            }
    

    现在MyMapFragment.java

    public class MyMapFragment extends MapFragment{
    
    
    
          private MapCallback callback;
    
          public static interface MapCallback
          {
             public void onMapReady(GoogleMap map);
          }
    
          public void setMapCallback(MapCallback callback)
          {
            this.callback = callback;
          }
    
          @Override public void onActivityCreated(Bundle savedInstanceState)
          {
              super.onActivityCreated(savedInstanceState);
             if(callback != null) callback.onMapReady(getMap());     
          }
    
    
    }
    

    CHEERS !!!

答案 1 :(得分:0)

答案 2 :(得分:-1)

在邮件线程上找到此问题的简便解决方法。这解决了我的问题。 使用相对布局并将此透明视图直接放在上面 你的地图片段。示例:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

    <fragment
      android:id="@+id/map"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      class="com.google.android.gms.maps.SupportMapFragment"/>

    <View
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:background="@android:color/transparent" />
</RelativeLayout>