2017-04-03 40 views
10

我正在用Xamarin(版本7.1)開發一個Android應用程序。它顯示爲地圖並繪製PolyLines,在OnCameraIdle()中這樣做。如何在旋轉設備(縱向/橫向)後在MapFragment上保留/重新綁定事件監聽器?

MapFragment以編程方式在OnCreate中生成。我通過GetMapAsync獲取GoogleMapOnResume並綁定了聽衆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),但這也沒有改變任何東西。

你有什麼想法我可能做錯了什麼?

+1

我一分錢:在設備輪換時,活動和碎片都被銷燬,然後新創建。 https://developer.android.com/guide/components/fragments.html#Lifecycle – user1506104

+1

謝謝。我有沒有實實在在的印象,片段不會被重新創建,可能是因爲視口被保留了,但這當然可以通過。 – Pharaoh

+0

嘗試檢查'savedInstanceState'來查看您的Activity是第一次構建還是隻是返回它。您似乎在每次通話時都會疊加片段。 – gustavogbc

回答

2

嘗試檢查savedInstanceState以查看您的活動是第一次構建還是隻是返回它。您似乎在每次通話時都會疊加片段。

+0

謝謝 - 雖然不是100%的答案,這指出我在正確的方向。檢查'savedInstanceState'並且只創建'MapFragment'如果它是'null'沒有幫助,但爲了避免重疊片段,我添加了'ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize'到我的活動。現在它可以工作。 – Pharaoh

5

嘗試把InitializeMap()調用到OnCreateView()方法,而不是在OnCreate的倍率()

+1

在我看來,'OnCreateView'是類'Fragment'的一部分。你是說我應該擴展'MapFragment'? – Pharaoh

+0

不,在MapActivity上爲OnCreateView創建一個覆蓋(應該可用)。並且將調用放在初始化映射中,而不是OnCreate中的當前調用 –

+0

好吧,'OnCreateView'是'Activity'的一部分,我沒有看到。但它沒有幫助 - 相機位置和縮放被保留(像以前一樣,使用'OnCreate'),但是在旋轉設備後沒有監聽器被觸發。 – Pharaoh

5

默認情況下,當屏幕旋轉時的活動將被終止並重新啓動。爲了確保沒有數據丟失,您需要使用生命週期方法正確保存和恢復您的數據。見SavingPersistentStatesavedInstanceState並按照此Android Developer Documentation希望今年五月可以幫助。

+0

沒有數據丟失 - 唯一需要保留的就是相機的位置,但它會自動保存。這只是聽衆的重新安排,並不適用於上面的代碼。 – Pharaoh

4

我有類似的問題,因爲我們有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 
} 

並請: 功能應該開始小寫!

+1

在C#/ Xamarin中,函數以大寫字母開頭。你的代碼基本上在'OnAttachedToWindow'中調用'InitializeMap()' - 我現在試過,但行爲是一樣的。最後,您的評論讓我感到驚訝,因爲當我旋轉設備時,地圖位置被保留。我認爲'MapFragment'會自動完成。 – Pharaoh

+0

對不起,沒有看到Xamarin標籤。請忽略我的評論。 – longilong

相關問題