diff --git a/ApiDemos/app/src/main/java/com/example/mapdemo/LiteDemoActivity.java b/ApiDemos/app/src/main/java/com/example/mapdemo/LiteDemoActivity.java index 780a8a87..0bed5ba0 100755 --- a/ApiDemos/app/src/main/java/com/example/mapdemo/LiteDemoActivity.java +++ b/ApiDemos/app/src/main/java/com/example/mapdemo/LiteDemoActivity.java @@ -16,10 +16,8 @@ package com.example.mapdemo; - import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.LatLng; @@ -28,13 +26,10 @@ import com.google.android.gms.maps.model.MarkerOptions; import com.google.android.gms.maps.model.PolygonOptions; import com.google.android.gms.maps.model.PolylineOptions; -import android.annotation.SuppressLint; import android.graphics.Color; -import android.os.Build; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; -import android.view.ViewTreeObserver.OnGlobalLayoutListener; /** * This demo shows some features supported in lite mode. @@ -42,7 +37,8 @@ import android.view.ViewTreeObserver.OnGlobalLayoutListener; * launch the Google Maps Mobile application, {@link com.google.android.gms.maps.CameraUpdate}s * and {@link com.google.android.gms.maps.model.Polygon}s. */ -public class LiteDemoActivity extends AppCompatActivity implements OnMapReadyCallback { +public class LiteDemoActivity extends AppCompatActivity implements + OnMapAndViewReadyListener.OnGlobalLayoutAndMapReadyListener { private static final LatLng BRISBANE = new LatLng(-27.47093, 153.0235); @@ -76,7 +72,7 @@ public class LiteDemoActivity extends AppCompatActivity implements OnMapReadyCal // Get the map and register for the ready callback SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); - mapFragment.getMapAsync(this); + new OnMapAndViewReadyListener(mapFragment, this); } /** @@ -136,24 +132,8 @@ public class LiteDemoActivity extends AppCompatActivity implements OnMapReadyCal public void onMapReady(GoogleMap googleMap) { mMap = googleMap; addMarkers(); - addPolyobjects(); - - final View mapView = getSupportFragmentManager().findFragmentById(R.id.map).getView(); - if (mapView.getViewTreeObserver().isAlive()) { - mapView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { - @SuppressWarnings("deprecation") // We use the new method when supported - @SuppressLint("NewApi") // We check which build version we are using. - @Override - public void onGlobalLayout() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { - mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this); - } else { - mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this); - } - showAustralia(null); - } - }); - } + addPolyObjects(); + showAustralia(null); } /** @@ -161,7 +141,7 @@ public class LiteDemoActivity extends AppCompatActivity implements OnMapReadyCal * The Polyline connects Melbourne, Adelaide and Perth. The Polygon is located in the Northern * Territory (Australia). */ - private void addPolyobjects() { + private void addPolyObjects() { mMap.addPolyline((new PolylineOptions()) .add(MELBOURNE, ADELAIDE, PERTH) .color(Color.GREEN) diff --git a/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerCloseInfoWindowOnRetapDemoActivity.java b/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerCloseInfoWindowOnRetapDemoActivity.java index 7cae5605..c5526b5d 100644 --- a/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerCloseInfoWindowOnRetapDemoActivity.java +++ b/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerCloseInfoWindowOnRetapDemoActivity.java @@ -20,7 +20,6 @@ import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMap.OnMapClickListener; import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener; -import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; @@ -35,8 +34,8 @@ import android.support.v7.app.AppCompatActivity; */ public class MarkerCloseInfoWindowOnRetapDemoActivity extends AppCompatActivity implements OnMarkerClickListener, - OnMapReadyCallback, - OnMapClickListener { + OnMapClickListener, + OnMapAndViewReadyListener.OnGlobalLayoutAndMapReadyListener { private static final LatLng BRISBANE = new LatLng(-27.47093, 153.0235); private static final LatLng MELBOURNE = new LatLng(-37.81319, 144.96298); @@ -58,7 +57,7 @@ public class MarkerCloseInfoWindowOnRetapDemoActivity extends AppCompatActivity SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); - mapFragment.getMapAsync(this); + new OnMapAndViewReadyListener(mapFragment, this); } @Override diff --git a/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerDemoActivity.java b/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerDemoActivity.java index 63f55975..71f6bfb8 100644 --- a/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerDemoActivity.java +++ b/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerDemoActivity.java @@ -24,7 +24,6 @@ import com.google.android.gms.maps.GoogleMap.OnInfoWindowCloseListener; import com.google.android.gms.maps.GoogleMap.OnInfoWindowLongClickListener; import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener; import com.google.android.gms.maps.GoogleMap.OnMarkerDragListener; -import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.BitmapDescriptor; import com.google.android.gms.maps.model.BitmapDescriptorFactory; @@ -50,7 +49,6 @@ import android.support.v7.app.AppCompatActivity; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.view.View; -import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.animation.BounceInterpolator; import android.view.animation.Interpolator; import android.widget.CheckBox; @@ -74,9 +72,9 @@ public class MarkerDemoActivity extends AppCompatActivity implements OnInfoWindowClickListener, OnMarkerDragListener, OnSeekBarChangeListener, - OnMapReadyCallback, OnInfoWindowLongClickListener, - OnInfoWindowCloseListener { + OnInfoWindowCloseListener, + OnMapAndViewReadyListener.OnGlobalLayoutAndMapReadyListener { private static final LatLng BRISBANE = new LatLng(-27.47093, 153.0235); @@ -226,7 +224,7 @@ public class MarkerDemoActivity extends AppCompatActivity implements SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); - mapFragment.getMapAsync(this); + new OnMapAndViewReadyListener(mapFragment, this); } @Override @@ -252,33 +250,16 @@ public class MarkerDemoActivity extends AppCompatActivity implements // Override the default content description on the view, for accessibility mode. // Ideally this string would be localised. - map.setContentDescription("Map with lots of markers."); + mMap.setContentDescription("Map with lots of markers."); - // Pan to see all markers in view. - // Cannot zoom to bounds until the map has a size. - final View mapView = getSupportFragmentManager().findFragmentById(R.id.map).getView(); - if (mapView.getViewTreeObserver().isAlive()) { - mapView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { - @SuppressWarnings("deprecation") // We use the new method when supported - @SuppressLint("NewApi") // We check which build version we are using. - @Override - public void onGlobalLayout() { - LatLngBounds bounds = new LatLngBounds.Builder() - .include(PERTH) - .include(SYDNEY) - .include(ADELAIDE) - .include(BRISBANE) - .include(MELBOURNE) - .build(); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { - mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this); - } else { - mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this); - } - mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50)); - } - }); - } + LatLngBounds bounds = new LatLngBounds.Builder() + .include(PERTH) + .include(SYDNEY) + .include(ADELAIDE) + .include(BRISBANE) + .include(MELBOURNE) + .build(); + mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50)); } private void addMarkersToMap() { diff --git a/ApiDemos/app/src/main/java/com/example/mapdemo/OnMapAndViewReadyListener.java b/ApiDemos/app/src/main/java/com/example/mapdemo/OnMapAndViewReadyListener.java new file mode 100644 index 00000000..41f32861 --- /dev/null +++ b/ApiDemos/app/src/main/java/com/example/mapdemo/OnMapAndViewReadyListener.java @@ -0,0 +1,101 @@ +/** + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.mapdemo; + +import android.annotation.SuppressLint; +import android.os.Build; +import android.view.View; +import android.view.ViewTreeObserver.OnGlobalLayoutListener; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.OnMapReadyCallback; +import com.google.android.gms.maps.SupportMapFragment; + +/** + * Helper class that will delay triggering the OnMapReady callback until both the GoogleMap and the + * View having completed initialization. This is only necessary if a developer wishes to immediately + * invoke any method on the GoogleMap that also requires the View to have finished layout + * (ie. anything that needs to know the View's true size like snapshotting). + */ +public class OnMapAndViewReadyListener implements OnGlobalLayoutListener, OnMapReadyCallback { + + /** A listener that needs to wait for both the GoogleMap and the View to be initialized. */ + public interface OnGlobalLayoutAndMapReadyListener { + void onMapReady(GoogleMap googleMap); + } + + private final SupportMapFragment mapFragment; + private final View mapView; + private final OnGlobalLayoutAndMapReadyListener devCallback; + + private boolean isViewReady; + private boolean isMapReady; + private GoogleMap googleMap; + + public OnMapAndViewReadyListener( + SupportMapFragment mapFragment, OnGlobalLayoutAndMapReadyListener devCallback) { + this.mapFragment = mapFragment; + mapView = mapFragment.getView(); + this.devCallback = devCallback; + isViewReady = false; + isMapReady = false; + googleMap = null; + + registerListeners(); + } + + private void registerListeners() { + // View layout. + if ((mapView.getWidth() != 0) && (mapView.getHeight() != 0)) { + // View has already completed layout. + isViewReady = true; + } else { + // Map has not undergone layout, register a View observer. + mapView.getViewTreeObserver().addOnGlobalLayoutListener(this); + } + + // GoogleMap. Note if the GoogleMap is already ready it will still fire the callback later. + mapFragment.getMapAsync(this); + } + + @Override + public void onMapReady(GoogleMap googleMap) { + // NOTE: The GoogleMap API specifies the listener is removed just prior to invocation. + this.googleMap = googleMap; + isMapReady = true; + fireCallbackIfReady(); + } + + @SuppressWarnings("deprecation") // We use the new method when supported + @SuppressLint("NewApi") // We check which build version we are using. + @Override + public void onGlobalLayout() { + // Remove our listener. + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { + mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this); + } else { + mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this); + } + isViewReady = true; + fireCallbackIfReady(); + } + + private void fireCallbackIfReady() { + if (isViewReady && isMapReady) { + devCallback.onMapReady(googleMap); + } + } +} diff --git a/ApiDemos/app/src/main/java/com/example/mapdemo/VisibleRegionDemoActivity.java b/ApiDemos/app/src/main/java/com/example/mapdemo/VisibleRegionDemoActivity.java index e6b8a52f..e4952af1 100755 --- a/ApiDemos/app/src/main/java/com/example/mapdemo/VisibleRegionDemoActivity.java +++ b/ApiDemos/app/src/main/java/com/example/mapdemo/VisibleRegionDemoActivity.java @@ -19,7 +19,6 @@ package com.example.mapdemo; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMap.OnCameraIdleListener; -import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; @@ -39,7 +38,8 @@ import android.widget.Toast; * This shows how to use setPadding to allow overlays that obscure part of the map without * obscuring the map UI or copyright notices. */ -public class VisibleRegionDemoActivity extends AppCompatActivity implements OnMapReadyCallback { +public class VisibleRegionDemoActivity extends AppCompatActivity implements + OnMapAndViewReadyListener.OnGlobalLayoutAndMapReadyListener { /** * Note that this may be null if the Google Play services APK is not available. @@ -72,7 +72,7 @@ public class VisibleRegionDemoActivity extends AppCompatActivity implements OnMa SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); - mapFragment.getMapAsync(this); + new OnMapAndViewReadyListener(mapFragment, this); } @Override