Android DrawerLayout с черным экраном MapFragment при возвращении на карту
Я экспериментировал с android.support.v4.widget.DrawerLayout
и иметь 4 фрагмента на выбор из ящика. Карта изначально загружается без проблем, однако, когда я открываю ящик и изменяю фрагменты, я не могу затем вернуться к карте. У меня просто черный экран. Logcat показывает, что фрагмент воссоздан, но я ничего не получаю. Просто пустой черный экран. Я могу переключаться между другими фрагментами без проблем. Что я делаю неправильно? Мой проект имеет минимальное 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 ответа
После нескольких дней, когда я бился головой о стену, я понял проблему, или я должен сказать, проблема. TSP предложил использовать библиотеки выше, что тоже работает, однако я хотел, чтобы это работало с Google при условии android.support.v4.widget.DrawerLayout
,
Вопрос был в 2 раза.
- Я использовал вложенные фрагменты и не удалял дочерний фрагмент (карту) при выходе из фрагмента ExploreMap. Моя подсказка: Activity(DrawerLayout)->ExploreMap(Фрагмент)->MapFragment. При открытии ящика и изменении фрагментов я не удалял MapFragment из ExploreMap (фрагмент). Исходный экземпляр MapFragment остался в памяти из-за
setRetainInstance(true)
, По причинам, которые я до сих пор не до конца понимаю, исходный экземпляр MapFragment не будет появляться снова после возврата к фрагменту ExploreMap. Чтобы решить эту проблему, я назначаю MapFragment тег String, который я назвал "mapfrag", когда он изначально создается, и устанавливаю переменную равнойpublic static
, Затем в Деятельности, где код ящика должен переключать фрагменты, я делаюfindFragmentByTag()
и проверить, если егоnull
, удаляя MapFragment, если он не нулевой.
Однако #1 дает вам только половину пути, так как карта снова появится, когда вы вернетесь к ExploreMap, однако основной GoogleMap
из MapFragment возвращал мне нулевое значение, и я вообще не мог настроить карту.
2) Я нашел этот пост MapFragment вернуть ноль. Который рекомендовал расширить свой собственный MapFragment и реализовать интерфейс для уведомления о завершении создания MapFragment, что в значительной степени гарантирует ненулевой GoogleMap.
и дикий!! у вас есть рабочая карта Google в макете ящика Google. Вот мой полный рабочий код.
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!!!
Я надеюсь, что это будет работать для вас: https://github.com/jfeinstein10/SlidingMenu https://play.google.com/store/apps/details?id=com.slidingmenu.example&hl=en
Простой способ решения этой проблемы найден в почтовой ветке. Это решило мою проблему. Используйте относительное расположение и поместите этот прозрачный вид прямо на фрагмент вашей карты. Пример:
<?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>