Android的DrawerLayout与MapFragment黑屏返回到地图时 [英] Android DrawerLayout with MapFragment black screen when returning to map

查看:715
本文介绍了Android的DrawerLayout与MapFragment黑屏返回到地图时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在 android.support.v4.widget.DrawerLayout 试验并有4个片段从抽屉选择。该地图最初没有问题,但是加载当我打开抽屉,并更改片段我无法再回到地图。我只是得到一个黑色的屏幕。 logcat的正显示出是重新创建的片段,但我还没有得到什么。只是黑屏。我可以没有问题的其它片段之间切换。我究竟做错了什么?我的项目有14敏API。

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

 如果(位置== 0){
            ExploreMap exMap =新ExploreMap();
            exMap.setRetainInstance(真);
            。getFragmentManager()调用BeginTransaction()取代(R.id.content_frame,exMap).commit()。
        }

ExploreMap.java 我做以下

 公共类ExploreMap扩展片段实现OnInfoWindowClickListener,android.location.LocationListener,OnMapLongClickListener { 私人的LocationManager mLocManager;
 私人GoogleMap的MMAP;
 私人MapFragment mMapFragment;    @覆盖
    公共查看onCreateView(LayoutInflater充气器,容器的ViewGroup,捆绑savedInstanceState){        FragmentManager FM = getActivity()getFragmentManager()。
        mMapFragment =(MapFragment)fm.findFragmentById(R.id.map);
        如果(mMapFragment == NULL){
            mMapFragment = MapFragment.newInstance();
            fm.beginTransaction()取代(R.id.map,mMapFragment).commit()。
        }
        如果(savedInstanceState == NULL){
            //本次活动的第一个化身。
            mMapFragment.setRetainInstance(真);
        }其他{
            //转世活动。得到的地图是在previous在同一个地图实例
            //活动的生命周期。没有必要重新初始化它。
            MMAP = mMapFragment.getMap();
        }        createMapIfNeeded();
       返回inflater.inflate(R.layout.explore_map_layout,集装箱,FALSE);
    }
    @覆盖
    公共无效onResume(){
        super.onResume();
        //创建地图
       createMapIfNeeded();
    }    私人无效createMapIfNeeded(){        如果(mLocManager == NULL){
            mLocManager =(的LocationManager)getActivity()getSystemService(Context.LOCATION_SERVICE)。
            mLocManager.requestLocationUpdates(
                       LocationManager.NETWORK_PROVIDER,
                       MIN_TIME_BW_UPDATES,
                       MIN_DISTANCE_CHANGE_FOR_UPDATES,
                       这个);
        }         // locmanager可以返回null如果没有最后已知locaiton可用。
        位置= mLocManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        //如果地图还没有被实例化,它会返回null
        如果(MMAP == NULL){
            //实例图
            MMAP = mMapFragment.getMap();
            //检查它已被实例化            如果(MMAP!= NULL){
                mMap.setOnMapLongClickListener(本);
                mMap.setOnInfoWindowClickListener(本);
                mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
                mMap.setMyLocationEnabled(真);                //此处操纵地图(添加坐标/从跳闸等等等等折线)
                UiSettings设定值= mMap.getUiSettings();
                setting.setTiltGesturesEnabled(真);
                setting.setRotateGesturesEnabled(真);
                setting.setZoomControlsEnabled(真);
                setting.setMyLocationButtonEnabled(真);                如果(位置!= NULL){
                的CameraUpdate立方米= CameraUpdateFactory.newLatLngZoom(新经纬度(location.getLatitude(),location.getLongitude()),15);
                mMap.animateCamera(CU);
                }
            }
        }
    }

XML的是如下:

  mainactivity_layout.xml
< android.support.v4.widget.DrawerLayout
    的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:ID =@ + ID / drawer_layout
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent>    <! - 为主要内容的视图,该视图下方消耗约占整个
         使用match_parent在两个维度可用空间。 - >
    <的FrameLayout
        机器人:ID =@ + ID / content_frame
        机器人:layout_width =match_parent
        机器人:layout_height =match_parent/>    < - 安卓!layout_gravity =启动讲述DrawerLayout治疗
         以此为在左侧的滑动抽屉左到右
         语言和右侧从右到左的语言。
         抽屉被赋予了DP一个固定的宽度并延伸的全高
         的容器。的扎实的背景是用于对比
         与内容视图。 - >
    < ListView控件
        机器人:ID =@ + ID / left_drawer
        机器人:layout_width =240dp
        机器人:layout_height =match_parent
        机器人:layout_gravity =开始
        机器人:choiceMode =singleChoice
        机器人:分=@机器人:彩色/透明
        机器人:dividerHeight =0dp
        机器人:背景=#111/>
