Add combined map/layout ready listener.

Change-Id: I56011849e39f1b473aa71cbe1ac5e894cf319fb8
This commit is contained in:
Stephen McDonald 2017-01-18 15:55:20 +11:00
parent d0ec782e7e
commit 8605faa807
5 changed files with 125 additions and 64 deletions

View File

@ -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)

View File

@ -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

View File

@ -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() {

View File

@ -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);
}
}
}

View File

@ -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