mark start and end of a track with a pin icon (see #95)

This commit is contained in:
y20k 2021-03-09 22:27:42 +01:00
parent dd25da53ce
commit fa43dde017
No known key found for this signature in database
GPG key ID: 824D4259F41FAFF6
13 changed files with 160 additions and 102 deletions

View file

@ -181,11 +181,11 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener, MapOverlayHelpe
/* Overrides onMarkerTapped from MarkerListener */ /* Overrides onMarkerTapped from MarkerListener */
override fun onMarkerTapped(latitude: Double, longitude: Double) { override fun onMarkerTapped(latitude: Double, longitude: Double, displayStartEndMarker: Boolean) {
super.onMarkerTapped(latitude, longitude) super.onMarkerTapped(latitude, longitude, displayStartEndMarker)
if (bound) { if (bound) {
track = TrackHelper.toggleStarred(activity as Context, track, latitude, longitude) track = TrackHelper.toggleStarred(activity as Context, track, latitude, longitude)
layout.overlayCurrentTrack(track, trackingState) layout.overlayCurrentTrack(track, trackingState, displayStartEndMarker)
trackerService.track = track trackerService.track = track
} }
} }
@ -320,7 +320,7 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener, MapOverlayHelpe
trackingState = trackerService.trackingState trackingState = trackerService.trackingState
// update location and track // update location and track
layout.markCurrentPosition(currentBestLocation, trackingState) layout.markCurrentPosition(currentBestLocation, trackingState)
layout.overlayCurrentTrack(track, trackingState) layout.overlayCurrentTrack(track, trackingState, displayStartEndMarker = false)
// center map, if it had not been dragged/zoomed before // center map, if it had not been dragged/zoomed before
if (!layout.userInteraction) { layout.centerMap(currentBestLocation, true)} if (!layout.userInteraction) { layout.centerMap(currentBestLocation, true)}
// show error snackbar if necessary // show error snackbar if necessary

View file

@ -162,11 +162,11 @@ class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDi
/* Overrides onMarkerTapped from MarkerListener */ /* Overrides onMarkerTapped from MarkerListener */
override fun onMarkerTapped(latitude: Double, longitude: Double) { override fun onMarkerTapped(latitude: Double, longitude: Double, displayStartEndMarker: Boolean) {
super.onMarkerTapped(latitude, longitude) super.onMarkerTapped(latitude, longitude, displayStartEndMarker)
// update track display // update track display
track = TrackHelper.toggleStarred(activity as Context, track, latitude, longitude) track = TrackHelper.toggleStarred(activity as Context, track, latitude, longitude)
layout.updateTrackOverlay(track) layout.updateTrackOverlay(track, displayStartEndMarker)
// save track // save track
GlobalScope.launch { GlobalScope.launch {
FileHelper.saveTrackSuspended(track, true) FileHelper.saveTrackSuspended(track, true)

View file

@ -44,7 +44,7 @@ class MapOverlayHelper (private var markerListener: MarkerListener) {
/* Interface used to communicate back to activity/fragment */ /* Interface used to communicate back to activity/fragment */
interface MarkerListener { interface MarkerListener {
fun onMarkerTapped(latitude: Double, longitude: Double) { fun onMarkerTapped(latitude: Double, longitude: Double, displayStartEndMarker: Boolean) {
} }
} }
@ -83,12 +83,12 @@ class MapOverlayHelper (private var markerListener: MarkerListener) {
overlayItems.add(overlayItem) overlayItems.add(overlayItem)
// create and return overlay for current position // create and return overlay for current position
return createOverlay(context, overlayItems) return createOverlay(context, overlayItems, enableStarring = false, displayStartEndMarker = false)
} }
/* Creates icon overlay for track */ /* Creates icon overlay for track */
fun createTrackOverlay(context: Context, track: Track, trackingState: Int, displayEndMarker: Boolean = false): ItemizedIconOverlay<OverlayItem> { fun createTrackOverlay(context: Context, track: Track, trackingState: Int, displayStartEndMarker: Boolean = false): ItemizedIconOverlay<OverlayItem> {
val overlayItems: ArrayList<OverlayItem> = ArrayList<OverlayItem>() val overlayItems: ArrayList<OverlayItem> = ArrayList<OverlayItem>()
val wayPoints: MutableList<WayPoint> = track.wayPoints val wayPoints: MutableList<WayPoint> = track.wayPoints
@ -118,11 +118,17 @@ class MapOverlayHelper (private var markerListener: MarkerListener) {
wayPoints.forEachIndexed { index: Int, wayPoint: WayPoint -> wayPoints.forEachIndexed { index: Int, wayPoint: WayPoint ->
// get drawable // get drawable
val newMarker: Drawable val newMarker: Drawable
if (displayEndMarker && index == maxIndex) { if (displayStartEndMarker && index == 0) {
if (wayPoint.starred) { if (wayPoint.starred) {
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_starred_blue_36dp)!! newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_start_starred_blue_48dp)!!
} else { } else {
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_blue_36dp)!! newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_start_blue_48dp)!!
}
} else if (displayStartEndMarker && index == maxIndex) {
if (wayPoint.starred) {
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_starred_blue_48dp)!!
} else {
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_blue_48dp)!!
} }
} }
else if (wayPoint.starred) { else if (wayPoint.starred) {
@ -140,7 +146,7 @@ class MapOverlayHelper (private var markerListener: MarkerListener) {
} }
} }
// create and return overlay for current position // create and return overlay for current position
return createOverlay(context, overlayItems) return createOverlay(context, overlayItems, enableStarring = true, displayStartEndMarker = displayStartEndMarker)
} }
@ -150,17 +156,23 @@ class MapOverlayHelper (private var markerListener: MarkerListener) {
//val description: String = "${context.getString(R.string.marker_description_accuracy)}: ${DecimalFormat("#0.00").format(accuracy)} (${provider})" //val description: String = "${context.getString(R.string.marker_description_accuracy)}: ${DecimalFormat("#0.00").format(accuracy)} (${provider})"
val description: String = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(time)} | ${context.getString(R.string.marker_description_accuracy)}: ${DecimalFormat("#0.00").format(accuracy)} (${provider})" val description: String = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(time)} | ${context.getString(R.string.marker_description_accuracy)}: ${DecimalFormat("#0.00").format(accuracy)} (${provider})"
val position: GeoPoint = GeoPoint(latitude, longitude) val position: GeoPoint = GeoPoint(latitude, longitude)
return OverlayItem(title, description, position) val item: OverlayItem = OverlayItem(title, description, position)
item.markerHotspot = OverlayItem.HotspotPlace.CENTER
return item
} }
/* Creates an overlay */ /* Creates an overlay */
private fun createOverlay(context: Context, overlayItems: ArrayList<OverlayItem>): ItemizedIconOverlay<OverlayItem> { private fun createOverlay(context: Context, overlayItems: ArrayList<OverlayItem>, enableStarring: Boolean, displayStartEndMarker: Boolean): ItemizedIconOverlay<OverlayItem> {
return ItemizedIconOverlay<OverlayItem>(context, overlayItems, return ItemizedIconOverlay<OverlayItem>(context, overlayItems,
object : ItemizedIconOverlay.OnItemGestureListener<OverlayItem> { object : ItemizedIconOverlay.OnItemGestureListener<OverlayItem> {
override fun onItemSingleTapUp(index: Int, item: OverlayItem): Boolean { override fun onItemSingleTapUp(index: Int, item: OverlayItem): Boolean {
markerListener.onMarkerTapped(item.point.latitude, item.point.longitude) if (enableStarring) {
markerListener.onMarkerTapped(item.point.latitude, item.point.longitude, displayStartEndMarker)
return true return true
} else {
return false
}
} }
override fun onItemLongPress(index: Int, item: OverlayItem): Boolean { override fun onItemLongPress(index: Int, item: OverlayItem): Boolean {
val v = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator val v = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator

View file

@ -162,12 +162,12 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar
/* Overlay current track on map */ /* Overlay current track on map */
fun overlayCurrentTrack(track: Track, trackingState: Int) { fun overlayCurrentTrack(track: Track, trackingState: Int, displayStartEndMarker: Boolean) {
if (currentTrackOverlay != null) { if (currentTrackOverlay != null) {
mapView.overlays.remove(currentTrackOverlay) mapView.overlays.remove(currentTrackOverlay)
} }
if (track.wayPoints.isNotEmpty()) { if (track.wayPoints.isNotEmpty()) {
currentTrackOverlay = MapOverlayHelper(markerListener).createTrackOverlay(context, track, trackingState) currentTrackOverlay = MapOverlayHelper(markerListener).createTrackOverlay(context, track, trackingState, displayStartEndMarker)
mapView.overlays.add(currentTrackOverlay) mapView.overlays.add(currentTrackOverlay)
} }
} }

View file

@ -146,7 +146,7 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m
mapView.overlays.add(compassOverlay) mapView.overlays.add(compassOverlay)
// create map overlay // create map overlay
trackOverlay = MapOverlayHelper(markerListener).createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT, displayEndMarker = true) trackOverlay = MapOverlayHelper(markerListener).createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT, displayStartEndMarker = true)
if (track.wayPoints.isNotEmpty()) { if (track.wayPoints.isNotEmpty()) {
mapView.overlays.add(trackOverlay) mapView.overlays.add(trackOverlay)
} }
@ -168,13 +168,13 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m
/* Updates map overlay */ /* Updates map overlay */
fun updateTrackOverlay(newTrack: Track) { fun updateTrackOverlay(newTrack: Track, displayStartEndMarker: Boolean) {
track = newTrack track = newTrack
if (trackOverlay != null) { if (trackOverlay != null) {
mapView.overlays.remove(trackOverlay) mapView.overlays.remove(trackOverlay)
} }
if (track.wayPoints.isNotEmpty()) { if (track.wayPoints.isNotEmpty()) {
trackOverlay = MapOverlayHelper(markerListener).createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT) trackOverlay = MapOverlayHelper(markerListener).createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT, displayStartEndMarker)
mapView.overlays.add(trackOverlay) mapView.overlays.add(trackOverlay)
} }
} }

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="36dp"
android:width="36dp"
android:viewportHeight="144"
android:viewportWidth="144">
<path android:fillColor="@color/trackbook_blue"
android:pathData="M72,72m-24,0a24,24 0,1 1,48 0a24,24 0,1 1,-48 0"/>
<path android:fillColor="@color/trackbook_red"
android:pathData="M72.02,0C58.088,0 46.82,11.268 46.82,25.2 46.82,44.1 72.02,72 72.02,72c0,0 25.2,-27.9 25.2,-46.8C97.22,11.268 85.952,0 72.02,0ZM72.02,34.2c-4.968,0 -9,-4.032 -9,-9 0,-4.968 4.032,-9 9,-9 4.968,0 9,4.032 9,9 0,4.968 -4.032,9 -9,9z" android:strokeWidth="3.60001"/>
</vector>

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillColor="@color/trackbook_blue"
android:pathData="M24,24m-6,0a6,6 0,1 1,12 0a6,6 0,1 1,-12 0" />
<path
android:fillColor="@color/trackbook_red"
android:pathData="M24,0C19.356,0 15.6,3.756 15.6,8.4 15.6,14.7 24,24 24,24 24,24 32.4,14.7 32.4,8.4 32.4,3.756 28.644,0 24,0ZM24,11.4c-1.656,0 -3,-1.344 -3,-3 0,-1.656 1.344,-3 3,-3 1.656,0 3,1.344 3,3 0,1.656 -1.344,3 -3,3z" />
</vector>

View file

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillColor="@color/trackbook_blue"
android:pathData="M24,28.3275 L28.635,31.125 27.405,25.8525 31.5,22.305 26.1075,21.8475 24,16.875 21.8925,21.8475 16.5,22.305l4.095,3.5475 -1.23,5.2725z" />
<path
android:fillColor="@color/trackbook_red"
android:pathData="M24,0C19.356,0 15.6,3.756 15.6,8.4 15.6,14.7 24,24 24,24 24,24 32.4,14.7 32.4,8.4 32.4,3.756 28.644,0 24,0ZM24,11.4c-1.656,0 -3,-1.344 -3,-3 0,-1.656 1.344,-3 3,-3 1.656,0 3,1.344 3,3 0,1.656 -1.344,3 -3,3z" />
</vector>

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillColor="@color/trackbook_blue"
android:pathData="M24,24m-6,0a6,6 0,1 1,12 0a6,6 0,1 1,-12 0" />
<path
android:fillColor="@color/trackbook_green"
android:pathData="M24,0C19.356,0 15.6,3.756 15.6,8.4 15.6,14.7 24,24 24,24 24,24 32.4,14.7 32.4,8.4 32.4,3.756 28.644,0 24,0ZM24,11.4c-1.656,0 -3,-1.344 -3,-3 0,-1.656 1.344,-3 3,-3 1.656,0 3,1.344 3,3 0,1.656 -1.344,3 -3,3z" />
</vector>

View file

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillColor="@color/trackbook_blue"
android:pathData="M24,28.3275 L28.635,31.125 27.405,25.8525 31.5,22.305 26.1075,21.8475 24,16.875 21.8925,21.8475 16.5,22.305l4.095,3.5475 -1.23,5.2725z" />
<path
android:fillColor="@color/trackbook_green"
android:pathData="M24,0C19.356,0 15.6,3.756 15.6,8.4 15.6,14.7 24,24 24,24 24,24 32.4,14.7 32.4,8.4 32.4,3.756 28.644,0 24,0ZM24,11.4c-1.656,0 -3,-1.344 -3,-3 0,-1.656 1.344,-3 3,-3 1.656,0 3,1.344 3,3 0,1.656 -1.344,3 -3,3z" />
</vector>

View file

@ -1,68 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg version="1.1" x="0px" y="0px" width="36" height="36" viewBox="0 0 36 36" enable-background="new 0 0 96 96"
xml:space="preserve" id="svg224" sodipodi:docname="ic_my_loacation_dot_blue_36px.svg"
inkscape:version="1.1-dev (9017afb, 2021-01-01)" inkscape:label="Layer1" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg"><defs
id="defs228" /><sodipodi:namedview
id="namedview226"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
objecttolerance="10.0"
gridtolerance="10.0"
guidetolerance="10.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
showgrid="false"
units="px"
inkscape:zoom="9.09375"
inkscape:cx="14.295533"
inkscape:cy="28.591065"
inkscape:window-width="2033"
inkscape:window-height="1126"
inkscape:window-x="450"
inkscape:window-y="25"
inkscape:window-maximized="0"
inkscape:current-layer="svg224"
inkscape:document-units="pt" />
<g
id="My_Location_Dot"
inkscape:label="Location Dot"
style="display:inline"
transform="translate(6,6)">
<circle
opacity="0.33"
fill="#2095f2"
cx="12"
cy="12"
id="circle217"
style="display:none;fill:#3c98db;fill-opacity:1;stroke-width:0.25"
r="12"
inkscape:label="Frame 24 px" />
<circle
fill="#2095f2"
cx="12"
cy="12"
id="circle220"
style="fill:#3c98db;fill-opacity:1;stroke-width:0.25"
r="6"
inkscape:label="Core 12 px" />
</g>
<path
d="M 18,22.3275 22.635,25.125 21.405,19.8525 25.5,16.305 20.1075,15.8475 18,10.875 15.8925,15.8475 10.5,16.305 l 4.095,3.5475 -1.23,5.2725 z"
id="path4-3"
style="display:none;fill:#3c98db;fill-opacity:1;stroke-width:0.75"
inkscape:label="Location Star 24 px"
sodipodi:insensitive="true" />
<path
d="M 25.5,16.305 20.1075,15.84 18,10.875 15.8925,15.8475 10.5,16.305 14.595,19.8525 13.365,25.125 18,22.3275 22.635,25.125 21.4125,19.8525 Z m -7.5,4.62 -2.82,1.7025 0.75,-3.21 -2.49,-2.16 3.285,-0.285 L 18,13.95 l 1.2825,3.03 3.285,0.285 -2.49,2.16 0.75,3.21 z"
id="path831"
style="display:none;fill:#3c98db;fill-opacity:1;stroke-width:0.5625"
inkscape:label="Location Star Outline 24 px"
sodipodi:insensitive="true" /><path
d="M 18,0 C 14.517,0 11.7,2.817 11.7,6.3 11.7,11.025 18,18 18,18 18,18 24.3,11.025 24.3,6.3 24.3,2.817 21.483,0 18,0 Z m 0,8.55 c -1.242001,0 -2.25,-1.008 -2.25,-2.25 0,-1.242 1.008,-2.25 2.25,-2.25 1.242,0 2.25,1.008 2.25,2.25 0,1.242 -1.008,2.25 -2.25,2.25 z"
id="path28"
style="display:inline;fill:#dc3d33;fill-opacity:1;stroke-width:0.9"
inkscape:label="Pin" /></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

View file

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.1" x="0px" y="0px" width="48"
height="48" viewBox="0 0 48 48" enable-background="new 0 0 96 96" xml:space="preserve" id="svg224"
sodipodi:docname="Location Marker with Pin 24px.svg" inkscape:version="1.0.2 (e86c870879, 2021-01-15)"
inkscape:label="Layer1"><metadata
id="metadata11"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs228" /><sodipodi:namedview
id="namedview226"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
objecttolerance="10.0"
gridtolerance="10.0"
guidetolerance="10.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
showgrid="false"
units="px"
inkscape:zoom="9.09375"
inkscape:cx="-7.5326457"
inkscape:cy="28.591065"
inkscape:window-width="2033"
inkscape:window-height="1126"
inkscape:window-x="364"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="svg224"
inkscape:document-units="pt"
inkscape:document-rotation="0" />
<g
id="My_Location_Dot"
inkscape:label="Location Dot"
style="display:inline"
transform="translate(12,12)">
<circle
opacity="0.33"
fill="#2095f2"
cx="12"
cy="12"
id="circle217"
style="display:none;fill:#3c98db;fill-opacity:1;stroke-width:0.25"
r="12"
inkscape:label="Frame 24 px" />
<circle
fill="#2095f2"
cx="12"
cy="12"
id="circle220"
style="fill:#3c98db;fill-opacity:1;stroke-width:0.25"
r="6"
inkscape:label="Core 12 px" />
</g>
<path
d="M 24,28.3275 28.635,31.125 27.405,25.8525 31.5,22.305 26.1075,21.8475 24,16.875 21.8925,21.8475 16.5,22.305 l 4.095,3.5475 -1.23,5.2725 z"
id="path4-3"
style="display:none;fill:#3c98db;fill-opacity:1;stroke-width:0.75"
inkscape:label="Location Star 24 px"
sodipodi:insensitive="true" />
<path
d="M 31.5,22.305 26.1075,21.84 24,16.875 21.8925,21.8475 16.5,22.305 20.595,25.8525 19.365,31.125 24,28.3275 28.635,31.125 27.4125,25.8525 Z m -7.5,4.62 -2.82,1.7025 0.75,-3.21 -2.49,-2.16 3.285,-0.285 L 24,19.95 l 1.2825,3.03 3.285,0.285 -2.49,2.16 0.75,3.21 z"
id="path831"
style="display:none;fill:#3c98db;fill-opacity:1;stroke-width:0.5625"
inkscape:label="Location Star Outline 24 px"
sodipodi:insensitive="true" /><path
d="M 24,0 C 19.356,0 15.6,3.756 15.6,8.4 15.6,14.7 24,24 24,24 24,24 32.4,14.7 32.4,8.4 32.4,3.756 28.644,0 24,0 Z m 0,11.4 c -1.656001,0 -3,-1.344 -3,-3 0,-1.656 1.344,-3 3,-3 1.656,0 3,1.344 3,3 0,1.656 -1.344,3 -3,3 z"
id="path28"
style="display:inline;fill:#dc3d33;fill-opacity:1;stroke-width:1.2"
inkscape:label="Pin" /></svg>

After

Width:  |  Height:  |  Size: 3.1 KiB