new feature: you can mark a recorded waypoint as POI see #71

This commit is contained in:
y20k 2020-07-30 13:59:07 +02:00
parent 6290cbd709
commit 18d043cafe
No known key found for this signature in database
GPG key ID: 824D4259F41FAFF6
18 changed files with 120 additions and 209 deletions

View file

@ -10,7 +10,7 @@ android {
defaultConfig { defaultConfig {
applicationId 'org.y20k.trackbook' applicationId 'org.y20k.trackbook'
minSdkVersion 25 minSdkVersion 25
targetSdkVersion 27 targetSdkVersion 29
versionCode 42 versionCode 42
versionName '2.0.5' versionName '2.0.5'
resConfigs "en", "da", "de", "fr", "hr", "id", "it", "ja", "nb-rNO", "nl", "sv", "zh-rCN" resConfigs "en", "da", "de", "fr", "hr", "id", "it", "ja", "nb-rNO", "nl", "sv", "zh-rCN"

View file

@ -30,7 +30,6 @@ import androidx.preference.PreferenceManager
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import org.osmdroid.config.Configuration import org.osmdroid.config.Configuration
import org.y20k.trackbook.helpers.AppThemeHelper import org.y20k.trackbook.helpers.AppThemeHelper
import org.y20k.trackbook.helpers.ImportHelper
import org.y20k.trackbook.helpers.LogHelper import org.y20k.trackbook.helpers.LogHelper
import org.y20k.trackbook.helpers.PreferencesHelper import org.y20k.trackbook.helpers.PreferencesHelper
@ -91,12 +90,6 @@ class MainActivity : AppCompatActivity() {
} }
} }
// convert old tracks (one-time import)
if (PreferencesHelper.isHouseKeepingNecessary(this)) {
ImportHelper.convertOldTracks(this)
PreferencesHelper.saveHouseKeepingNecessaryState(this)
}
// register listener for changes in shared preferences // register listener for changes in shared preferences
PreferenceManager.getDefaultSharedPreferences(this as Context).registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener) PreferenceManager.getDefaultSharedPreferences(this as Context).registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener)
} }

View file

