Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
736ef94
Change default color for lines in maps
seadowg Jan 8, 2026
36fad66
Simplify MapIconCreator interface
seadowg Jan 9, 2026
ecd7772
Add convenience extension for create marker icon bitmaps
seadowg Jan 9, 2026
c825cc2
Add new specific icon for line points
seadowg Jan 9, 2026
12b6cd8
Fill center of shapes
seadowg Jan 9, 2026
b05cc7a
Make first point in polygon bigger
seadowg Jan 9, 2026
98c9d9b
Fix constructor use in tests
seadowg Jan 9, 2026
71dc983
Update default color tests
seadowg Jan 9, 2026
cdc6503
Fix assertions on MarkerIconDescription
seadowg Jan 9, 2026
6a76557
Correct method name
seadowg Jan 13, 2026
dff3c30
Update implementations
seadowg Jan 13, 2026
2b6491d
Store line points in GeoPolyFragment instead of in MapFragment
seadowg Jan 13, 2026
be829c4
Fix clear behaviour
seadowg Jan 14, 2026
b6c1276
Remove unneeded formatting for shape
seadowg Jan 14, 2026
29b7bb3
Switch to using polygons with map for shapes
seadowg Jan 14, 2026
8415fc2
Don't use new API for Google and Mapbox
seadowg Jan 14, 2026
7e585a2
Highlight last point rather than first
seadowg Jan 14, 2026
d5f30e7
Remove add/remove methods for poly points
seadowg Jan 15, 2026
3d90579
Store LocationTracker location in Flow
seadowg Jan 15, 2026
b45e310
Expose location as StateFlow
seadowg Jan 15, 2026
7d09ee0
Remove unused field
seadowg Jan 15, 2026
0f8d2f2
Use ViewModel for points state
seadowg Jan 15, 2026
e576fa6
Use LocationTracker to schedule location recording
seadowg Jan 15, 2026
91b0bea
Fix whitespace issue
seadowg Jan 15, 2026
6ae1adb
Add updatePolyLine method
seadowg Jan 15, 2026
d0281d4
Add updatePolygon method
seadowg Jan 15, 2026
2774e36
Simplify feature description constructor calls
seadowg Jan 15, 2026
055f227
Highlight last point with different color
seadowg Jan 15, 2026
f3147e3
Update fake
seadowg Jan 15, 2026
3e07038
Clean up unneeded code
seadowg Jan 15, 2026
d508feb
Break up single line
seadowg Jan 19, 2026
974898f
Rename method
seadowg Jan 19, 2026
a63222a
Rename class
seadowg Jan 19, 2026
f3c1845
Remove double save to cache
seadowg Jan 19, 2026
46f0155
Correct whitespace
seadowg Jan 19, 2026
16eabc9
Fix formatting
seadowg Jan 19, 2026
2164907
Correct typo
seadowg Jan 19, 2026
72a978f
Use isNotEmpty
seadowg Jan 19, 2026
f6ded2d
Use last()
seadowg Jan 19, 2026
35ae10e
Remove redundant let
seadowg Jan 19, 2026
e6d579d
Remove redundant alpha setting
seadowg Jan 19, 2026
0b63d63
Only update map when points updated
seadowg Jan 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add new specific icon for line points
  • Loading branch information
