diff options
author | tobrun <tobrun.van.nuland@gmail.com> | 2017-11-09 19:23:38 +0100 |
---|---|---|
committer | Tobrun <tobrun.van.nuland@gmail.com> | 2017-11-13 18:57:56 +0100 |
commit | 632d33578b757a139d84cda1a0df08b1e2f7669f (patch) | |
tree | 8857c10ac85f5ac8c3f44f5f01ce7576089a5f70 | |
parent | 9804e901eea17ce1156f35713f88711b68affca5 (diff) | |
download | qtlocation-mapboxgl-632d33578b757a139d84cda1a0df08b1e2f7669f.tar.gz |
[android] - rework attribution to include small logo, add layout placement
10 files changed, 255 insertions, 21 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/attribution/AttributionPlacement.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/attribution/AttributionPlacement.java new file mode 100644 index 0000000000..1eedbb4f46 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/attribution/AttributionPlacement.java @@ -0,0 +1,56 @@ +package com.mapbox.mapboxsdk.attribution; + +import android.graphics.Bitmap; +import android.graphics.PointF; +import android.support.annotation.Nullable; + +public class AttributionPlacement { + + private Bitmap logo; + private PointF anchorPoint; + + public AttributionPlacement(@Nullable Bitmap logo, @Nullable PointF anchorPoint) { + this.logo = logo; + this.anchorPoint = anchorPoint; + } + + public Bitmap getLogo() { + return logo; + } + + public PointF getAnchorPoint() { + return anchorPoint; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + AttributionPlacement that = (AttributionPlacement) o; + + if (logo != null ? !logo.equals(that.logo) : that.logo != null) { + return false; + } + return anchorPoint != null ? anchorPoint.equals(that.anchorPoint) : that.anchorPoint == null; + } + + @Override + public int hashCode() { + int result = logo != null ? logo.hashCode() : 0; + result = 31 * result + (anchorPoint != null ? anchorPoint.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "AttributionPlacement{" + + "logo=" + logo + + ", anchorPoint=" + anchorPoint + + '}'; + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/attribution/AttributionProvider.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/attribution/AttributionProvider.java new file mode 100644 index 0000000000..762bbd37a9 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/attribution/AttributionProvider.java @@ -0,0 +1,49 @@ +package com.mapbox.mapboxsdk.attribution; + +import android.graphics.Bitmap; +import android.graphics.PointF; +import android.widget.TextView; + +public class AttributionProvider { + + private Bitmap logo; + private Bitmap logoSmall; + private Bitmap snapshot; + private TextView textView; + private float margin; + + public AttributionProvider(Bitmap snapshot, Bitmap logo, Bitmap logoSmall, TextView textView, float marginPadding) { + this.snapshot = snapshot; + this.logo = logo; + this.logoSmall = logoSmall; + this.textView = textView; + this.margin = marginPadding; + } + + public AttributionPlacement calculateAttributionPlacement() { + float logoContainerWidth = logo.getWidth() + (2 * margin); + + PointF anchor = new PointF(snapshot.getWidth() - textView.getMeasuredWidth() - margin, snapshot.getHeight() - margin - textView.getMeasuredHeight()); + float textViewContainerWidth = textView.getMeasuredWidth() + margin; + if (logoContainerWidth + textViewContainerWidth <= snapshot.getWidth()) { + // it fits! align to right + return new AttributionPlacement(logo, anchor); + } else { + // it doesn't fit let's try again with a smaller logo + float smallLogoContainerWidth = logoSmall.getWidth() + (2 * margin); + if (smallLogoContainerWidth + textViewContainerWidth <= snapshot.getWidth()) { + // it fits! align to right + use small logo + return new AttributionPlacement(logoSmall, anchor); + } else { + // it doesn't fit let try without a logo + if (textViewContainerWidth + margin <= snapshot.getWidth()) { + // it fits + return new AttributionPlacement(null, anchor); + } else { + // it doesn't fit + return new AttributionPlacement(null, null); + } + } + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java index 677bc33f14..4d85ea4f6a 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java @@ -5,7 +5,7 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; -import android.os.Build; +import android.graphics.PointF; import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -17,6 +17,8 @@ import android.view.ViewGroup; import android.widget.TextView; import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.attribution.AttributionParser; +import com.mapbox.mapboxsdk.attribution.AttributionPlacement; +import com.mapbox.mapboxsdk.attribution.AttributionProvider; import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.constants.Style; import com.mapbox.mapboxsdk.geometry.LatLngBounds; @@ -278,8 +280,8 @@ public class MapSnapshotter { Bitmap original = snapshot.getBitmap(); Canvas canvas = new Canvas(original); if (snapshot.isShowLogo()) { - Logo logo = addLogo(canvas, original); - addAttribution(canvas, logo, snapshot); +// Logo logo = addLogo(canvas, original); + addAttribution(canvas, snapshot); } } @@ -305,7 +307,9 @@ public class MapSnapshotter { * @param canvas the canvas to draw the attribution on * @param mapSnapshot the map snapshot */ - private void addAttribution(Canvas canvas, Logo logo, MapSnapshot mapSnapshot) { + private void addAttribution(Canvas canvas, MapSnapshot mapSnapshot) { + + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); int margin = (int) displayMetrics.density * LOGO_MARGIN_DP; Bitmap original = mapSnapshot.getBitmap(); @@ -316,22 +320,35 @@ public class MapSnapshotter { ViewGroup.LayoutParams.WRAP_CONTENT) ); textView.setSingleLine(true); - textView.setTextSize(10 * logo.scale); + textView.setTextSize(8/** logo.scale*/); textView.setText(Html.fromHtml(createAttribution(mapSnapshot))); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - textView.setClipToOutline(true); - } int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(original.getWidth(), View.MeasureSpec.AT_MOST); int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); - textView.setPadding(margin, 0, margin, margin); +// textView.setPadding(margin, 0, margin, margin); textView.setBackgroundResource(R.drawable.mapbox_rounded_corner); textView.measure(widthMeasureSpec, heightMeasureSpec); - - canvas.save(); textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight()); - canvas.translate(logo.getWidth(), logo.getTop()); - textView.draw(canvas); - canvas.restore(); + + + Bitmap snapshot = mapSnapshot.getBitmap(); + Bitmap logo = BitmapFactory.decodeResource(context.getResources(), R.drawable.mapbox_logo_icon, null); + Bitmap logoSmall = BitmapFactory.decodeResource(context.getResources(), R.drawable.mapbox_logo_helmet, null); + AttributionProvider attributionProvider = new AttributionProvider(snapshot, logo, logoSmall, textView, margin); + AttributionPlacement placement = attributionProvider.calculateAttributionPlacement(); + + // draw logo + Bitmap selectedLogo = placement.getLogo(); + if (selectedLogo != null) { + canvas.drawBitmap(selectedLogo, margin, snapshot.getHeight() - logo.getHeight() - margin, null); + } + + PointF anchorPoint = placement.getAnchorPoint(); + if (anchorPoint != null) { + canvas.save(); + canvas.translate(anchorPoint.x, anchorPoint.y); + textView.draw(canvas); + canvas.restore(); + } } private String createAttribution(MapSnapshot mapSnapshot) { @@ -352,7 +369,8 @@ public class MapSnapshotter { */ private Logo createScaledLogo(Bitmap snapshot) { Bitmap logo = BitmapFactory.decodeResource(context.getResources(), R.drawable.mapbox_logo_icon, null); - float scale = calculateLogoScale(snapshot, logo); +// float scale = calculateLogoScale(snapshot, logo); + float scale = 1.0f; Matrix matrix = new Matrix(); matrix.postScale(scale, scale); return new Logo(Bitmap.createBitmap(logo, 0, 0, logo.getWidth(), logo.getHeight(), matrix, true), scale); @@ -460,8 +478,8 @@ public class MapSnapshotter { this.top = top; } - public int getWidth() { - return (int) (left + bitmap.getWidth() + left + left + left); + public int getWidthContainer() { + return (int) (left + bitmap.getWidth() + left); } } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_logo_helmet.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_logo_helmet.png Binary files differnew file mode 100644 index 0000000000..2629afe6a3 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_logo_helmet.png diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_logo_helmet.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_logo_helmet.png Binary files differnew file mode 100644 index 0000000000..34bab3bf6d --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/mapbox_logo_helmet.png diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_logo_helmet.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_logo_helmet.png Binary files differnew file mode 100644 index 0000000000..942d78ec58 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_logo_helmet.png diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_logo_helmet.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_logo_helmet.png Binary files differnew file mode 100644 index 0000000000..947d5a2a30 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/mapbox_logo_helmet.png diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_logo_helmet.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_logo_helmet.png Binary files differnew file mode 100644 index 0000000000..bec38cedc7 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_logo_helmet.png diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_rounded_corner.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_rounded_corner.xml index 11d4fa445d..c4dbfb3d80 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_rounded_corner.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_rounded_corner.xml @@ -2,9 +2,9 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#A6FFFFFF"/> <padding - android:left="4dp" - android:right="4dp" - android:top="0.5dp" - android:bottom="1.5dp"/> + android:left="7.5dp" + android:right="7.5dp" + android:top="2dp" + android:bottom="3dp"/> <corners android:radius="7.5dp"/> </shape>
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/attribution/AttributionLayoutTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/attribution/AttributionLayoutTest.java new file mode 100644 index 0000000000..0e45951c24 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/attribution/AttributionLayoutTest.java @@ -0,0 +1,111 @@ +package com.mapbox.mapboxsdk.maps.attribution; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.PointF; +import android.support.test.rule.ActivityTestRule; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import com.mapbox.mapboxsdk.attribution.AttributionParser; +import com.mapbox.mapboxsdk.attribution.AttributionPlacement; +import com.mapbox.mapboxsdk.attribution.AttributionProvider; +import com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; + +public class AttributionLayoutTest { + + @Rule + public ActivityTestRule<FeatureOverviewActivity> rule = new ActivityTestRule<>(FeatureOverviewActivity.class); + + private static final String SATELLITE_ATTRIBUTION = "<a href=\"https://www.mapbox.com/about/maps/\" target=\"_blank\">© Mapbox</a> <a href=\"http://www.openstreetmap.org/about/\" target=\"_blank\">© OpenStreetMap</a> <a class=\"mapbox-improve-map\" href=\"https://www.mapbox.com/map-feedback/\" target=\"_blank\">Improve this map</a> <a href=\"https://www.digitalglobe.com/\" target=\"_blank\">© DigitalGlobe</a>\n"; + private static final Bitmap LOGO = Bitmap.createBitmap(128, 56, Bitmap.Config.ARGB_8888); + private static final Bitmap LOGO_SMALL = Bitmap.createBitmap(56, 56, Bitmap.Config.ARGB_8888); + private static final String ATTRIBUTION = new AttributionParser.Options() + .withAttributionData(SATELLITE_ATTRIBUTION) + .withImproveMap(false) + .withCopyrightSign(false) + .build().getAttributionString(); + + private Context context; + private TextView textView; + private float margin; + + @Before + public void setUp() throws Exception { + context = rule.getActivity(); + margin = context.getResources().getDisplayMetrics().density * 4; + + textView = new TextView(context); + textView.setLayoutParams(new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT) + ); + textView.setSingleLine(true); + textView.setTextSize(8); + textView.setText(ATTRIBUTION); + } + + @Test + public void testLogoLayout() throws Exception { + Bitmap snapshot = Bitmap.createBitmap(650, 600, Bitmap.Config.ARGB_8888); + int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(snapshot.getWidth(), View.MeasureSpec.AT_MOST); + int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + textView.measure(widthMeasureSpec, heightMeasureSpec); + + AttributionProvider attributionProvider = new AttributionProvider(snapshot, LOGO, LOGO_SMALL, textView, margin); + + PointF expectedPoint = new PointF(snapshot.getWidth() - textView.getMeasuredWidth() - margin, snapshot.getHeight() - textView.getMeasuredHeight() - margin); + AttributionPlacement expected = new AttributionPlacement(LOGO, expectedPoint); + AttributionPlacement actual = attributionProvider.calculateAttributionPlacement(); + assertEquals("Calculated placement should match: ", expected, actual); + } + + @Test + public void testSmallLogoLayout() { + Bitmap snapshot = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888); + int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(snapshot.getWidth(), View.MeasureSpec.AT_MOST); + int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + textView.measure(widthMeasureSpec, heightMeasureSpec); + + AttributionProvider attributionProvider = new AttributionProvider(snapshot, LOGO, LOGO_SMALL, textView, margin); + + PointF expectedPoint = new PointF(snapshot.getWidth() - textView.getMeasuredWidth() - margin, snapshot.getHeight() - textView.getMeasuredHeight() - margin); + AttributionPlacement expected = new AttributionPlacement(LOGO_SMALL, expectedPoint); + AttributionPlacement actual = attributionProvider.calculateAttributionPlacement(); + assertEquals("Calculated placement should match: ", expected, actual); + } + + @Test + public void testNoLogoLayout() { + Bitmap snapshot = Bitmap.createBitmap(415, 415, Bitmap.Config.ARGB_8888); + int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + textView.measure(widthMeasureSpec, heightMeasureSpec); + + AttributionProvider attributionProvider = new AttributionProvider(snapshot, LOGO, LOGO_SMALL, textView, margin); + + PointF expectedPoint = new PointF(snapshot.getWidth() - textView.getMeasuredWidth() - margin, snapshot.getHeight() - textView.getMeasuredHeight() - margin); + AttributionPlacement expected = new AttributionPlacement(null, expectedPoint); + AttributionPlacement actual = attributionProvider.calculateAttributionPlacement(); + assertEquals("Calculated placement should match: ", expected, actual); + } + + @Test + public void testNoAttributionLayout() { + Bitmap snapshot = Bitmap.createBitmap(25, 25, Bitmap.Config.ARGB_8888); + int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(snapshot.getWidth(), View.MeasureSpec.AT_MOST); + int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + textView.measure(widthMeasureSpec, heightMeasureSpec); + + AttributionProvider attributionProvider = new AttributionProvider(snapshot, LOGO, LOGO_SMALL, textView, margin); + + AttributionPlacement expected = new AttributionPlacement(null, null); + AttributionPlacement actual = attributionProvider.calculateAttributionPlacement(); + assertEquals("Calculated placement should match: ", expected, actual); + } +}
\ No newline at end of file |