< /android.support.v4.widget.DrawerLayout>

exploremap_layout.xml

 < LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent>
        <的FrameLayout
        机器人:ID =@ + ID /图
        机器人:layout_width =match_parent
        机器人:layout_height =match_parent/>
< / LinearLayout中>


解决方案

在打我的头撞在墙上的日子里,我想通了这个问题,或者我应该说的问题。用小勺上述图书馆其中工程太,但是我希望得到这个工作与谷歌提供的 android.support.v4.widget.DrawerLayout 建议。

问题是2倍。


  1. 我使用嵌套的片段,并在离开ExploreMap片段时,我并没有删除子(图)片段。我hiearchy是:活动(DrawerLayout) - > ExploreMap(A片段) - > MapFragment。当打开抽屉和改变片段我是不是从本ExploreMap(片段)的MapFragment。原来MapFragment实例保持在内存中,由于 setRetainInstance(真)。至于原因,我还是不完全了解MapFragment的原始实例将不会再出现一次久违的ExploreMap片段。为了解决这个我分配MapFragment字符串变量我叫mapfrag时,最初创建它,并设置变量为公共静态。接下来的活动,那里的抽屉code是切换的片段,我做了 findFragmentByTag()和测试,如果它的,删除MapFragment,如果它不为空。

然而#1只让你的一半,因为它会在地图再次出现,当你回到ExploreMap但是底层的GoogleMap 从MapFragment保持返回null来我,我不能让所有配置的地图。

2)我发现这个职位 MapFragment返回null 。其中建议扩大自己MapFragment和实现一个接口来通知时所创建的MapFragment完成后,pretty多少保障非空的GoogleMap的。

和打击!你在谷歌的抽屉布局的工作谷歌地图。这里是我完整的工作code。

  MainActivity.java
 如果(位置== 0){
                exMap =新ExploreMap();
                exMap.setRetainInstance(真);
                。getFragmentManager()调用BeginTransaction()取代(R.id.content_frame,exMap).commit()。
            }
            如果(位置== 1){
                //删除地图断枝在这里,而不是在探索地图
                片f = getFragmentManager()findFragmentByTag(mapfrag);
                如果(F!= NULL){
                     。getFragmentManager()调用BeginTransaction()删除(F).commit();
                }                女士片段=新的MS();
                。getFragmentManager()调用BeginTransaction()取代(R.id.content_frame,片段).commit();
            }
            如果(位置== 2){
                片f = getFragmentManager()findFragmentByTag(mapfrag);
                如果(F!= NULL){
                     。getFragmentManager()调用BeginTransaction()删除(F).commit();
                }
                设置片段=新设置();
                。getFragmentManager()调用BeginTransaction()取代(R.id.content_frame,片段).commit();
            }
            如果(位置== 3){
                片f = getFragmentManager()findFragmentByTag(mapfrag);
                如果(F!= NULL){
                     。getFragmentManager()调用BeginTransaction()删除(F).commit();
                }
                关于片段=新约();
                。getFragmentManager()调用BeginTransaction()取代(R.id.content_frame,片段).commit();
            }

