display distance and duration on map while Trackbook is recording.

This commit is contained in:
y20k 2022-01-11 17:54:49 +01:00
parent 264f704124
commit 9a7fc6fcb9
No known key found for this signature in database
GPG key ID: 824D4259F41FAFF6
7 changed files with 128 additions and 12 deletions

View file

@ -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

View file

@ -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 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)
val timeString: String
when (milliseconds >= Keys.ONE_HOUR_IN_MILLISECONDS) {
// CASE: format hh:mm:ss
when (compactFormat) {
// Compact tine format
true -> {
timeString = "$hours $h $minutes $m $seconds $s"
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"
}
}
// CASE: format mm:ss
// Long time format
false -> {
timeString = "$minutes $m $seconds $s"
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"
}
}
}
return timeString
}

View file

@ -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) {

View file

@ -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"

View file

@ -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>

View file

@ -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>

View file

@ -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>