From 1be63108bb66f235bec3704a0df8b8145f3c49a1 Mon Sep 17 00:00:00 2001 From: Tobrun Date: Thu, 12 Jul 2018 20:05:40 +0200 Subject: [android] - wait for the initial render to occur before showing the map to the end-user --- .../java/com/mapbox/mapboxsdk/maps/MapView.java | 44 ++++++++++++++++-- .../mapbox/mapboxsdk/maps/MapboxMapOptions.java | 31 ++++++++++++- .../mapboxsdk/maps/renderer/MapRenderer.java | 21 +-------- .../glsurfaceview/GLSurfaceViewMapRenderer.java | 4 +- .../mapboxsdk/style/layers/PropertyFactory.java | 14 +++--- .../style/layers/property_factory.java.ejs | 14 +++--- .../com/mapbox/mapboxsdk/utils/ColorUtils.java | 54 ++++++++++++++++++++++ 7 files changed, 143 insertions(+), 39 deletions(-) (limited to 'platform/android/MapboxGLAndroidSDK/src/main/java') diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java index 0fa1072cd2..aaed71ddec 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java @@ -3,6 +3,7 @@ package com.mapbox.mapboxsdk.maps; import android.content.Context; import android.graphics.Bitmap; import android.graphics.PointF; +import android.graphics.drawable.ColorDrawable; import android.opengl.GLSurfaceView; import android.os.Build; import android.os.Bundle; @@ -126,6 +127,11 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback { // in IDE layout editor, just return return; } + + // hide surface until map is fully loaded #10990 + setForeground(new ColorDrawable(options.getForegroundLoadColor())); + addOnMapChangedListener(new InitialRenderCallback(this)); + mapboxMapOptions = options; // inflate view @@ -283,11 +289,12 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback { } private void initialiseDrawingSurface(MapboxMapOptions options) { + String localFontFamily = options.getLocalIdeographFontFamily(); if (options.getTextureMode()) { TextureView textureView = new TextureView(getContext()); - String localFontFamily = options.getLocalIdeographFontFamily(); boolean translucentSurface = options.getTranslucentTextureSurface(); - mapRenderer = new TextureViewMapRenderer(getContext(), textureView, localFontFamily, translucentSurface) { + mapRenderer = new TextureViewMapRenderer(getContext(), + textureView, localFontFamily, translucentSurface) { @Override protected void onSurfaceCreated(GL10 gl, EGLConfig config) { MapView.this.onSurfaceCreated(); @@ -299,7 +306,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback { } else { GLSurfaceView glSurfaceView = new GLSurfaceView(getContext()); glSurfaceView.setZOrderMediaOverlay(mapboxMapOptions.getRenderSurfaceOnTop()); - mapRenderer = new GLSurfaceViewMapRenderer(getContext(), glSurfaceView, options.getLocalIdeographFontFamily()) { + mapRenderer = new GLSurfaceViewMapRenderer(getContext(), glSurfaceView, localFontFamily) { @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { MapView.this.onSurfaceCreated(); @@ -981,6 +988,37 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback { } } + /** + * The initial render callback waits for rendering to happen before making the map visible for end-users. + * We wait for the second DID_FINISH_RENDERING_FRAME map change event as the first will still show a black surface. + */ + private static class InitialRenderCallback implements OnMapChangedListener { + + private WeakReference weakReference; + private int renderCount; + private boolean styleLoaded; + + InitialRenderCallback(MapView mapView) { + this.weakReference = new WeakReference<>(mapView); + } + + @Override + public void onMapChanged(int change) { + if (change == MapView.DID_FINISH_LOADING_STYLE) { + styleLoaded = true; + } else if (styleLoaded && change == MapView.DID_FINISH_RENDERING_FRAME) { + renderCount++; + if (renderCount == 2) { + MapView mapView = weakReference.get(); + if (mapView != null && !mapView.isDestroyed()) { + mapView.setForeground(null); + mapView.removeOnMapChangedListener(this); + } + } + } + } + } + private class GesturesManagerInteractionListener implements MapboxMap.OnGesturesManagerInteractionListener { @Override diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java index 02c50c9f18..0075199b1e 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java @@ -30,6 +30,7 @@ import java.util.Arrays; */ public class MapboxMapOptions implements Parcelable { + private static final int LIGHT_GRAY = 0xFFF0E9E1; // RGB(240, 233, 225)) private static final float FOUR_DP = 4f; private static final float NINETY_TWO_DP = 92f; private static final int UNDEFINED_COLOR = -1; @@ -73,6 +74,9 @@ public class MapboxMapOptions implements Parcelable { private boolean textureMode; private boolean translucentTextureSurface; + @ColorInt + private int foregroundLoadColor; + private String style; private float pixelRatio; @@ -124,6 +128,7 @@ public class MapboxMapOptions implements Parcelable { zMediaOverlay = in.readByte() != 0; localIdeographFontFamily = in.readString(); pixelRatio = in.readFloat(); + foregroundLoadColor = in.readInt(); } /** @@ -209,7 +214,6 @@ public class MapboxMapOptions implements Parcelable { FOUR_DP * pxlRatio)), (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginBottom, FOUR_DP * pxlRatio))}); - mapboxMapOptions.textureMode( typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_renderTextureMode, false)); mapboxMapOptions.translucentTextureSurface( @@ -222,6 +226,9 @@ public class MapboxMapOptions implements Parcelable { typedArray.getString(R.styleable.mapbox_MapView_mapbox_localIdeographFontFamily)); mapboxMapOptions.pixelRatio( typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_pixelRatio, 0)); + mapboxMapOptions.foregroundLoadColor( + typedArray.getInt(R.styleable.mapbox_MapView_mapbox_foregroundLoadColor, LIGHT_GRAY) + ); } finally { typedArray.recycle(); } @@ -521,6 +528,17 @@ public class MapboxMapOptions implements Parcelable { return this; } + /** + * Set the MapView foreground color that is used when the map surface is being created. + * + * @param loadColor the color to show during map creation + * @return This + */ + public MapboxMapOptions foregroundLoadColor(@ColorInt int loadColor) { + this.foregroundLoadColor = loadColor; + return this; + } + /** * Enable tile pre-fetching. Loads tiles at a lower zoom-level to pre-render * a low resolution preview while more detailed tiles are loaded. @@ -819,6 +837,16 @@ public class MapboxMapOptions implements Parcelable { return translucentTextureSurface; } + /** + * Returns the current configured foreground color that is used during map creation. + * + * @return the load color + */ + @ColorInt + public int getForegroundLoadColor() { + return foregroundLoadColor; + } + /** * Returns the font-family for locally overriding generation of glyphs in the * 'CJK Unified Ideographs' and 'Hangul Syllables' ranges. @@ -892,6 +920,7 @@ public class MapboxMapOptions implements Parcelable { dest.writeByte((byte) (zMediaOverlay ? 1 : 0)); dest.writeString(localIdeographFontFamily); dest.writeFloat(pixelRatio); + dest.writeInt(foregroundLoadColor); } @Override diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/MapRenderer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/MapRenderer.java index b05a8a407f..1129b8000e 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/MapRenderer.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/MapRenderer.java @@ -26,10 +26,10 @@ public abstract class MapRenderer implements MapRendererScheduler { private MapboxMap.OnFpsChangedListener onFpsChangedListener; public MapRenderer(Context context, String localIdeographFontFamily) { - FileSource fileSource = FileSource.getInstance(context); float pixelRatio = context.getResources().getDisplayMetrics().density; String programCacheDir = context.getCacheDir().getAbsolutePath(); + // Initialise native peer nativeInitialize(this, fileSource, pixelRatio, programCacheDir, localIdeographFontFamily); } @@ -65,24 +65,6 @@ public abstract class MapRenderer implements MapRendererScheduler { @CallSuper protected void onSurfaceChanged(GL10 gl, int width, int height) { - if (width < 0) { - throw new IllegalArgumentException("fbWidth cannot be negative."); - } - - if (height < 0) { - throw new IllegalArgumentException("fbHeight cannot be negative."); - } - - if (width > 65535) { - throw new IllegalArgumentException( - "fbWidth cannot be greater than 65535."); - } - - if (height > 65535) { - throw new IllegalArgumentException( - "fbHeight cannot be greater than 65535."); - } - gl.glViewport(0, 0, width, height); nativeOnSurfaceChanged(width, height); } @@ -140,5 +122,4 @@ public abstract class MapRenderer implements MapRendererScheduler { frames = 0; } } - } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/GLSurfaceViewMapRenderer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/GLSurfaceViewMapRenderer.java index b0667751bb..d27fadf5ca 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/GLSurfaceViewMapRenderer.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/GLSurfaceViewMapRenderer.java @@ -21,7 +21,9 @@ public class GLSurfaceViewMapRenderer extends MapRenderer implements GLSurfaceVi private final GLSurfaceView glSurfaceView; - public GLSurfaceViewMapRenderer(Context context, GLSurfaceView glSurfaceView, String localIdeographFontFamily) { + public GLSurfaceViewMapRenderer(Context context, + GLSurfaceView glSurfaceView, + String localIdeographFontFamily) { super(context, localIdeographFontFamily); this.glSurfaceView = glSurfaceView; glSurfaceView.setEGLContextClientVersion(2); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java index ad603d356e..1cedf8c9ca 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java @@ -5,9 +5,7 @@ package com.mapbox.mapboxsdk.style.layers; import android.support.annotation.ColorInt; import com.mapbox.mapboxsdk.style.expressions.Expression; - -import java.text.DecimalFormat; -import java.util.Locale; +import com.mapbox.mapboxsdk.utils.ColorUtils; /** * Constructs paint/layout properties for Layers @@ -2404,11 +2402,11 @@ public class PropertyFactory { * * @param color Android color int * @return String rgba color + * @deprecated use {@link com.mapbox.mapboxsdk.utils.ColorUtils#colorToRgbaString(int)} instead */ + @Deprecated public static String colorToRgbaString(@ColorInt int color) { - String alpha = new DecimalFormat("#.###").format(((float)((color >> 24) & 0xFF)) / 255.0f); - return String.format(Locale.US, "rgba(%d, %d, %d, %s)", - (color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF, alpha); + return ColorUtils.colorToRgbaString(color); } /** @@ -2419,8 +2417,10 @@ public class PropertyFactory { * * @param color Android color int * @return int rgba array + * @deprecated use {@link com.mapbox.mapboxsdk.utils.ColorUtils#colorToRgbaArray(int)} instead */ + @Deprecated public static float[] colorToRgbaArray(@ColorInt int color) { - return new float[] {(color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF, ((color >> 24) & 0xFF) / 255.0f}; + return ColorUtils.colorToRgbaArray(color); } } \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs index 2fb51f4a47..27bb66aa08 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs @@ -9,9 +9,7 @@ package com.mapbox.mapboxsdk.style.layers; import android.support.annotation.ColorInt; import com.mapbox.mapboxsdk.style.expressions.Expression; - -import java.text.DecimalFormat; -import java.util.Locale; +import com.mapbox.mapboxsdk.utils.ColorUtils; /** * Constructs paint/layout properties for Layers @@ -94,11 +92,11 @@ public class PropertyFactory { * * @param color Android color int * @return String rgba color + * @deprecated use {@link com.mapbox.mapboxsdk.utils.ColorUtils#colorToRgbaString(int)} instead */ + @Deprecated public static String colorToRgbaString(@ColorInt int color) { - String alpha = new DecimalFormat("#.###").format(((float)((color >> 24) & 0xFF)) / 255.0f); - return String.format(Locale.US, "rgba(%d, %d, %d, %s)", - (color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF, alpha); + return ColorUtils.colorToRgbaString(color); } /** @@ -109,8 +107,10 @@ public class PropertyFactory { * * @param color Android color int * @return int rgba array + * @deprecated use {@link com.mapbox.mapboxsdk.utils.ColorUtils#colorToRgbaArray(int)} instead */ + @Deprecated public static float[] colorToRgbaArray(@ColorInt int color) { - return new float[] {(color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF, ((color >> 24) & 0xFF) / 255.0f}; + return ColorUtils.colorToRgbaArray(color); } } \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java index 1c0e439afc..3a53794e50 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java @@ -15,6 +15,8 @@ import android.widget.ImageView; import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.exceptions.ConversionException; +import java.text.DecimalFormat; +import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -139,6 +141,58 @@ public class ColorUtils { } } + /** + * Converts Android color int to "rbga(r, g, b, a)" String equivalent. + *

+ * Alpha value will be converted from 0-255 range to 0-1. + *

+ * + * @param color Android color int + * @return String rgba color + */ + public static String colorToRgbaString(@ColorInt int color) { + String alpha = new DecimalFormat("#.###").format(((float)((color >> 24) & 0xFF)) / 255.0f); + return String.format(Locale.US, "rgba(%d, %d, %d, %s)", + (color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF, alpha); + } + + /** + * Converts Android color int to rgba float array. + *

+ * Returned RGB values range from 0 to 255. + * Alpha value ranges from 0-1. + *

+ * + * @param color Android color int + * @return float rgba array, rgb values range from 0-255, alpha from 0-1 + */ + public static float[] colorToRgbaArray(@ColorInt int color) { + return new float[] { + (color >> 16) & 0xFF, // r (0-255) + (color >> 8) & 0xFF, // g (0-255) + color & 0xFF, // b (0-255) + ((color >> 24) & 0xFF) / 255.0f // a (0-1) + }; + } + + /** + * Converts Android color int to GL rgba float array. + *

+ * Returned values range from 0-1. + *

+ * + * @param color Android color int + * @return float rgba array, values range from 0 to 1 + */ + public static float[] colorToGlRgbaArray(@ColorInt int color) { + return new float[] { + ((color >> 16) & 0xFF) / 255.0f, // r (0-1) + ((color >> 8) & 0xFF) / 255.0f, // g (0-1) + (color & 0xFF) / 255.0f, // b (0-1) + ((color >> 24) & 0xFF) / 255.0f // a (0-1) + }; + } + private static int getColorCompat(Context context, int id) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return context.getResources().getColor(id, context.getTheme()); -- cgit v1.2.1