seadowg committed Jan 19, 2026
commit c825cc27222eb733841318463a31bbdcefdfbb05
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ private void clear() {
/** Places the marker and enables the button to remove it. */
private void placeMarker(@NonNull MapPoint point) {
map.clearFeatures();
featureId = map.addMarker(new MarkerDescription(point, intentDraggable && !intentReadOnly && !isPointLocked, MapFragment.CENTER, new MarkerIconDescription(org.odk.collect.icons.R.drawable.ic_map_point)));
featureId = map.addMarker(new MarkerDescription(point, intentDraggable && !intentReadOnly && !isPointLocked, MapFragment.CENTER, new MarkerIconDescription.Resource(org.odk.collect.icons.R.drawable.ic_map_point)));
if (!intentReadOnly) {
clearButton.setEnabled(true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ class SelectionMapFragment(

map.setMarkerIcon(
featureId,
MarkerIconDescription(item.largeIcon, item.color, item.symbol)
MarkerIconDescription.Resource(item.largeIcon, item.color, item.symbol)
)
}
}
Expand Down Expand Up @@ -380,7 +380,7 @@ class SelectionMapFragment(
if (featureId != null) {
map.setMarkerIcon(
featureId,
MarkerIconDescription(selectedItem.smallIcon, selectedItem.color, selectedItem.symbol)
MarkerIconDescription.Resource(selectedItem.smallIcon, selectedItem.color, selectedItem.symbol)
)
}
}
Expand All @@ -402,7 +402,7 @@ class SelectionMapFragment(
MapPoint(it.point.latitude, it.point.longitude),
false,
MapFragment.BOTTOM,
MarkerIconDescription(it.smallIcon, it.color, it.symbol)
MarkerIconDescription.Resource(it.smallIcon, it.color, it.symbol)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ private void updateLocationIndicator(LatLng loc, double radius) {
if (locationCrosshairs == null) {
locationCrosshairs = map.addMarker(new MarkerOptions()
.position(loc)
.icon(getBitmapDescriptor(getContext(), new MarkerIconDescription(org.odk.collect.maps.R.drawable.ic_crosshairs)))
.icon(getBitmapDescriptor(getContext(), new MarkerIconDescription.Resource(org.odk.collect.maps.R.drawable.ic_crosshairs)))
.anchor(0.5f, 0.5f) // center the crosshairs on the position
);
}
Expand Down Expand Up @@ -871,7 +871,7 @@ private static class DynamicPolyLineFeature implements LineFeature {
}

for (MapPoint point : lineDescription.getPoints()) {
markers.add(createMarker(context, new MarkerDescription(point, true, CENTER, new MarkerIconDescription(org.odk.collect.icons.R.drawable.ic_map_point)), map));
markers.add(createMarker(context, new MarkerDescription(point, true, CENTER, new MarkerIconDescription.Resource(org.odk.collect.icons.R.drawable.ic_map_point)), map));
}

update();
Expand Down Expand Up @@ -937,7 +937,7 @@ public void addPoint(MapPoint point) {
if (map == null) { // during Robolectric tests, map will be null
return;
}
markers.add(createMarker(context, new MarkerDescription(point, true, CENTER, new MarkerIconDescription(org.odk.collect.icons.R.drawable.ic_map_point)), map));
markers.add(createMarker(context, new MarkerDescription(point, true, CENTER, new MarkerIconDescription.Resource(org.odk.collect.icons.R.drawable.ic_map_point)), map));
update();
}

Expand Down
2 changes: 1 addition & 1 deletion mapbox/src/main/java/org/odk/collect/mapbox/MapUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ object MapUtils {
return pointAnnotationManager.create(
PointAnnotationOptions()
.withPoint(Point.fromLngLat(point.longitude, point.latitude, point.altitude))
.withIconImage(MarkerIconDescription(iconDrawableId).getBitmap(context))
.withIconImage(MarkerIconDescription.Resource(iconDrawableId).getBitmap(context))
.withIconSize(1.0)
.withSymbolSortKey(10.0)
.withDraggable(draggable)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.odk.collect.maps.markers

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Bitmap.Config
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
Expand All @@ -10,6 +11,7 @@ import android.util.LruCache
import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils
import androidx.core.graphics.drawable.toBitmap
import org.odk.collect.maps.MapConsts

object MarkerIconCreator {
/**
Expand All @@ -22,14 +24,53 @@ object MarkerIconCreator {

@JvmStatic
fun getMarkerIcon(context: Context, markerIconDescription: MarkerIconDescription): Bitmap {
val drawableId = markerIconDescription.icon
val color = markerIconDescription.getColor()
val symbol = markerIconDescription.getSymbol()
return when (markerIconDescription) {
is MarkerIconDescription.LinePoint -> {
fromCache("LinePoint") {
val size = markerIconDescription.lineSize * 6
val bitmap =
Bitmap.createBitmap(size.toInt(), size.toInt(), Config.ARGB_8888)

val bitmapId = drawableId.toString() + color + symbol
Canvas(bitmap).also { canvas ->
val radius = size / 2

val fill = Paint().also {
it.style = Paint.Style.FILL
it.color = MapConsts.DEFAULT_STROKE_COLOR
}
canvas.drawCircle(radius, radius, radius, fill)

val strokeWidth = markerIconDescription.lineSize
val stroke = Paint().also {
it.style = Paint.Style.STROKE
it.color = Color.parseColor("#ffffff")
it.strokeWidth = strokeWidth
}
canvas.drawCircle(radius, radius, radius - (strokeWidth / 2), stroke)
}

bitmap
}
}

is MarkerIconDescription.Resource -> {
val drawableId = markerIconDescription.icon
val color = markerIconDescription.getColor()
val symbol = markerIconDescription.getSymbol()

val bitmapId = drawableId.toString() + color + symbol
fromCache(bitmapId) {
createBitmap(context, drawableId, color, symbol).also {
cache.put(bitmapId, it)
}
}
}
}
}

private fun fromCache(bitmapId: String, factory: () -> Bitmap): Bitmap {
return if (cache[bitmapId] == null) {
createBitmap(context, drawableId, color, symbol).also {
factory().also {
cache.put(bitmapId, it)
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,22 @@ import org.odk.collect.androidshared.utils.toColorInt
import org.odk.collect.shared.strings.StringUtils
import java.util.Locale

class MarkerIconDescription @JvmOverloads constructor(
val icon: Int,
private val color: String? = null,
private val symbol: String? = null
) {
fun getColor(): Int? = color?.toColorInt()
sealed interface MarkerIconDescription {
class Resource @JvmOverloads constructor(
val icon: Int,
private val color: String? = null,
private val symbol: String? = null
) : MarkerIconDescription {
fun getColor(): Int? = color?.toColorInt()

fun getSymbol(): String? = symbol?.let {
if (it.isBlank()) {
null
} else {
StringUtils.firstCharacterOrEmoji(it).uppercase(Locale.US)
fun getSymbol(): String? = symbol?.let {
if (it.isBlank()) {
null
} else {
StringUtils.firstCharacterOrEmoji(it).uppercase(Locale.US)
}
}
}

class LinePoint(val lineSize: Float) : MarkerIconDescription
}
Original file line number Diff line number Diff line change
Expand Up @@ -874,8 +874,10 @@ private class DynamicPolyLineFeature implements LineFeature {
final List<Marker> markers = new ArrayList<>();
final Polyline polyline;
final boolean closedPolygon;
private final LineDescription lineDescription;

DynamicPolyLineFeature(MapView map, LineDescription lineDescription) {
this.lineDescription = lineDescription;
this.map = map;
this.closedPolygon = lineDescription.getClosed();
polyline = new Polyline();
Expand All @@ -892,7 +894,7 @@ private class DynamicPolyLineFeature implements LineFeature {
paint.setStrokeWidth(lineDescription.getStrokeWidth());
map.getOverlays().add(polyline);
for (MapPoint point : lineDescription.getPoints()) {
markers.add(createMarker(map, new MarkerDescription(point, true, CENTER, new MarkerIconDescription(org.odk.collect.icons.R.drawable.ic_map_point))));
markers.add(getPointMarker(point));
}
update();
}
Expand Down Expand Up @@ -944,10 +946,15 @@ public List<MapPoint> getPoints() {
}

public void addPoint(MapPoint point) {
markers.add(createMarker(map, new MarkerDescription(point, true, CENTER, new MarkerIconDescription(org.odk.collect.icons.R.drawable.ic_map_point))));
markers.add(getPointMarker(point));
update();
}

@NonNull
private Marker getPointMarker(MapPoint point) {
return createMarker(map, new MarkerDescription(point, true, CENTER, new MarkerIconDescription.LinePoint(lineDescription.getStrokeWidth())));
}

public void removeLastPoint() {
if (!markers.isEmpty()) {
int last = markers.size() - 1;
Expand Down