Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.

Commit 632d335

Browse files
committed
[android] - rework attribution to include small logo, add layout placement
1 parent 9804e90 commit 632d335

File tree

10 files changed

+255
-21
lines changed

10 files changed

+255
-21
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.mapbox.mapboxsdk.attribution;
2+
3+
import android.graphics.Bitmap;
4+
import android.graphics.PointF;
5+
import android.support.annotation.Nullable;
6+
7+
public class AttributionPlacement {
8+
9+
private Bitmap logo;
10+
private PointF anchorPoint;
11+
12+
public AttributionPlacement(@Nullable Bitmap logo, @Nullable PointF anchorPoint) {
13+
this.logo = logo;
14+
this.anchorPoint = anchorPoint;
15+
}
16+
17+
public Bitmap getLogo() {
18+
return logo;
19+
}
20+
21+
public PointF getAnchorPoint() {
22+
return anchorPoint;
23+
}
24+
25+
@Override
26+
public boolean equals(Object o) {
27+
if (this == o) {
28+
return true;
29+
}
30+
if (o == null || getClass() != o.getClass()) {
31+
return false;
32+
}
33+
34+
AttributionPlacement that = (AttributionPlacement) o;
35+
36+
if (logo != null ? !logo.equals(that.logo) : that.logo != null) {
37+
return false;
38+
}
39+
return anchorPoint != null ? anchorPoint.equals(that.anchorPoint) : that.anchorPoint == null;
40+
}
41+
42+
@Override
43+
public int hashCode() {
44+
int result = logo != null ? logo.hashCode() : 0;
45+
result = 31 * result + (anchorPoint != null ? anchorPoint.hashCode() : 0);
46+
return result;
47+
}
48+
49+
@Override
50+
public String toString() {
51+
return "AttributionPlacement{" +
52+
"logo=" + logo +
53+
", anchorPoint=" + anchorPoint +
54+
'}';
55+
}
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.mapbox.mapboxsdk.attribution;
2+
3+
import android.graphics.Bitmap;
4+
import android.graphics.PointF;
5+
import android.widget.TextView;
6+
7+
public class AttributionProvider {
8+
9+
private Bitmap logo;
10+
private Bitmap logoSmall;
11+
private Bitmap snapshot;
12+
private TextView textView;
13+
private float margin;
14+
15+
public AttributionProvider(Bitmap snapshot, Bitmap logo, Bitmap logoSmall, TextView textView, float marginPadding) {
16+
this.snapshot = snapshot;
17+
this.logo = logo;
18+
this.logoSmall = logoSmall;
19+
this.textView = textView;
20+
this.margin = marginPadding;
21+
}
22+
23+
public AttributionPlacement calculateAttributionPlacement() {
24+
float logoContainerWidth = logo.getWidth() + (2 * margin);
25+
26+
PointF anchor = new PointF(snapshot.getWidth() - textView.getMeasuredWidth() - margin, snapshot.getHeight() - margin - textView.getMeasuredHeight());
27+
float textViewContainerWidth = textView.getMeasuredWidth() + margin;
28+
if (logoContainerWidth + textViewContainerWidth <= snapshot.getWidth()) {
29+
// it fits! align to right
30+
return new AttributionPlacement(logo, anchor);
31+
} else {
32+
// it doesn't fit let's try again with a smaller logo
33+
float smallLogoContainerWidth = logoSmall.getWidth() + (2 * margin);
34+
if (smallLogoContainerWidth + textViewContainerWidth <= snapshot.getWidth()) {
35+
// it fits! align to right + use small logo
36+
return new AttributionPlacement(logoSmall, anchor);
37+
} else {
38+
// it doesn't fit let try without a logo
39+
if (textViewContainerWidth + margin <= snapshot.getWidth()) {
40+
// it fits
41+
return new AttributionPlacement(null, anchor);
42+
} else {
43+
// it doesn't fit
44+
return new AttributionPlacement(null, null);
45+
}
46+
}
47+
}
48+
}
49+
}

platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java

+35-17
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import android.graphics.BitmapFactory;
66
import android.graphics.Canvas;
77
import android.graphics.Matrix;
8-
import android.os.Build;
8+
import android.graphics.PointF;
99
import android.os.Handler;
1010
import android.support.annotation.NonNull;
1111
import android.support.annotation.Nullable;
@@ -17,6 +17,8 @@
1717
import android.widget.TextView;
1818
import com.mapbox.mapboxsdk.R;
1919
import com.mapbox.mapboxsdk.attribution.AttributionParser;
20+
import com.mapbox.mapboxsdk.attribution.AttributionPlacement;
21+
import com.mapbox.mapboxsdk.attribution.AttributionProvider;
2022
import com.mapbox.mapboxsdk.camera.CameraPosition;
2123
import com.mapbox.mapboxsdk.constants.Style;
2224
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
@@ -278,8 +280,8 @@ protected void addOverlay(MapSnapshot snapshot) {
278280
Bitmap original = snapshot.getBitmap();
279281
Canvas canvas = new Canvas(original);
280282
if (snapshot.isShowLogo()) {
281-
Logo logo = addLogo(canvas, original);
282-
addAttribution(canvas, logo, snapshot);
283+
// Logo logo = addLogo(canvas, original);
284+
addAttribution(canvas, snapshot);
283285
}
284286
}
285287

@@ -305,7 +307,9 @@ private Logo addLogo(Canvas canvas, Bitmap original) {
305307
* @param canvas the canvas to draw the attribution on
306308
* @param mapSnapshot the map snapshot
307309
*/
308-
private void addAttribution(Canvas canvas, Logo logo, MapSnapshot mapSnapshot) {
310+
private void addAttribution(Canvas canvas, MapSnapshot mapSnapshot) {
311+
312+
309313
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
310314
int margin = (int) displayMetrics.density * LOGO_MARGIN_DP;
311315
Bitmap original = mapSnapshot.getBitmap();
@@ -316,22 +320,35 @@ private void addAttribution(Canvas canvas, Logo logo, MapSnapshot mapSnapshot) {
316320
ViewGroup.LayoutParams.WRAP_CONTENT)
317321
);
318322
textView.setSingleLine(true);
319-
textView.setTextSize(10 * logo.scale);
323+
textView.setTextSize(8/** logo.scale*/);
320324
textView.setText(Html.fromHtml(createAttribution(mapSnapshot)));
321-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
322-
textView.setClipToOutline(true);
323-
}
324325
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(original.getWidth(), View.MeasureSpec.AT_MOST);
325326
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
326-
textView.setPadding(margin, 0, margin, margin);
327+
// textView.setPadding(margin, 0, margin, margin);
327328
textView.setBackgroundResource(R.drawable.mapbox_rounded_corner);
328329
textView.measure(widthMeasureSpec, heightMeasureSpec);
329-
330-
canvas.save();
331330
textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
332-
canvas.translate(logo.getWidth(), logo.getTop());
333-
textView.draw(canvas);
334-
canvas.restore();
331+
332+
333+
Bitmap snapshot = mapSnapshot.getBitmap();
334+
Bitmap logo = BitmapFactory.decodeResource(context.getResources(), R.drawable.mapbox_logo_icon, null);
335+
Bitmap logoSmall = BitmapFactory.decodeResource(context.getResources(), R.drawable.mapbox_logo_helmet, null);
336+
AttributionProvider attributionProvider = new AttributionProvider(snapshot, logo, logoSmall, textView, margin);
337+
AttributionPlacement placement = attributionProvider.calculateAttributionPlacement();
338+
339+
// draw logo
340+
Bitmap selectedLogo = placement.getLogo();
341+
if (selectedLogo != null) {
342+
canvas.drawBitmap(selectedLogo, margin, snapshot.getHeight() - logo.getHeight() - margin, null);
343+
}
344+
345+
PointF anchorPoint = placement.getAnchorPoint();
346+
if (anchorPoint != null) {
347+
canvas.save();
348+
canvas.translate(anchorPoint.x, anchorPoint.y);
349+
textView.draw(canvas);
350+
canvas.restore();
351+
}
335352
}
336353

337354
private String createAttribution(MapSnapshot mapSnapshot) {
@@ -352,7 +369,8 @@ private String createAttribution(MapSnapshot mapSnapshot) {
352369
*/
353370
private Logo createScaledLogo(Bitmap snapshot) {
354371
Bitmap logo = BitmapFactory.decodeResource(context.getResources(), R.drawable.mapbox_logo_icon, null);
355-
float scale = calculateLogoScale(snapshot, logo);
372+
// float scale = calculateLogoScale(snapshot, logo);
373+
float scale = 1.0f;
356374
Matrix matrix = new Matrix();
357375
matrix.postScale(scale, scale);
358376
return new Logo(Bitmap.createBitmap(logo, 0, 0, logo.getWidth(), logo.getHeight(), matrix, true), scale);
@@ -460,8 +478,8 @@ public void setTop(float top) {
460478
this.top = top;
461479
}
462480

463-
public int getWidth() {
464-
return (int) (left + bitmap.getWidth() + left + left + left);
481+
public int getWidthContainer() {
482+
return (int) (left + bitmap.getWidth() + left);
465483
}
466484
}
467485
}
Loading
Loading
Loading
Loading
Loading

platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_rounded_corner.xml

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
<shape xmlns:android="http://schemas.android.com/apk/res/android">
33
<solid android:color="#A6FFFFFF"/>
44
<padding
5-
android:left="4dp"
6-
android:right="4dp"
7-
android:top="0.5dp"
8-
android:bottom="1.5dp"/>
5+
android:left="7.5dp"
6+
android:right="7.5dp"
7+
android:top="2dp"
8+
android:bottom="3dp"/>
99
<corners android:radius="7.5dp"/>
1010
</shape>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package com.mapbox.mapboxsdk.maps.attribution;
2+
3+
import android.content.Context;
4+
import android.graphics.Bitmap;
5+
import android.graphics.PointF;
6+
import android.support.test.rule.ActivityTestRule;
7+
import android.view.View;
8+
import android.view.ViewGroup;
9+
import android.widget.TextView;
10+
import com.mapbox.mapboxsdk.attribution.AttributionParser;
11+
import com.mapbox.mapboxsdk.attribution.AttributionPlacement;
12+
import com.mapbox.mapboxsdk.attribution.AttributionProvider;
13+
import com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity;
14+
import org.junit.Before;
15+
import org.junit.Rule;
16+
import org.junit.Test;
17+
18+
import static junit.framework.Assert.assertEquals;
19+
20+
public class AttributionLayoutTest {
21+
22+
@Rule
23+
public ActivityTestRule<FeatureOverviewActivity> rule = new ActivityTestRule<>(FeatureOverviewActivity.class);
24+
25+
private static final String SATELLITE_ATTRIBUTION = "<a href=\"https://www.mapbox.com/about/maps/\" target=\"_blank\">&copy; Mapbox</a> <a href=\"http://www.openstreetmap.org/about/\" target=\"_blank\">&copy; 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\">&copy; DigitalGlobe</a>\n";
26+
private static final Bitmap LOGO = Bitmap.createBitmap(128, 56, Bitmap.Config.ARGB_8888);
27+
private static final Bitmap LOGO_SMALL = Bitmap.createBitmap(56, 56, Bitmap.Config.ARGB_8888);
28+
private static final String ATTRIBUTION = new AttributionParser.Options()
29+
.withAttributionData(SATELLITE_ATTRIBUTION)
30+
.withImproveMap(false)
31+
.withCopyrightSign(false)
32+
.build().getAttributionString();
33+
34+
private Context context;
35+
private TextView textView;
36+
private float margin;
37+
38+
@Before
39+
public void setUp() throws Exception {
40+
context = rule.getActivity();
41+
margin = context.getResources().getDisplayMetrics().density * 4;
42+
43+
textView = new TextView(context);
44+
textView.setLayoutParams(new ViewGroup.LayoutParams(
45+
ViewGroup.LayoutParams.WRAP_CONTENT,
46+
ViewGroup.LayoutParams.WRAP_CONTENT)
47+
);
48+
textView.setSingleLine(true);
49+
textView.setTextSize(8);
50+
textView.setText(ATTRIBUTION);
51+
}
52+
53+
@Test
54+
public void testLogoLayout() throws Exception {
55+
Bitmap snapshot = Bitmap.createBitmap(650, 600, Bitmap.Config.ARGB_8888);
56+
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(snapshot.getWidth(), View.MeasureSpec.AT_MOST);
57+
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
58+
textView.measure(widthMeasureSpec, heightMeasureSpec);
59+
60+
AttributionProvider attributionProvider = new AttributionProvider(snapshot, LOGO, LOGO_SMALL, textView, margin);
61+
62+
PointF expectedPoint = new PointF(snapshot.getWidth() - textView.getMeasuredWidth() - margin, snapshot.getHeight() - textView.getMeasuredHeight() - margin);
63+
AttributionPlacement expected = new AttributionPlacement(LOGO, expectedPoint);
64+
AttributionPlacement actual = attributionProvider.calculateAttributionPlacement();
65+
assertEquals("Calculated placement should match: ", expected, actual);
66+
}
67+
68+
@Test
69+
public void testSmallLogoLayout() {
70+
Bitmap snapshot = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888);
71+
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(snapshot.getWidth(), View.MeasureSpec.AT_MOST);
72+
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
73+
textView.measure(widthMeasureSpec, heightMeasureSpec);
74+
75+
AttributionProvider attributionProvider = new AttributionProvider(snapshot, LOGO, LOGO_SMALL, textView, margin);
76+
77+
PointF expectedPoint = new PointF(snapshot.getWidth() - textView.getMeasuredWidth() - margin, snapshot.getHeight() - textView.getMeasuredHeight() - margin);
78+
AttributionPlacement expected = new AttributionPlacement(LOGO_SMALL, expectedPoint);
79+
AttributionPlacement actual = attributionProvider.calculateAttributionPlacement();
80+
assertEquals("Calculated placement should match: ", expected, actual);
81+
}
82+
83+
@Test
84+
public void testNoLogoLayout() {
85+
Bitmap snapshot = Bitmap.createBitmap(415, 415, Bitmap.Config.ARGB_8888);
86+
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
87+
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
88+
textView.measure(widthMeasureSpec, heightMeasureSpec);
89+
90+
AttributionProvider attributionProvider = new AttributionProvider(snapshot, LOGO, LOGO_SMALL, textView, margin);
91+
92+
PointF expectedPoint = new PointF(snapshot.getWidth() - textView.getMeasuredWidth() - margin, snapshot.getHeight() - textView.getMeasuredHeight() - margin);
93+
AttributionPlacement expected = new AttributionPlacement(null, expectedPoint);
94+
AttributionPlacement actual = attributionProvider.calculateAttributionPlacement();
95+
assertEquals("Calculated placement should match: ", expected, actual);
96+
}
97+
98+
@Test
99+
public void testNoAttributionLayout() {
100+
Bitmap snapshot = Bitmap.createBitmap(25, 25, Bitmap.Config.ARGB_8888);
101+
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(snapshot.getWidth(), View.MeasureSpec.AT_MOST);
102+
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
103+
textView.measure(widthMeasureSpec, heightMeasureSpec);
104+
105+
AttributionProvider attributionProvider = new AttributionProvider(snapshot, LOGO, LOGO_SMALL, textView, margin);
106+
107+
AttributionPlacement expected = new AttributionPlacement(null, null);
108+
AttributionPlacement actual = attributionProvider.calculateAttributionPlacement();
109+
assertEquals("Calculated placement should match: ", expected, actual);
110+
}
111+
}

0 commit comments

Comments
 (0)