Reputation: 2346
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>
Upvotes: 2
Views: 2047
Reputation: 2254
Easy workaround for this issue found on a mail thread. This solved my issue. Use relative layout and place this transparent view directly over your map fragment. Example :
<?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>
Upvotes: -1
Reputation: 2346
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.
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!!!
Upvotes: 2
Reputation: 2182
I hope this will work for you: https://github.com/jfeinstein10/SlidingMenu https://play.google.com/store/apps/details?id=com.slidingmenu.example&hl=en
Upvotes: 0