use SimpleFastPointOverlay for the track overlay (see #96)
This commit is contained in:
parent
c193e8a475
commit
1c70fe1b5e
6 changed files with 117 additions and 76 deletions
|
@ -181,11 +181,11 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener, MapOverlayHelpe
|
|||
|
||||
|
||||
/* Overrides onMarkerTapped from MarkerListener */
|
||||
override fun onMarkerTapped(latitude: Double, longitude: Double, displayStartEndMarker: Boolean) {
|
||||
super.onMarkerTapped(latitude, longitude, displayStartEndMarker)
|
||||
override fun onMarkerTapped(latitude: Double, longitude: Double) {
|
||||
super.onMarkerTapped(latitude, longitude)
|
||||
if (bound) {
|
||||
track = TrackHelper.toggleStarred(activity as Context, track, latitude, longitude)
|
||||
layout.overlayCurrentTrack(track, trackingState, displayStartEndMarker)
|
||||
layout.overlayCurrentTrack(track, trackingState)
|
||||
trackerService.track = track
|
||||
}
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener, MapOverlayHelpe
|
|||
trackingState = trackerService.trackingState
|
||||
// update location and track
|
||||
layout.markCurrentPosition(currentBestLocation, trackingState)
|
||||
layout.overlayCurrentTrack(track, trackingState, displayStartEndMarker = false)
|
||||
layout.overlayCurrentTrack(track, trackingState)
|
||||
// center map, if it had not been dragged/zoomed before
|
||||
if (!layout.userInteraction) { layout.centerMap(currentBestLocation, true)}
|
||||
// show error snackbar if necessary
|
||||
|
|
|
@ -162,11 +162,11 @@ class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDi
|
|||
|
||||
|
||||
/* Overrides onMarkerTapped from MarkerListener */
|
||||
override fun onMarkerTapped(latitude: Double, longitude: Double, displayStartEndMarker: Boolean) {
|
||||
super.onMarkerTapped(latitude, longitude, displayStartEndMarker)
|
||||
override fun onMarkerTapped(latitude: Double, longitude: Double) {
|
||||
super.onMarkerTapped(latitude, longitude)
|
||||
// update track display
|
||||
track = TrackHelper.toggleStarred(activity as Context, track, latitude, longitude)
|
||||
layout.updateTrackOverlay(track, displayStartEndMarker)
|
||||
layout.updateTrackOverlay(track)
|
||||
// save track
|
||||
GlobalScope.launch {
|
||||
FileHelper.saveTrackSuspended(track, true)
|
||||
|
|
|
@ -476,7 +476,6 @@ class TrackerService: Service(), CoroutineScope, SensorEventListener {
|
|||
if (now.time - lastSave.time > Keys.SAVE_TEMP_TRACK_INTERVAL) {
|
||||
lastSave = now
|
||||
GlobalScope.launch { FileHelper.saveTempTrackSuspended(this@TrackerService, track) }
|
||||
LogHelper.e(TAG, "TEMP SAVE: $lastSave")
|
||||
}
|
||||
}
|
||||
// update notification
|
||||
|
|
|
@ -19,14 +19,20 @@ package org.y20k.trackbook.helpers
|
|||
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Paint
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.location.Location
|
||||
import android.os.Vibrator
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import org.osmdroid.api.IGeoPoint
|
||||
import org.osmdroid.util.GeoPoint
|
||||
import org.osmdroid.views.overlay.ItemizedIconOverlay
|
||||
import org.osmdroid.views.overlay.OverlayItem
|
||||
import org.osmdroid.views.overlay.simplefastpoint.LabelledGeoPoint
|
||||
import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlay
|
||||
import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlayOptions
|
||||
import org.osmdroid.views.overlay.simplefastpoint.SimplePointTheme
|
||||
import org.y20k.trackbook.Keys
|
||||
import org.y20k.trackbook.R
|
||||
import org.y20k.trackbook.core.Track
|
||||
|
@ -44,7 +50,7 @@ class MapOverlayHelper (private var markerListener: MarkerListener) {
|
|||
|
||||
/* Interface used to communicate back to activity/fragment */
|
||||
interface MarkerListener {
|
||||
fun onMarkerTapped(latitude: Double, longitude: Double, displayStartEndMarker: Boolean) {
|
||||
fun onMarkerTapped(latitude: Double, longitude: Double) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,70 +89,86 @@ class MapOverlayHelper (private var markerListener: MarkerListener) {
|
|||
overlayItems.add(overlayItem)
|
||||
|
||||
// create and return overlay for current position
|
||||
return createOverlay(context, overlayItems, enableStarring = false, displayStartEndMarker = false)
|
||||
return createOverlay(context, overlayItems, enableStarring = false)
|
||||
}
|
||||
|
||||
|
||||
/* Creates icon overlay for track */
|
||||
fun createTrackOverlay(context: Context, track: Track, trackingState: Int, displayStartEndMarker: Boolean = false): ItemizedIconOverlay<OverlayItem> {
|
||||
|
||||
val overlayItems: ArrayList<OverlayItem> = ArrayList<OverlayItem>()
|
||||
val wayPoints: MutableList<WayPoint> = track.wayPoints
|
||||
val maxIndex: Int = wayPoints.size - 1
|
||||
|
||||
when (trackingState) {
|
||||
// CASE: Recording is active
|
||||
Keys.STATE_TRACKING_ACTIVE -> {
|
||||
wayPoints.forEach { wayPoint: WayPoint ->
|
||||
// get drawable
|
||||
val newMarker: Drawable
|
||||
if (wayPoint.starred) {
|
||||
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_star_red_24dp)!!
|
||||
} else if (wayPoint.isStopOver) {
|
||||
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_grey_24dp)!!
|
||||
} else {
|
||||
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_red_24dp)!!
|
||||
}
|
||||
// create overlay item and add to list of overlay items
|
||||
val overlayItem: OverlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
|
||||
overlayItem.setMarker(newMarker)
|
||||
overlayItems.add(overlayItem)
|
||||
}
|
||||
}
|
||||
// CASE: Recording is paused/stopped
|
||||
else -> {
|
||||
wayPoints.forEachIndexed { index: Int, wayPoint: WayPoint ->
|
||||
// get drawable
|
||||
val newMarker: Drawable
|
||||
if (displayStartEndMarker && index == 0) {
|
||||
if (wayPoint.starred) {
|
||||
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_start_starred_blue_48dp)!!
|
||||
} else {
|
||||
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) {
|
||||
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_star_blue_24dp)!!
|
||||
} else if (wayPoint.isStopOver) {
|
||||
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_grey_24dp)!!
|
||||
} else {
|
||||
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_blue_24dp)!!
|
||||
}
|
||||
// create overlay item and add to list of overlay items
|
||||
val overlayItem: OverlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
|
||||
overlayItem.setMarker(newMarker)
|
||||
overlayItems.add(overlayItem)
|
||||
}
|
||||
fun createTrackOverlay(context: Context, track: Track, trackingState: Int): SimpleFastPointOverlay {
|
||||
// get marker color
|
||||
val color = if (trackingState == Keys.STATE_TRACKING_ACTIVE) context.getColor(R.color.trackbook_red)
|
||||
else context.getColor(R.color.trackbook_blue)
|
||||
// gather points for overlay
|
||||
val points: MutableList<IGeoPoint> = mutableListOf()
|
||||
track.wayPoints.forEach { wayPoint ->
|
||||
val label: String = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(wayPoint.time)} | ${context.getString(R.string.marker_description_accuracy)}: ${DecimalFormat("#0.00").format(wayPoint.accuracy)} (${wayPoint.provider})"
|
||||
// only add normal points
|
||||
if (!wayPoint.starred && !wayPoint.isStopOver) {
|
||||
points.add(LabelledGeoPoint(wayPoint.latitude, wayPoint.longitude, wayPoint.altitude, label))
|
||||
}
|
||||
}
|
||||
val pointTheme: SimplePointTheme = SimplePointTheme(points, false)
|
||||
// set styling for overlay
|
||||
val style: Paint = Paint()
|
||||
style.style = Paint.Style.FILL
|
||||
style.color = color
|
||||
val scalingFactor: Float = UiHelper.getDensityScalingFactor(context)
|
||||
val overlayOptions: SimpleFastPointOverlayOptions = SimpleFastPointOverlayOptions.getDefaultStyle()
|
||||
.setAlgorithm(SimpleFastPointOverlayOptions.RenderingAlgorithm.MAXIMUM_OPTIMIZATION)
|
||||
.setSymbol(SimpleFastPointOverlayOptions.Shape.CIRCLE)
|
||||
.setPointStyle(style)
|
||||
.setRadius(6F * scalingFactor) // radius is set in px - scaling factor makes that display density independent (= dp)
|
||||
.setIsClickable(true)
|
||||
// .setCellSize(15) // Sets the grid cell size used for indexing, in pixels. Larger cells result in faster rendering speed, but worse fidelity. Default is 10 pixels, for large datasets (>10k points), use 15.
|
||||
// create and return overlay
|
||||
val overlay: SimpleFastPointOverlay = SimpleFastPointOverlay(pointTheme, overlayOptions)
|
||||
overlay.setOnClickListener(object : SimpleFastPointOverlay.OnClickListener {
|
||||
override fun onClick(points: SimpleFastPointOverlay.PointAdapter?, point: Int?) {
|
||||
if (points != null && point != null) {
|
||||
val markerPoint: IGeoPoint = points.get(point)
|
||||
markerListener.onMarkerTapped(markerPoint.latitude, markerPoint.longitude)
|
||||
}
|
||||
}
|
||||
})
|
||||
return overlay
|
||||
}
|
||||
|
||||
|
||||
/* Creates overlay containing start, stop, stopover and starred markers for track */
|
||||
fun createSpecialMakersTrackOverlay(context: Context, track: Track, trackingState: Int, displayStartEndMarker: Boolean = false): ItemizedIconOverlay<OverlayItem> {
|
||||
val overlayItems: ArrayList<OverlayItem> = ArrayList<OverlayItem>()
|
||||
val trackingActive: Boolean = trackingState == Keys.STATE_TRACKING_ACTIVE
|
||||
val maxIndex: Int = track.wayPoints.size - 1
|
||||
|
||||
track.wayPoints.forEachIndexed { index: Int, wayPoint: WayPoint ->
|
||||
var overlayItem: OverlayItem? = null
|
||||
if (!trackingActive && index == 0 && displayStartEndMarker && wayPoint.starred) {
|
||||
overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
|
||||
overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_start_starred_blue_48dp)!!)
|
||||
} else if (!trackingActive && index == 0 && displayStartEndMarker && !wayPoint.starred) {
|
||||
overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
|
||||
overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_start_blue_48dp)!!)
|
||||
} else if (!trackingActive && index == maxIndex && displayStartEndMarker && wayPoint.starred) {
|
||||
overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
|
||||
overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_starred_blue_48dp)!!)
|
||||
} else if (!trackingActive && index == maxIndex && displayStartEndMarker && !wayPoint.starred) {
|
||||
overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
|
||||
overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_blue_48dp)!!)
|
||||
} else if (!trackingActive && wayPoint.starred) {
|
||||
overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
|
||||
overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_star_blue_24dp)!!)
|
||||
} else if (trackingActive && wayPoint.starred) {
|
||||
overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
|
||||
overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_star_red_24dp)!!)
|
||||
} else if (wayPoint.isStopOver) {
|
||||
overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
|
||||
overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_grey_24dp)!!)
|
||||
}
|
||||
// add overlay item, if it was created
|
||||
if (overlayItem != null) overlayItems.add(overlayItem)
|
||||
}
|
||||
// create and return overlay for current position
|
||||
return createOverlay(context, overlayItems, enableStarring = true, displayStartEndMarker = displayStartEndMarker)
|
||||
return createOverlay(context, overlayItems, enableStarring = true)
|
||||
}
|
||||
|
||||
|
||||
|
@ -163,12 +185,12 @@ class MapOverlayHelper (private var markerListener: MarkerListener) {
|
|||
|
||||
|
||||
/* Creates an overlay */
|
||||
private fun createOverlay(context: Context, overlayItems: ArrayList<OverlayItem>, enableStarring: Boolean, displayStartEndMarker: Boolean): ItemizedIconOverlay<OverlayItem> {
|
||||
private fun createOverlay(context: Context, overlayItems: ArrayList<OverlayItem>, enableStarring: Boolean): ItemizedIconOverlay<OverlayItem> {
|
||||
return ItemizedIconOverlay<OverlayItem>(context, overlayItems,
|
||||
object : ItemizedIconOverlay.OnItemGestureListener<OverlayItem> {
|
||||
override fun onItemSingleTapUp(index: Int, item: OverlayItem): Boolean {
|
||||
if (enableStarring) {
|
||||
markerListener.onMarkerTapped(item.point.latitude, item.point.longitude, displayStartEndMarker)
|
||||
markerListener.onMarkerTapped(item.point.latitude, item.point.longitude)
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.osmdroid.views.overlay.OverlayItem
|
|||
import org.osmdroid.views.overlay.TilesOverlay
|
||||
import org.osmdroid.views.overlay.compass.CompassOverlay
|
||||
import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider
|
||||
import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlay
|
||||
import org.y20k.trackbook.Keys
|
||||
import org.y20k.trackbook.R
|
||||
import org.y20k.trackbook.core.Track
|
||||
|
@ -67,7 +68,8 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar
|
|||
val resumeButton: FloatingActionButton
|
||||
var userInteraction: Boolean = false
|
||||
private var currentPositionOverlay: ItemizedIconOverlay<OverlayItem>
|
||||
private var currentTrackOverlay: ItemizedIconOverlay<OverlayItem>?
|
||||
private var currentTrackOverlay: SimpleFastPointOverlay?
|
||||
private var currentTrackSpecialMarkerOverlay: ItemizedIconOverlay<OverlayItem>?
|
||||
private var locationErrorBar: Snackbar
|
||||
private var controller: IMapController
|
||||
private var zoomLevel: Double
|
||||
|
@ -112,8 +114,9 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar
|
|||
mapView.overlays.add(currentPositionOverlay)
|
||||
centerMap(startLocation)
|
||||
|
||||
// initialize track overlay
|
||||
// initialize track overlays
|
||||
currentTrackOverlay = null
|
||||
currentTrackSpecialMarkerOverlay = null
|
||||
|
||||
// initialize recording button state
|
||||
updateRecordingButton(trackingState)
|
||||
|
@ -162,13 +165,19 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar
|
|||
|
||||
|
||||
/* Overlay current track on map */
|
||||
fun overlayCurrentTrack(track: Track, trackingState: Int, displayStartEndMarker: Boolean) {
|
||||
fun overlayCurrentTrack(track: Track, trackingState: Int) {
|
||||
if (currentTrackOverlay != null) {
|
||||
mapView.overlays.remove(currentTrackOverlay)
|
||||
}
|
||||
if (currentTrackSpecialMarkerOverlay != null) {
|
||||
mapView.overlays.remove(currentTrackSpecialMarkerOverlay)
|
||||
}
|
||||
if (track.wayPoints.isNotEmpty()) {
|
||||
currentTrackOverlay = MapOverlayHelper(markerListener).createTrackOverlay(context, track, trackingState, displayStartEndMarker)
|
||||
val mapOverlayHelper: MapOverlayHelper = MapOverlayHelper(markerListener)
|
||||
currentTrackOverlay = mapOverlayHelper.createTrackOverlay(context, track, trackingState)
|
||||
currentTrackSpecialMarkerOverlay = mapOverlayHelper.createSpecialMakersTrackOverlay(context, track, trackingState)
|
||||
mapView.overlays.add(currentTrackOverlay)
|
||||
mapView.overlays.add(currentTrackSpecialMarkerOverlay)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.osmdroid.views.overlay.OverlayItem
|
|||
import org.osmdroid.views.overlay.TilesOverlay
|
||||
import org.osmdroid.views.overlay.compass.CompassOverlay
|
||||
import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider
|
||||
import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlay
|
||||
import org.y20k.trackbook.Keys
|
||||
import org.y20k.trackbook.R
|
||||
import org.y20k.trackbook.core.Track
|
||||
|
@ -68,7 +69,8 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m
|
|||
val editButton: ImageButton
|
||||
val trackNameView: MaterialTextView
|
||||
private val mapView: MapView
|
||||
private var trackOverlay: ItemizedIconOverlay<OverlayItem>?
|
||||
private var trackSpecialMarkersOverlay: ItemizedIconOverlay<OverlayItem>?
|
||||
private var trackOverlay: SimpleFastPointOverlay?
|
||||
private var controller: IMapController
|
||||
private var zoomLevel: Double
|
||||
private val statisticsSheetBehavior: BottomSheetBehavior<View>
|
||||
|
@ -146,9 +148,12 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m
|
|||
mapView.overlays.add(compassOverlay)
|
||||
|
||||
// create map overlay
|
||||
trackOverlay = MapOverlayHelper(markerListener).createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT, displayStartEndMarker = true)
|
||||
val mapOverlayHelper: MapOverlayHelper = MapOverlayHelper(markerListener)
|
||||
trackOverlay = mapOverlayHelper.createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT)
|
||||
trackSpecialMarkersOverlay = mapOverlayHelper.createSpecialMakersTrackOverlay(context, track, Keys.STATE_TRACKING_NOT, displayStartEndMarker = true)
|
||||
if (track.wayPoints.isNotEmpty()) {
|
||||
mapView.overlays.add(trackOverlay)
|
||||
mapView.overlays.add(trackSpecialMarkersOverlay)
|
||||
}
|
||||
|
||||
// set up and show statistics sheet
|
||||
|
@ -168,14 +173,20 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m
|
|||
|
||||
|
||||
/* Updates map overlay */
|
||||
fun updateTrackOverlay(newTrack: Track, displayStartEndMarker: Boolean) {
|
||||
fun updateTrackOverlay(newTrack: Track) {
|
||||
track = newTrack
|
||||
if (trackOverlay != null) {
|
||||
mapView.overlays.remove(trackOverlay)
|
||||
}
|
||||
if (trackSpecialMarkersOverlay != null) {
|
||||
mapView.overlays.remove(trackSpecialMarkersOverlay)
|
||||
}
|
||||
if (track.wayPoints.isNotEmpty()) {
|
||||
trackOverlay = MapOverlayHelper(markerListener).createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT, displayStartEndMarker)
|
||||
val mapOverlayHelper: MapOverlayHelper = MapOverlayHelper(markerListener)
|
||||
trackOverlay = mapOverlayHelper.createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT)
|
||||
trackSpecialMarkersOverlay = mapOverlayHelper.createSpecialMakersTrackOverlay(context, track, Keys.STATE_TRACKING_NOT, displayStartEndMarker = true)
|
||||
mapView.overlays.add(trackOverlay)
|
||||
mapView.overlays.add(trackSpecialMarkersOverlay)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue