如何在旋转设备(纵向/横向)后在MapFragment上保留/重新绑定事件监听器?
我正在用Xamarin(版本7.1)开发一个Android应用程序。它显示为地图并绘制PolyLines,在OnCameraIdle()
中这样做。如何在旋转设备(纵向/横向)后在MapFragment上保留/重新绑定事件监听器?
MapFragment
以编程方式在OnCreate
中生成。我通过GetMapAsync
获取GoogleMap
的OnResume
并绑定了听众OnMapReady
。
他们工作正常,但只在一开始。一旦设备旋转(纵向 - >横向或反之亦然),摄像机的移动不会再触发听众。
但是地图起作用 - 我(用户)仍然可以移动相机。我(应用程序)无法使用它了。
这是裸码,只有地图的创建和处理。其他一切(实际绘图)被删除:
public class MapActivity : Activity, IOnMapReadyCallback,
GoogleMap.IOnCameraIdleListener, GoogleMap.IOnCameraMoveStartedListener
{
private GoogleMap _map;
private MapFragment _mapFragment;
private void InitializeMap()
{
_mapFragment = MapFragment.NewInstance();
var tx = FragmentManager.BeginTransaction();
tx.Add(Resource.Id.map_placeholder, _mapFragment);
tx.Commit();
}
private void SetMapListeners()
{
Log.Debug("MyApp/ Map", "SetMapListeners");
_map.SetOnCameraIdleListener(this);
_map.SetOnCameraMoveStartedListener(this);
}
/* Activity */
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Log.Debug("MyApp/Map", "OnCreate");
SetContentView(Resource.Layout.Map);
InitializeMap();
}
protected override void OnStart()
{
base.OnStart();
Log.Debug("MyApp/Map", "OnStart");
}
protected override void OnResume()
{
base.OnResume();
if (_map == null)
_mapFragment.GetMapAsync(this);
Log.Debug("MyApp/Map", "OnResume");
}
protected override void OnPause()
{
base.OnPause();
Log.Debug("MyApp/Map", "OnPause");
}
protected override void OnStop()
{
base.OnStop();
Log.Debug("MyApp/Map", "OnStop");
}
protected override void OnDestroy()
{
base.OnStop();
Log.Debug("MyApp/ Map", "OnDestroy");
}
/* IOnMapReadyCallback */
public void OnMapReady(GoogleMap googleMap)
{
Log.Debug("MyApp/Map", "Map is ready!");
_map = googleMap;
SetMapListeners();
}
/* IOnCameraIdleListener */
public void OnCameraIdle()
{
Log.Debug("MyApp/Map", "Camera is idle.");
// Drawing routine is called here
}
/* IOnCameraMoveStartedListener */
public void OnCameraMoveStarted(int reason)
{
Log.Debug("MyApp/Map", "Camera move started.");
}
}
正如你可以在下面的日志摘录看到,听众都在开始工作,但一旦设备被旋转(至少)一次,他们都不见了。
我也尝试在生命周期中只呼叫SetMapListeners
一次,第一次调用OnMapReady
,但这并没有改变任何东西。
04-03 20:29:06.486 D/MyApp/Map(7446): OnCreate
04-03 20:29:06.688 I/Google Maps Android API(7446): Google Play services client version: 10084000
04-03 20:29:06.695 I/Google Maps Android API(7446): Google Play services package version: 10298438
04-03 20:29:07.394 D/MyApp/Map(7446): OnStart
04-03 20:29:07.399 D/MyApp/Map(7446): OnResume
04-03 20:29:07.432 D/MyApp/Map(7446): Map is ready!
04-03 20:29:07.438 D/MyApp/Map(7446): SetMapListeners
04-03 20:29:07.568 D/MyApp/Map(7446): Camera is idle.
04-03 20:29:09.231 D/MyApp/Map(7446): Camera move started.
04-03 20:29:09.590 D/MyApp/Map(7446): Camera is idle.
04-03 20:29:12.350 D/MyApp/Map(7446): Camera move started.
04-03 20:29:12.751 D/MyApp/Map(7446): Camera is idle.
## Listeners are responding, now rotating the device.
04-03 20:29:15.503 D/MyApp/Map(7446): OnPause
04-03 20:29:15.508 D/MyApp/Map(7446): OnStop
04-03 20:29:15.572 D/MyApp/Map(7446): OnDestroy
04-03 20:29:15.595 I/Google Maps Android API(7446): Google Play services package version: 10298438
04-03 20:29:15.596 D/MyApp/Map(7446): OnCreate
04-03 20:29:15.628 I/Google Maps Android API(7446): Google Play services package version: 10298438
04-03 20:29:15.655 D/MyApp/Map(7446): OnStart
04-03 20:29:15.655 D/MyApp/Map(7446): OnResume
04-03 20:29:15.690 D/MyApp/Map(7446): Map is ready!
04-03 20:29:15.691 D/MyApp/Map(7446): SetMapListeners
## Map is rotated, camera position was preserved.
## Now moving the camera, but no listeners are responding.
04-03 20:29:24.436 D/MyApp/Map(7446): OnPause
04-03 20:29:31.288 D/MyApp/Map(7446): OnStop
04-03 20:29:31.359 D/MyApp/Map(7446): OnDestroy
这里对我有意思的是,当我切换回上一个活动并再次打开地图时,它会重新开始并重新运行。但是,正如您在日志中看到的那样,在旋转设备时,活动也会被破坏并新创建。据我所知,片段不是,所以也许这就是暗示。我不知道。
我也尝试删除OnDestroy
中的听众(通过设置null
),但这也没有改变任何东西。
你有什么想法我可能做错了什么?
尝试检查savedInstanceState
以查看您的活动是第一次构建还是只是返回它。您似乎在每次通话时都会叠加片段。
谢谢 - 虽然不是100%的答案,这指出我在正确的方向。检查'savedInstanceState'并且只创建'MapFragment'如果它是'null'没有帮助,但为了避免重叠片段,我添加了'ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize'到我的活动。现在它可以工作。 – Pharaoh
尝试把InitializeMap()调用到OnCreateView()方法,而不是在OnCreate的倍率()
默认情况下,当屏幕旋转时的活动将被终止并重新启动。为了确保没有数据丢失,您需要使用生命周期方法正确保存和恢复您的数据。见SavingPersistentState或savedInstanceState
并按照此Android Developer Documentation希望今年五月可以帮助。
没有数据丢失 - 唯一需要保留的就是相机的位置,但它会自动保存。这只是听众的重新安排,并不适用于上面的代码。 – Pharaoh
我有类似的问题,因为我们有MapFragment嵌套在另一个Fragment中,所以我们必须每次重新添加MapFragment。既然你已经将它直接嵌入到Activity中,@App Pack也应该可以工作,但我仍然会粘贴代码。
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow(); //onCreateView() or onResume() should work too
FragmentManager fragmentManager = ((AppCompatActivity) getContext()).getSupportFragmentManager();
SupportMapFragment mapFragment = SupportMapFragment.newInstance();
fragmentManager.beginTransaction()
.replace(R.id.mapContainer, mapFragment)
.commit();
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
this.googleMap = googleMap;
UiSettings uiSettings = googleMap.getUiSettings();
uiSettings.setZoomControlsEnabled(false);
//do your initialization + recreate your last map position from BundleSavedIntance: check this answer: http://stackoverflow.com/questions/16697891/google-maps-android-api-v2-restoring-map-state/16698624#16698624
}
并请:
功能应该开始小写!
我一分钱:在设备轮换时,活动和碎片都被销毁,然后新创建。 https://developer.android.com/guide/components/fragments.html#Lifecycle – user1506104
谢谢。我有没有实实在在的印象,片段不会被重新创建,可能是因为视口被保留了,但这当然可以通过。 – Pharaoh
尝试检查'savedInstanceState'来查看您的Activity是第一次构建还是只是返回它。您似乎在每次通话时都会叠加片段。 – gustavogbc