ExploreMap.java

 公共类ExploreMap扩展片段实现MyMapFragment.MapCallback,OnInfoWindowClickListener,android.location.LocationListener,OnMapLongClickListener {     私人的LocationManager mLocManager;
     私人GoogleMap的MMAP;
     公共静态MyMapFragment mMapFragment;@覆盖
        公共查看onCreateView(LayoutInflater充气器,容器的ViewGroup,捆绑savedInstanceState){
            视图V = inflater.inflate(R.layout.explore_map_layout,集装箱,FALSE);
            FragmentManager FM = getActivity()getFragmentManager()。
            mMapFragment =(MyMapFragment)fm.findFragmentById(R.id.map_framelayout);
            如果(mMapFragment == NULL){
                mMapFragment =新MyMapFragment();
                mMapFragment.setRetainInstance(真);
                mMapFragment.setMapCallback(本);
                。fm.beginTransaction()取代(R.id.map_framelayout,mMapFragment,mapfrag)提交()。
            }            createMapIfNeeded();            返回伏;
        }        @覆盖
        公共无效onMa pready(GoogleMap的地图){
            createMapIfNeeded();
        }私人无效createMapIfNeeded(){            如果(mLocManager == NULL){
                mLocManager =(的LocationManager)getActivity()getSystemService(Context.LOCATION_SERVICE)。
                mLocManager.requestLocationUpdates(
                           LocationManager.NETWORK_PROVIDER,
                           MIN_TIME_BW_UPDATES,
                           MIN_DISTANCE_CHANGE_FOR_UPDATES,
                           这个);
            }             // locmanager可以返回null如果没有最后已知locaiton可用。
            位置= mLocManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            //如果地图还没有被实例化,它会返回null
            如果(MMAP == NULL){
                //实例图
                MMAP = mMapFragment.getMap();
                //检查它已被实例化
                如果(MMAP!= NULL){
                    mMap.setOnMapLongClickListener(本);
                    mMap.setOnInfoWindowClickListener(本);
                    mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
                    mMap.setMyLocationEnabled(真);                    //此处操纵地图(添加坐标/从跳闸等等等等折线)
                    UiSettings设定值= mMap.getUiSettings();
                    setting.setTiltGesturesEnabled(真);
                    setting.setRotateGesturesEnabled(真);
                    setting.setZoomControlsEnabled(真);
                    setting.setMyLocationButtonEnabled(真);                    如果(位置!= NULL){
                    的CameraUpdate立方米= CameraUpdateFactory.newLatLngZoom(新经纬度(location.getLatitude(),location.getLongitude()),15);
                    mMap.animateCamera(CU);
                    }
                }
            }
        }

现在 MyMapFragment.java

 公共类MyMapFragment扩展MapFragment {      私人MapCallback回调;      公共静态界面MapCallback
      {
         公共无效onMa pready(GoogleMap的地图);
      }      公共无效setMapCallback(MapCallback回调)
      {
        this.callback =回调;
      }      @覆盖公共无效onActivityCreated(捆绑savedInstanceState)
      {
          super.onActivityCreated(savedInstanceState);
         如果(!=回调空)callback.onMa pready(的GetMap());
      }
}

CHEERS!

I've been experimenting with android.support.v4.widget.DrawerLayout and have 4 fragments to choose from the drawer. The map initially loads with no problems however when I open the drawer and change fragments I am unable to then go back to the map. I just get a black screen. Logcat is showing the fragment is re-created but yet I get nothing. Just a blank black screen. I can switch between the other fragments with no problem. What am I doing wrong? My project has a Min API of 14.

I load the ExploreMap (a fragment) from MainActivity.java here:

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

in ExploreMap.java I do the following

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's are as follows

 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>

and 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>

解决方案

After days of beating my head against the wall I figured out the problem, or should I say problemS. tsp suggested using libraries above which works too however I wanted to get this to work with the Google provided android.support.v4.widget.DrawerLayout.

The issue was 2 fold.

  1. I was using nested fragments and I wasn't removing the child (map) fragment when leaving the ExploreMap fragment. My hiearchy is: Activity(DrawerLayout)-->ExploreMap(A Fragment)-->MapFragment. When opening the drawer and changing fragments I was not removing the MapFragment from the ExploreMap(fragment). The original MapFragment instance remained in memory due to setRetainInstance(true). For reasons I still don't fully understand the original instance of the MapFragment would not re-appear once returning to the ExploreMap fragment. To solve this I assign the MapFragment a String tag I called "mapfrag" when it is initially created and set the variable to be public static. Next in the Activity, where the drawer code is to switch fragments, I do a findFragmentByTag() and test if its null, removing the MapFragment if it is not null.

However #1 only gets you half way as it will get the map to reappear when you go back to the ExploreMap however the underlying GoogleMap from the MapFragment kept returning null to me and I couldn't get the map configured at all.

2) I found this post MapFragment return null. Which recommended extending your own MapFragment and implementing an interface to notify when the MapFragment is done being created, pretty much guaranteeing a non-null GoogleMap.

and WHAMMY!! you have a working google map in googles drawer layout. Here is my complete working code.

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(); 
            }

in 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);
                    }
                }
            }  
        }

and now 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!!!

这篇关于Android的DrawerLayout与MapFragment黑屏返回到地图时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