display distance and duration on map while Trackbook is recording.
This commit is contained in:
parent
264f704124
commit
9a7fc6fcb9
7 changed files with 128 additions and 12 deletions
|
@ -361,6 +361,7 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener, MapOverlayHelpe
|
|||
// update location and track
|
||||
layout.markCurrentPosition(currentBestLocation, trackingState)
|
||||
layout.overlayCurrentTrack(track, trackingState)
|
||||
layout.updateLiveStatics(length = track.length, duration = track.duration, trackingState = trackingState)
|
||||
// center map, if it had not been dragged/zoomed before
|
||||
if (!layout.userInteraction) { layout.centerMap(currentBestLocation, true)}
|
||||
// show error snackbar if necessary
|
||||
|
|
|
@ -33,25 +33,51 @@ import java.util.concurrent.TimeUnit
|
|||
object DateTimeHelper {
|
||||
|
||||
/* Converts milliseconds to mm:ss or hh:mm:ss */
|
||||
fun convertToReadableTime(context: Context, milliseconds: Long): String {
|
||||
val timeString: String
|
||||
fun convertToReadableTime(context: Context, milliseconds: Long, compactFormat: Boolean = false): String {
|
||||
val hours: Long = TimeUnit.MILLISECONDS.toHours(milliseconds)
|
||||
val minutes: Long = TimeUnit.MILLISECONDS.toMinutes(milliseconds) % TimeUnit.HOURS.toMinutes(1)
|
||||
val seconds: Long = TimeUnit.MILLISECONDS.toSeconds(milliseconds) % TimeUnit.MINUTES.toSeconds(1)
|
||||
val timeString: String
|
||||
|
||||
when (compactFormat) {
|
||||
|
||||
// Compact tine format
|
||||
true -> {
|
||||
if (milliseconds < Keys.ONE_HOUR_IN_MILLISECONDS) {
|
||||
// example: 23:45
|
||||
val minutesString: String = minutes.toString()
|
||||
val secondsString: String = seconds.toString().padStart(2, '0')
|
||||
timeString = "$minutesString:$secondsString"
|
||||
} else {
|
||||
// example: 1:23
|
||||
val hoursString: String = hours.toString()
|
||||
val minutesString: String = minutes.toString()
|
||||
timeString = "$hoursString:$minutesString"
|
||||
}
|
||||
}
|
||||
|
||||
// Long time format
|
||||
false -> {
|
||||
if (milliseconds < Keys.ONE_HOUR_IN_MILLISECONDS) {
|
||||
// example: 23 min 45 sec
|
||||
val minutesString: String = minutes.toString()
|
||||
val secondsString: String = seconds.toString()
|
||||
val m: String = context.getString(R.string.abbreviation_minutes)
|
||||
val s: String = context.getString(R.string.abbreviation_seconds)
|
||||
timeString = "$minutesString $m $secondsString $s"
|
||||
} else {
|
||||
// example: 1 hrs 23 min 45 sec
|
||||
val hoursString: String = hours.toString()
|
||||
val minutesString: String = minutes.toString()
|
||||
val secondsString: String = seconds.toString()
|
||||
val h: String = context.getString(R.string.abbreviation_hours)
|
||||
val m: String = context.getString(R.string.abbreviation_minutes)
|
||||
val s: String = context.getString(R.string.abbreviation_seconds)
|
||||
timeString = "$hoursString $h $minutesString $m $secondsString $s"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when (milliseconds >= Keys.ONE_HOUR_IN_MILLISECONDS) {
|
||||
// CASE: format hh:mm:ss
|
||||
true -> {
|
||||
timeString = "$hours $h $minutes $m $seconds $s"
|
||||
}
|
||||
// CASE: format mm:ss
|
||||
false -> {
|
||||
timeString = "$minutes $m $seconds $s"
|
||||
}
|
||||
}
|
||||
return timeString
|
||||
}
|
||||
|
||||
|
|
|
@ -22,16 +22,19 @@ import android.annotation.SuppressLint
|
|||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Paint
|
||||
import android.location.Location
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.constraintlayout.widget.Group
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.textview.MaterialTextView
|
||||
import org.osmdroid.api.IMapController
|
||||
import org.osmdroid.tileprovider.tilesource.TileSourceFactory
|
||||
import org.osmdroid.util.GeoPoint
|
||||
|
@ -70,6 +73,11 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar
|
|||
private var currentPositionOverlay: ItemizedIconOverlay<OverlayItem>
|
||||
private var currentTrackOverlay: SimpleFastPointOverlay?
|
||||
private var currentTrackSpecialMarkerOverlay: ItemizedIconOverlay<OverlayItem>?
|
||||
private val liveStatisticsDistanceView: MaterialTextView
|
||||
private val liveStatisticsDistanceOutlineView: MaterialTextView
|
||||
private val liveStatisticsDurationView: MaterialTextView
|
||||
private val liveStatisticsDurationOutlineView: MaterialTextView
|
||||
private val useImperial: Boolean = PreferencesHelper.loadUseImperialUnits()
|
||||
private var locationErrorBar: Snackbar
|
||||
private var controller: IMapController
|
||||
private var zoomLevel: Double
|
||||
|
@ -86,6 +94,10 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar
|
|||
saveButton = rootView.findViewById(R.id.fab_sub_menu_button_save)
|
||||
clearButton = rootView.findViewById(R.id.fab_sub_menu_button_clear)
|
||||
resumeButton = rootView.findViewById(R.id.fab_sub_menu_button_resume)
|
||||
liveStatisticsDistanceView = rootView.findViewById(R.id.live_statistics_distance)
|
||||
liveStatisticsDistanceOutlineView = rootView.findViewById(R.id.live_statistics_distance_outline)
|
||||
liveStatisticsDurationView = rootView.findViewById(R.id.live_statistics_duration)
|
||||
liveStatisticsDurationOutlineView = rootView.findViewById(R.id.live_statistics_duration_outline)
|
||||
locationErrorBar = Snackbar.make(mapView, String(), Snackbar.LENGTH_INDEFINITE)
|
||||
|
||||
// basic map setup
|
||||
|
@ -102,13 +114,20 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar
|
|||
mapView.overlayManager.tilesOverlay.setColorFilter(TilesOverlay.INVERT_COLORS)
|
||||
}
|
||||
|
||||
// store Density Scaling Factor
|
||||
val densityScalingFactor: Float = UiHelper.getDensityScalingFactor(context)
|
||||
|
||||
// add compass to map
|
||||
val compassOverlay = CompassOverlay(context, InternalCompassOrientationProvider(context), mapView)
|
||||
compassOverlay.enableCompass()
|
||||
compassOverlay.setCompassCenter(36f, 36f + (statusBarHeight / UiHelper.getDensityScalingFactor(context)))
|
||||
|
||||
compassOverlay.setCompassCenter(36f, 36f + (statusBarHeight / densityScalingFactor))
|
||||
mapView.overlays.add(compassOverlay)
|
||||
|
||||
// position the live statistics
|
||||
(liveStatisticsDistanceView.layoutParams as ConstraintLayout.LayoutParams).apply {
|
||||
topMargin = (12 * densityScalingFactor).toInt() + statusBarHeight
|
||||
}
|
||||
|
||||
// add my location overlay
|
||||
currentPositionOverlay = MapOverlayHelper(markerListener).createMyLocationOverlay(context, startLocation, trackingState)
|
||||
mapView.overlays.add(currentPositionOverlay)
|
||||
|
@ -182,6 +201,27 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar
|
|||
}
|
||||
|
||||
|
||||
/* Update live statics */
|
||||
fun updateLiveStatics(length: Float, duration: Long, trackingState: Int) {
|
||||
// toggle visibility
|
||||
val trackingActive: Boolean = trackingState != Keys.STATE_TRACKING_NOT
|
||||
liveStatisticsDistanceView.isVisible = trackingActive
|
||||
liveStatisticsDurationView.isVisible = trackingActive
|
||||
// update distance and duration (and add outline)
|
||||
val distanceString: String = LengthUnitHelper.convertDistanceToString(length, useImperial)
|
||||
liveStatisticsDistanceView.text = distanceString
|
||||
liveStatisticsDistanceOutlineView.text = distanceString
|
||||
liveStatisticsDistanceOutlineView.paint.strokeWidth = 5f
|
||||
liveStatisticsDistanceOutlineView.paint.style = Paint.Style.STROKE
|
||||
val durationString: String = DateTimeHelper.convertToReadableTime(context, duration, compactFormat = true)
|
||||
liveStatisticsDurationView.text = durationString
|
||||
liveStatisticsDurationOutlineView.text = durationString
|
||||
liveStatisticsDurationOutlineView.paint.strokeWidth = 5f
|
||||
liveStatisticsDurationOutlineView.paint.style = Paint.Style.STROKE
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Toggles state of recording button and sub menu_bottom_navigation */
|
||||
fun updateRecordingButton(trackingState: Int) {
|
||||
when (trackingState) {
|
||||
|
|
|
@ -201,6 +201,50 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:tint="@color/location_button_icon" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/live_statistics_distance_outline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAlignment="textEnd"
|
||||
android:textAppearance="@style/TextAppearance.Material3.LabelLarge"
|
||||
android:textColor="@color/text_outline_default"
|
||||
app:layout_constraintEnd_toEndOf="@+id/live_statistics_distance"
|
||||
app:layout_constraintTop_toTopOf="@+id/live_statistics_distance" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/live_statistics_distance"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="64dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textAlignment="textEnd"
|
||||
android:textAppearance="@style/TextAppearance.Material3.LabelLarge"
|
||||
android:textColor="@color/text_default"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@string/sample_text_default_live_statistics_distance" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/live_statistics_duration_outline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAlignment="textEnd"
|
||||
android:textAppearance="@style/TextAppearance.Material3.LabelLarge"
|
||||
android:textColor="@color/text_outline_default"
|
||||
app:layout_constraintEnd_toEndOf="@+id/live_statistics_duration"
|
||||
app:layout_constraintTop_toTopOf="@+id/live_statistics_duration" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/live_statistics_duration"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAlignment="textEnd"
|
||||
android:textAppearance="@style/TextAppearance.Material3.LabelLarge"
|
||||
android:textColor="@color/text_default"
|
||||
app:layout_constraintEnd_toEndOf="@+id/live_statistics_distance"
|
||||
app:layout_constraintTop_toBottomOf="@+id/live_statistics_distance"
|
||||
tools:text="@string/sample_text_default_live_statistics_duration" />
|
||||
|
||||
<!-- GROUPS -->
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/fab_sub_menu"
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
<color name="text_default">@color/trackbook_neutral_white</color>
|
||||
<color name="text_lightweight">@color/trackbook_neutral_very_light</color>
|
||||
<color name="text_outline_default">@color/trackbook_neutral_darker</color>
|
||||
|
||||
<color name="icon_default">@color/trackbook_neutral_white</color>
|
||||
<color name="icon_lightweight">@color/trackbook_neutral_very_light</color>
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
<color name="text_default">@color/trackbook_neutral_darker</color>
|
||||
<color name="text_lightweight">@color/trackbook_neutral_dark</color>
|
||||
<color name="text_outline_default">@color/trackbook_neutral_white</color>
|
||||
|
||||
|
||||
<color name="icon_default">@color/trackbook_neutral_dark</color>
|
||||
<color name="icon_lightweight">@color/trackbook_neutral_medium_light</color>
|
||||
|
|
|
@ -128,4 +128,6 @@
|
|||
<string name="sample_text_track_name" translatable="false">July 20, 1969</string>
|
||||
<string name="sample_text_default_data" translatable="false">track data missing</string>
|
||||
<string name="sample_text_default_total_distance" translatable="false">6357.23 km</string>
|
||||
<string name="sample_text_default_live_statistics_distance" translatable="false">23.0 km</string>
|
||||
<string name="sample_text_default_live_statistics_duration" translatable="false">5:23</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue