summaryrefslogtreecommitdiff
path: root/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java
blob: 9e7877f313fff1a7f3812e101667691c42af26e2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
package com.mapbox.mapboxsdk.annotations;

import android.animation.AnimatorSet;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.support.annotation.FloatRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import android.view.animation.AnimationUtils;

import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.utils.AnimatorUtils;

/**
 * MarkerView is an annotation that shows an View at a geographical location.
 * <p>
 * This class uses {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter} to adapt a
 * MarkerView model to an Android SDK {@link android.view.View} object.
 * </p>
 * <p>
 * An {@link InfoWindow} can be shown when a MarkerView is pressed
 * </p>
 */
public class MarkerView extends Marker {

    private MarkerViewManager markerViewManager;

    private float anchorU;
    private float anchorV;

    private float offsetX = -1;
    private float offsetY = -1;

    private float infoWindowAnchorU;
    private float infoWindowAnchorV;

    private boolean flat;
    private boolean visible = true;

    private float tiltValue;
    private float rotation;
    private float alpha = 1;

    private Icon markerViewIcon;

    private boolean selected;

    /**
     * Publicly hidden default constructor
     */
    MarkerView() {
    }

    /**
     * Creates a instance of MarkerView using the builder of MarkerView
     *
     * @param baseMarkerViewOptions the builder used to construct the MarkerView
     */
    public MarkerView(BaseMarkerViewOptions baseMarkerViewOptions) {
        super(baseMarkerViewOptions);
        this.anchorU = baseMarkerViewOptions.getAnchorU();
        this.anchorV = baseMarkerViewOptions.getAnchorV();
        this.infoWindowAnchorU = baseMarkerViewOptions.getInfoWindowAnchorU();
        this.infoWindowAnchorV = baseMarkerViewOptions.getInfoWindowAnchorV();
        this.flat = baseMarkerViewOptions.isFlat();
        this.infoWindowAnchorU = baseMarkerViewOptions.infoWindowAnchorU;
        this.infoWindowAnchorV = baseMarkerViewOptions.infoWindowAnchorV;
        this.anchorU = baseMarkerViewOptions.anchorU;
        this.anchorV = baseMarkerViewOptions.anchorV;
        this.selected = baseMarkerViewOptions.selected;
    }

    /**
     * Specifies the anchor being set on a particular point point of the MarkerView.
     * <p>
     * The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0)
     * is the top-left corner of the image, and (1, 1) is the bottom-right corner.
     * </p>
     *
     * @param u u-coordinate of the anchor, as a ratio of the image width (in the range [0, 1])
     * @param v v-coordinate of the anchor, as a ratio of the image height (in the range [0, 1])
     */
    public void setAnchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) {
        this.anchorU = u;
        this.anchorV = v;
        setOffset(-1, -1);
    }

    /**
     * Get the horizontal distance, normalized to [0, 1], of the anchor from the left edge.
     *
     * @return the u-value of the anchor
     */
    public float getAnchorU() {
        return anchorU;
    }

    /**
     * Get the vertical distance, normalized to [0, 1], of the anchor from the top edge.
     *
     * @return the v-value of the anchor
     */
    public float getAnchorV() {
        return anchorV;
    }

    /**
     * Internal method to set the calculated offset.
     * <p>
     * These are calculated based on the View bounds and the provided anchor.
     * </p>
     *
     * @param x the x-value of the offset
     * @param y the y-value of the offset
     */
    void setOffset(float x, float y) {
        offsetX = x;
        offsetY = y;
    }

    /**
     * Internal method to get the horizontal calculated offset
     *
     * @return the calculated horizontal offset
     */
    float getOffsetX() {
        return offsetX;
    }

    /**
     * Internal method to get the vertical calculated offset
     *
     * @return the calculated vertical offset
     */
    float getOffsetY() {
        return offsetY;
    }

    /**
     * Specifies the anchor point of the info window on the View of the MarkerView.
     * <p>
     * This is specified in the same coordinate system as the anchor.
     * </p>
     * <p>
     * The default is the top middle of the View.
     * </p>
     *
     * @param u u-coordinate of the info window anchor, as a ratio of the image width (in the range [0, 1])
     * @param v v-coordinate of the info window anchor, as a ratio of the image height (in the range [0, 1])
     * @see #setAnchor(float, float) for more details.
     */
    public void setInfoWindowAnchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) {
        this.infoWindowAnchorU = u;
        this.infoWindowAnchorV = v;
    }

    /**
     * Get the horizontal distance, normalized to [0, 1], of the info window anchor from the left edge.
     *
     * @return the u value of the InfoWindow anchor.
     */
    public float getInfoWindowAnchorU() {
        return infoWindowAnchorU;
    }

    /**
     * Get the vertical distance, normalized to [0, 1], of the info window anchor from the top edge.
     *
     * @return the v value of the InfoWindow anchor.
     */
    public float getInfoWindowAnchorV() {
        return infoWindowAnchorV;
    }

    /**
     * Get the flat state of a MarkerView.
     *
     * @return true is the MarkerView is flat; false is the MarkerView is billboard
     */
    public boolean isFlat() {
        return flat;
    }

    /**
     * Sets whether this marker should be flat against the map true or a billboard facing the camera false.
     *
     * @param flat the flat state of the MarkerView
     */
    public void setFlat(boolean flat) {
        this.flat = flat;
    }

    /**
     * Internal method to get the current tilted value of a MarkerView.
     *
     * @return the tilted value
     */
    float getTilt() {
        return tiltValue;
    }

    /**
     * Internal method to set the current titled value of a MarkerView.
     *
     * @param tiltValue the tilted value to set
     */
    void setTilt(@FloatRange(from = 0.0, to = MapboxConstants.MAXIMUM_TILT) float tiltValue) {
        this.tiltValue = tiltValue;
    }

    /**
     * Set the visible state of a MarkerView.
     *
     * @param visible true will make the MarkerView visible, false will hide the MarkerViews
     */
    public void setVisible(boolean visible) {
        this.visible = visible;
        if (markerViewManager != null) {
            markerViewManager.animateVisible(this, visible);
        }
    }

    /**
     * Returns the visible state of the MarkerView.
     *
     * @return the visible state
     */
    public boolean isVisible() {
        return visible;
    }

    /**
     * Set the rotation value of the MarkerView.
     * <p>
     * This will result in animating the rotation of the MarkerView using an rotation animator
     * from current value to the provided parameter value.
     * </p>
     *
     * @param rotation the rotation value to animate to
     */
    public void setRotation(float rotation) {
        this.rotation = rotation;
        if (markerViewManager != null) {
            markerViewManager.animateRotation(this, rotation);
        }
    }

    /**
     * Get the rotation value of the MarkerView.
     *
     * @return the rotation value
     */
    public float getRotation() {
        return rotation;
    }

    /**
     * Get the alpha value of the MarkerView.
     *
     * @return the alpha value
     */
    public float getAlpha() {
        return alpha;
    }

    /**
     * Set the alpha value of the MarkerView.
     * <p>
     * This will result in animating the alpha of the MarkerView using an alpha animator
     * from current value to the provided parameter value.
     * </p>
     *
     * @param alpha the alpha value to animate to
     */
    public void setAlpha(@FloatRange(from = 0.0, to = 255.0) float alpha) {
        this.alpha = alpha;
        if (markerViewManager != null) {
            markerViewManager.animateAlpha(this, alpha);
        }
    }

    /**
     * Set the icon of the MarkerView.
     *
     * @param icon the icon to be used as Marker image
     */
    @Override
    public void setIcon(@Nullable Icon icon) {
        if (icon != null) {
            markerViewIcon = IconFactory.recreate("icon", icon.getBitmap());
        }
        Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
        Icon transparentIcon = IconFactory.recreate("markerViewSettings", bitmap);
        if (markerViewManager != null) {
            markerViewManager.updateIcon(this);
        }
        super.setIcon(transparentIcon);
    }

    public boolean isSelected() {
        return selected;
    }

    /**
     * For internal use only, use {@link MapboxMap#selectMarker(Marker)} instead.
     */
    void setSelected(boolean selected) {
        this.selected = selected;
    }

    /**
     * Get the icon of the MarkerView.
     *
     * @return the icon use as Marker image
     */
    @Override
    public Icon getIcon() {
        return markerViewIcon;
    }

    /**
     * Set the MapboxMap associated tot the MapView containing the MarkerView.
     * <p>
     * This method is used to instantiate the MarkerView and provide an instance of {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter}
     * </p>
     *
     * @param mapboxMap the MapboxMap instances
     */
    @Override
    public void setMapboxMap(MapboxMap mapboxMap) {
        super.setMapboxMap(mapboxMap);

        if(isFlat()) {
            // initial tilt value if MapboxMap is started with a tilt attribute
            tiltValue = (float) mapboxMap.getCameraPosition().tilt;
        }

        markerViewManager = mapboxMap.getMarkerViewManager();
    }

    /**
     * Get the String representation of a MarkerView.
     *
     * @return the String representation
     */
    @Override
    public String toString() {
        return "MarkerView [position[" + getPosition() + "]]";
    }
}