@ -44,7 +44,7 @@ import org.y20k.trackbook.ui.MapFragmentLayoutHolder
/* /*
* MapFragment class * MapFragment class
*/ */
class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener { class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener, MapOverlay.MarkerListener {
/* Define log tag */ /* Define log tag */
private val TAG: String = LogHelper.makeLogTag(MapFragment::class.java) private val TAG: String = LogHelper.makeLogTag(MapFragment::class.java)
@ -75,7 +75,7 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener {
/* Overrides onStop from Fragment */ /* Overrides onStop from Fragment */
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// initialize layout // initialize layout
layout = MapFragmentLayoutHolder(activity as Context, inflater, container, currentBestLocation, trackingState) layout = MapFragmentLayoutHolder(activity as Context, this as MapOverlay.MarkerListener, inflater, container, currentBestLocation, trackingState)
// set up buttons // set up buttons
layout.currentLocationButton.setOnClickListener { layout.currentLocationButton.setOnClickListener {
@ -178,6 +178,17 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener {
} }
/* Overrides onMarkerTapped from MarkerListener */
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)
trackerService.track = track
}
}
/* Start tracker service */ /* Start tracker service */
private fun startTrackerService() { private fun startTrackerService() {
val intent = Intent(activity, TrackerService::class.java) val intent = Intent(activity, TrackerService::class.java)

View file

@ -41,10 +41,12 @@ import org.y20k.trackbook.core.Track
import org.y20k.trackbook.dialogs.RenameTrackDialog import org.y20k.trackbook.dialogs.RenameTrackDialog
import org.y20k.trackbook.helpers.FileHelper import org.y20k.trackbook.helpers.FileHelper
import org.y20k.trackbook.helpers.LogHelper import org.y20k.trackbook.helpers.LogHelper
import org.y20k.trackbook.helpers.MapOverlay
import org.y20k.trackbook.helpers.TrackHelper
import org.y20k.trackbook.ui.TrackFragmentLayoutHolder import org.y20k.trackbook.ui.TrackFragmentLayoutHolder
class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDialog.YesNoDialogListener { class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDialog.YesNoDialogListener, MapOverlay.MarkerListener {
/* Define log tag */ /* Define log tag */
private val TAG: String = LogHelper.makeLogTag(TrackFragment::class.java) private val TAG: String = LogHelper.makeLogTag(TrackFragment::class.java)
@ -71,7 +73,7 @@ class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDi
/* Overrides onCreateView from Fragment */ /* Overrides onCreateView from Fragment */
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// initialize layout // initialize layout
layout = TrackFragmentLayoutHolder(activity as Context, inflater, container, track) layout = TrackFragmentLayoutHolder(activity as Context, this as MapOverlay.MarkerListener, inflater, container, track)
// set up share button // set up share button
layout.shareButton.setOnClickListener { layout.shareButton.setOnClickListener {
@ -162,6 +164,19 @@ class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDi
} }
/* Overrides onMarkerTapped from MarkerListener */
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)
// save track
GlobalScope.launch {
FileHelper.saveTrackSuspended(track, true)
}
}
/* Opens up a file picker to select the save location */ /* Opens up a file picker to select the save location */
private fun openSaveGpxDialog() { private fun openSaveGpxDialog() {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply { val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
@ -182,7 +197,7 @@ class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDi
/* Share track as GPX via share sheet */ /* Share track as GPX via share sheet */
private fun shareGpxTrack() { private fun shareGpxTrack() {
val gpxFile = Uri.parse(layout.track.gpxUriString).toFile() val gpxFile = Uri.parse(layout.track.gpxUriString).toFile()
val gpxShareUri = FileProvider.getUriForFile(this.activity as Context, "${activity!!.applicationContext.packageName}.provider", gpxFile) val gpxShareUri = FileProvider.getUriForFile(this.activity as Context, "${requireActivity().applicationContext.packageName}.provider", gpxFile)
val shareIntent: Intent = Intent.createChooser(Intent().apply { val shareIntent: Intent = Intent.createChooser(Intent().apply {
action = Intent.ACTION_SEND action = Intent.ACTION_SEND
data = gpxShareUri data = gpxShareUri

View file

@ -37,7 +37,8 @@ data class WayPoint(@Expose val provider: String,
@Expose val time: Long, @Expose val time: Long,
@Expose val distanceToStartingPoint: Float = 0f, @Expose val distanceToStartingPoint: Float = 0f,
@Expose val numberSatellites: Int = 0, @Expose val numberSatellites: Int = 0,
@Expose var isStopOver: Boolean = false): Parcelable { @Expose var isStopOver: Boolean = false,
@Expose var starred: Boolean = false): Parcelable {
/* Converts WayPoint into Location */ /* Converts WayPoint into Location */

View file

@ -1,168 +0,0 @@
/*
* ImportHelper.kt
* Implements the ImportHelper object
* A ImportHelper manages the one-time import of old .trackbook files
*
* This file is part of
* TRACKBOOK - Movement Recorder for Android
*
* Copyright (c) 2016-20 - Y20K.org
* Licensed under the MIT-License
* http://opensource.org/licenses/MIT
*
* Trackbook uses osmdroid - OpenStreetMap-Tools for Android
* https://github.com/osmdroid/osmdroid
*/
package org.y20k.trackbook.helpers
import android.content.Context
import android.location.Location
import androidx.annotation.Keep
import com.google.gson.GsonBuilder
import com.google.gson.annotations.SerializedName
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.y20k.trackbook.Keys
import org.y20k.trackbook.core.Track
import org.y20k.trackbook.core.WayPoint
import java.io.BufferedReader
import java.io.File
import java.io.InputStream
import java.io.InputStreamReader
import java.util.*
/*
* ImportHelper data class
*/
object ImportHelper {
/* Define log tag */
private val TAG: String = LogHelper.makeLogTag(ImportHelper::class.java)
/* Converts older tracks of type .trackbook into the new format */
fun convertOldTracks(context: Context) {
val oldTracks: ArrayList<Track> = arrayListOf()
val trackFolder: File? = context.getExternalFilesDir(Keys.FOLDER_TRACKS)
if (trackFolder != null && trackFolder.exists() && trackFolder.isDirectory) {
trackFolder.listFiles()?.forEach { file ->
if (file.name.endsWith(".trackbook")) {
// read until last line reached
val stream: InputStream = file.inputStream()
val reader: BufferedReader = BufferedReader(InputStreamReader(stream))
val builder: StringBuilder = StringBuilder()
reader.forEachLine {
builder.append(it)
builder.append("\n") }
stream.close()
// get content of file
val fileContent: String = builder.toString()
// get LegacyTrack from JSON
val gsonBuilder = GsonBuilder()
gsonBuilder.setDateFormat("M/d/yy hh:mm a")
val oldTrack: LegacyTrack = gsonBuilder.create().fromJson(fileContent, LegacyTrack::class.java)
oldTracks.add(oldTrack.toTrack())
}
}
}
// save track using "deferred await"
if (oldTracks.isNotEmpty()) {
GlobalScope.launch {
oldTracks.forEach { oldTrack ->
// step 1: create and store filenames for json and gpx files
oldTrack.trackUriString = FileHelper.getTrackFileUri(context, oldTrack).toString()
oldTrack.gpxUriString = FileHelper.getGpxFileUri(context, oldTrack).toString()
// step 2: save track
FileHelper.saveTrackSuspended(oldTrack, saveGpxToo = true)
// step 3: save tracklist
FileHelper.addTrackAndSaveTracklistSuspended(context, oldTrack)
}
}
}
}
/*
* Inner class: Legacy version of Track - used for one-time import only
* Warning: Works only as long as targetSdkVersion < 28
*/
@Keep
private data class LegacyTrack (
@SerializedName("b") var mTrackFormatVersion: Int = 0,
@SerializedName("c") var mWayPoints: List<LegacyWayPoint>,
@SerializedName("d") var mTrackLength: Float = 0f,
@SerializedName("e") var mDuration: Long = 0,
@SerializedName("f") var mStepCount: Float = 0f,
@SerializedName("g") var mRecordingStart: Date = GregorianCalendar.getInstance().time,
@SerializedName("h") var mRecordingStop: Date = mRecordingStart,
@SerializedName("i") var mMaxAltitude: Double = 0.0,
@SerializedName("j") var mMinAltitude: Double = 0.0,
@SerializedName("k") var mPositiveElevation: Double = 0.0,
@SerializedName("l") var mNegativeElevation: Double = 0.0) {
/* Converts */
fun toTrack():Track {
val track: Track = Track()
track.trackFormatVersion = mTrackFormatVersion
mWayPoints.forEach { legacyWayPoint ->
val wayPoint: WayPoint= WayPoint(
provider = legacyWayPoint.mLocation.provider,
latitude = legacyWayPoint.mLocation.latitude,
longitude = legacyWayPoint.mLocation.longitude,
altitude = legacyWayPoint.mLocation.altitude,
accuracy = legacyWayPoint.mLocation.accuracy,
time = legacyWayPoint.mLocation.time,
distanceToStartingPoint = legacyWayPoint.mDistanceToStartingPoint,
numberSatellites = legacyWayPoint.mNumberSatellites,
isStopOver = legacyWayPoint.mIsStopOver
)
track.wayPoints.add(wayPoint)
}
track.length = mTrackLength
track.duration = mDuration
track.stepCount = mStepCount
track.recordingStart = mRecordingStart
track.recordingStop = mRecordingStop
track.maxAltitude = mMaxAltitude
track.minAltitude = mMinAltitude
track.positiveElevation = mPositiveElevation
track.negativeElevation = mNegativeElevation
track.latitude = track.wayPoints[0].latitude
track.longitude = track.wayPoints[0].longitude
track.name = DateTimeHelper.convertToReadableDate(mRecordingStart)
return track
}
}
/*
* End of inner class
*/
/*
* Inner class: Legacy version of WayPoint - used for one-time import only
* Warning: Works only as long as targetSdkVersion < 28
*/
@Keep
private data class LegacyWayPoint (
@SerializedName("a") var mLocation: Location,
@SerializedName("b") var mIsStopOver: Boolean = false,
@SerializedName("c") var mDistanceToStartingPoint: Float = 0f,
@SerializedName("d") var mNumberSatellites: Int = 0) {
}
/*
* End of inner class
*/
}

View file

@ -106,7 +106,6 @@ object LengthUnitHelper {
// speed in km/h / mph // speed in km/h / mph
val velocity: Double = convertMetersPerSecond((trackLength / duration), useImperialUnits) val velocity: Double = convertMetersPerSecond((trackLength / duration), useImperialUnits)
// create readable speed string // create readable speed string
LogHelper.e("TAG", "duration = $duration velocity = $velocity")
var bd: BigDecimal = BigDecimal.valueOf(velocity) var bd: BigDecimal = BigDecimal.valueOf(velocity)
bd = bd.setScale(1, RoundingMode.HALF_UP) bd = bd.setScale(1, RoundingMode.HALF_UP)
speed = bd.toPlainString() speed = bd.toPlainString()

View file

@ -36,12 +36,18 @@ import java.util.*
/* /*
* MapHelper object * MapHelper class
*/ */
object MapHelper { class MapOverlay (private var markerListener: MarkerListener) {
/* Interface used to communicate back to activity/fragment */
interface MarkerListener {
fun onMarkerTapped(latitude: Double, longitude: Double) {
}
}
/* Define log tag */ /* Define log tag */
private val LOG_TAG = MapHelper::class.java.simpleName private val TAG = MapOverlay::class.java.simpleName
/* Creates icon overlay for current position (used in MapFragment) */ /* Creates icon overlay for current position (used in MapFragment) */
@ -93,16 +99,22 @@ object MapHelper {
when (trackingState) { when (trackingState) {
// CASE: Recording is active // CASE: Recording is active
Keys.STATE_TRACKING_ACTIVE -> { Keys.STATE_TRACKING_ACTIVE -> {
when (wayPoint.isStopOver) { if (wayPoint.starred) {
true -> newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_grey_24dp)!! newMarker = ContextCompat.getDrawable(context, R.drawable.ic_star_red_24dp)!!
false -> newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_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)!!
} }
} }
// CASE: Recording is paused/stopped // CASE: Recording is paused/stopped
else -> { else -> {
when (wayPoint.isStopOver) { if (wayPoint.starred) {
true -> newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_grey_24dp)!! newMarker = ContextCompat.getDrawable(context, R.drawable.ic_star_blue_24dp)!!
false -> newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_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)!!
} }
} }
} }
@ -121,7 +133,8 @@ object MapHelper {
/* Creates a marker overlay item */ /* Creates a marker overlay item */
private fun createOverlayItem(context: Context, latitude: Double, longitude: Double, accuracy: Float, provider: String, time: Long): OverlayItem { private fun createOverlayItem(context: Context, latitude: Double, longitude: Double, accuracy: Float, provider: String, time: Long): OverlayItem {
val title: String = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(time)}" val title: String = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(time)}"
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 position: GeoPoint = GeoPoint(latitude, longitude) val position: GeoPoint = GeoPoint(latitude, longitude)
return OverlayItem(title, description, position) return OverlayItem(title, description, position)
} }
@ -129,10 +142,10 @@ object MapHelper {
/* Creates an overlay */ /* Creates an overlay */
private fun createOverlay(context: Context, overlayItems: ArrayList<OverlayItem>): ItemizedIconOverlay<OverlayItem> { private fun createOverlay(context: Context, overlayItems: ArrayList<OverlayItem>): ItemizedIconOverlay<OverlayItem> {
return ItemizedIconOverlay(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 {
Toast.makeText(context, item.title, Toast.LENGTH_LONG).show() markerListener.onMarkerTapped(item.point.latitude, item.point.longitude)
return true return true
} }
override fun onItemLongPress(index: Int, item: OverlayItem): Boolean { override fun onItemLongPress(index: Int, item: OverlayItem): Boolean {
@ -141,8 +154,7 @@ object MapHelper {
Toast.makeText(context, item.snippet, Toast.LENGTH_LONG).show() Toast.makeText(context, item.snippet, Toast.LENGTH_LONG).show()
return true return true
} }
}, context) })
} }
} }

View file

@ -19,6 +19,8 @@ package org.y20k.trackbook.helpers
import android.content.Context import android.content.Context
import android.location.Location import android.location.Location
import android.widget.Toast
import org.y20k.trackbook.R
import org.y20k.trackbook.core.Track import org.y20k.trackbook.core.Track
import org.y20k.trackbook.core.TracklistElement import org.y20k.trackbook.core.TracklistElement
import org.y20k.trackbook.core.WayPoint import org.y20k.trackbook.core.WayPoint
@ -219,5 +221,18 @@ object TrackHelper {
} }
/* Toggles starred flag for given position */
fun toggleStarred(context: Context, track: Track, latitude: Double, longitude: Double): Track {
track.wayPoints.forEach { waypoint ->
if (waypoint.latitude == latitude && waypoint.longitude == longitude) {
waypoint.starred = !waypoint.starred
when (waypoint.starred) {
true -> Toast.makeText(context, R.string.toast_message_poi_added, Toast.LENGTH_LONG).show()
false -> Toast.makeText(context, R.string.toast_message_poi_removed, Toast.LENGTH_LONG).show()
}
}
}
return track
}
} }

View file

@ -88,8 +88,8 @@ class TracklistAdapter(private val fragment: Fragment) : RecyclerView.Adapter<Re
trackElementViewHolder.trackNameView.text = tracklist.tracklistElements[position].name trackElementViewHolder.trackNameView.text = tracklist.tracklistElements[position].name
trackElementViewHolder.trackDataView.text = createTrackDataString(position) trackElementViewHolder.trackDataView.text = createTrackDataString(position)
when (tracklist.tracklistElements[position].starred) { when (tracklist.tracklistElements[position].starred) {
true -> trackElementViewHolder.starButton.setImageDrawable(context.getDrawable(R.drawable.ic_star_24dp)) true -> trackElementViewHolder.starButton.setImageDrawable(context.getDrawable(R.drawable.ic_star_filled_24dp))
false -> trackElementViewHolder.starButton.setImageDrawable(context.getDrawable(R.drawable.ic_star_border_24dp)) false -> trackElementViewHolder.starButton.setImageDrawable(context.getDrawable(R.drawable.ic_star_outline_24dp))
} }
trackElementViewHolder.trackElement.setOnClickListener { trackElementViewHolder.trackElement.setOnClickListener {
tracklistListener.onTrackElementTapped(tracklist.tracklistElements[position]) tracklistListener.onTrackElementTapped(tracklist.tracklistElements[position])
@ -134,11 +134,11 @@ class TracklistAdapter(private val fragment: Fragment) : RecyclerView.Adapter<Re
val starButton: ImageButton = view as ImageButton val starButton: ImageButton = view as ImageButton
when (tracklist.tracklistElements[position].starred) { when (tracklist.tracklistElements[position].starred) {
true -> { true -> {
starButton.setImageDrawable(context.getDrawable(R.drawable.ic_star_border_24dp)) starButton.setImageDrawable(context.getDrawable(R.drawable.ic_star_outline_24dp))
tracklist.tracklistElements[position].starred = false tracklist.tracklistElements[position].starred = false
} }
false -> { false -> {
starButton.setImageDrawable(context.getDrawable(R.drawable.ic_star_24dp)) starButton.setImageDrawable(context.getDrawable(R.drawable.ic_star_filled_24dp))
tracklist.tracklistElements[position].starred = true tracklist.tracklistElements[position].starred = true
} }
} }

View file

@ -44,14 +44,14 @@ import org.y20k.trackbook.R
import org.y20k.trackbook.core.Track import org.y20k.trackbook.core.Track
import org.y20k.trackbook.helpers.AppThemeHelper import org.y20k.trackbook.helpers.AppThemeHelper
import org.y20k.trackbook.helpers.LogHelper import org.y20k.trackbook.helpers.LogHelper
import org.y20k.trackbook.helpers.MapHelper import org.y20k.trackbook.helpers.MapOverlay
import org.y20k.trackbook.helpers.PreferencesHelper import org.y20k.trackbook.helpers.PreferencesHelper
/* /*
* MapFragmentLayoutHolder class * MapFragmentLayoutHolder class
*/ */
data class MapFragmentLayoutHolder(var context: Context, var inflater: LayoutInflater, var container: ViewGroup?, val startLocation: Location, val trackingState: Int) { data class MapFragmentLayoutHolder(private var context: Context, private var markerListener: MapOverlay.MarkerListener, private var inflater: LayoutInflater, private var container: ViewGroup?, private val startLocation: Location, private val trackingState: Int) {
/* Define log tag */ /* Define log tag */
private val TAG: String = LogHelper.makeLogTag(MapFragmentLayoutHolder::class.java) private val TAG: String = LogHelper.makeLogTag(MapFragmentLayoutHolder::class.java)
@ -109,7 +109,7 @@ data class MapFragmentLayoutHolder(var context: Context, var inflater: LayoutInf
mapView.overlays.add(compassOverlay) mapView.overlays.add(compassOverlay)
// add my location overlay // add my location overlay
currentPositionOverlay = MapHelper.createMyLocationOverlay(context, startLocation, trackingState) currentPositionOverlay = MapOverlay(markerListener).createMyLocationOverlay(context, startLocation, trackingState)
mapView.overlays.add(currentPositionOverlay) mapView.overlays.add(currentPositionOverlay)
centerMap(startLocation) centerMap(startLocation)
@ -157,7 +157,7 @@ data class MapFragmentLayoutHolder(var context: Context, var inflater: LayoutInf
/* Mark current position on map */ /* Mark current position on map */
fun markCurrentPosition(location: Location, trackingState: Int = Keys.STATE_TRACKING_NOT) { fun markCurrentPosition(location: Location, trackingState: Int = Keys.STATE_TRACKING_NOT) {
mapView.overlays.remove(currentPositionOverlay) mapView.overlays.remove(currentPositionOverlay)
currentPositionOverlay = MapHelper.createMyLocationOverlay(context, location, trackingState) currentPositionOverlay = MapOverlay(markerListener).createMyLocationOverlay(context, location, trackingState)
mapView.overlays.add(currentPositionOverlay) mapView.overlays.add(currentPositionOverlay)
} }
@ -168,7 +168,7 @@ data class MapFragmentLayoutHolder(var context: Context, var inflater: LayoutInf
mapView.overlays.remove(currentTrackOverlay) mapView.overlays.remove(currentTrackOverlay)
} }
if (track.wayPoints.isNotEmpty()) { if (track.wayPoints.isNotEmpty()) {
currentTrackOverlay = MapHelper.createTrackOverlay(context, track, trackingState) currentTrackOverlay = MapOverlay(markerListener).createTrackOverlay(context, track, trackingState)
mapView.overlays.add(currentTrackOverlay) mapView.overlays.add(currentTrackOverlay)
} }
} }

View file

@ -50,7 +50,7 @@ import kotlin.math.roundToInt
/* /*
* TrackFragmentLayoutHolder class * TrackFragmentLayoutHolder class
*/ */
data class TrackFragmentLayoutHolder(var context: Context, var inflater: LayoutInflater, var container: ViewGroup?, var track: Track) { data class TrackFragmentLayoutHolder(private var context: Context, private var markerListener: MapOverlay.MarkerListener, private var inflater: LayoutInflater, private var container: ViewGroup?, var track: Track) {
/* Define log tag */ /* Define log tag */
private val TAG: String = LogHelper.makeLogTag(TrackFragmentLayoutHolder::class.java) private val TAG: String = LogHelper.makeLogTag(TrackFragmentLayoutHolder::class.java)
@ -140,7 +140,7 @@ data class TrackFragmentLayoutHolder(var context: Context, var inflater: LayoutI
mapView.overlays.add(compassOverlay) mapView.overlays.add(compassOverlay)
// create map overlay // create map overlay
trackOverlay = MapHelper.createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT) trackOverlay = MapOverlay(markerListener).createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT)
if (track.wayPoints.isNotEmpty()) { if (track.wayPoints.isNotEmpty()) {
mapView.overlays.add(trackOverlay) mapView.overlays.add(trackOverlay)
} }
@ -161,6 +161,19 @@ data class TrackFragmentLayoutHolder(var context: Context, var inflater: LayoutI
} }
/* Updates map overlay */
fun updateTrackOverlay(newTrack: Track) {
track = newTrack
if (trackOverlay != null) {
mapView.overlays.remove(trackOverlay)
}
if (track.wayPoints.isNotEmpty()) {
trackOverlay = MapOverlay(markerListener).createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT)
mapView.overlays.add(trackOverlay)
}
}
/* Saves zoom level and center of this map */ /* Saves zoom level and center of this map */
fun saveViewStateToTrack() { fun saveViewStateToTrack() {
val center: IGeoPoint = mapView.mapCenter val center: IGeoPoint = mapView.mapCenter

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/trackbook_blue"
android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/trackbook_red"
android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
</vector>

View file

@ -57,7 +57,7 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_star_border_24dp" /> app:srcCompat="@drawable/ic_star_outline_24dp" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -43,6 +43,8 @@
<string name="toast_message_copied_to_clipboard">Copied to clipboard.</string> <string name="toast_message_copied_to_clipboard">Copied to clipboard.</string>
<string name="toast_message_elevation_info">Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured.</string> <string name="toast_message_elevation_info">Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured.</string>
<string name="toast_message_install_file_helper">Unable to save. Please install a file manager first.</string> <string name="toast_message_install_file_helper">Unable to save. Please install a file manager first.</string>
<string name="toast_message_poi_added">Point of interest marker added.</string>
<string name="toast_message_poi_removed">Point of interest marker removed.</string>
<string name="toast_message_save_gpx">Saving recording as GPX.</string> <string name="toast_message_save_gpx">Saving recording as GPX.</string>
<!-- Map Markers --> <!-- Map Markers -->
<string name="marker_description_time">Time</string> <string name="marker_description_time">Time</string>