forked from upstream-mirrors/OpenTracks
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 397e056f6f | |||
| eb79f2277a | |||
| ae8833d21b | |||
| e8017a4e9d | |||
| cea180f871 | |||
| be1b6ece9d | |||
| 0592863d3c | |||
| 18bc100d5a | |||
| 4476a15558 | |||
| 215c28be85 | |||
| a429fbe4df | |||
| 6b470c7fdc | |||
| 6b690f38ad | |||
| f138826d60 | |||
| 14ac29095d | |||
| a3f4de7d18 | |||
| 6392e88dc7 | |||
| 1e913d6bb5 | |||
| ced8454f59 | |||
| 974a5afeb1 | |||
| 9c9bdde6b9 | |||
| ca2bc6426c | |||
| 81097aac40 | |||
| a74b5fc743 |
@@ -9,6 +9,7 @@
|
||||
* Polar OH1
|
||||
Has updatable firmware that requires a user account at polar.com
|
||||
* Wahoo Tickr (Model: WFBTHR02)
|
||||
* Mi Band 3, Amazfit Band 5, Amazfit Bip. These devices are manufactured by Huami, and other Huami devices will very likely work. Theoretically, this sensor must be enabled, but testing reveals that it works even without enabling. For details on how to enable see [Gadgetbridge wiki](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Huami-Heartrate-measurement#bluetooth-heart-rate-sensor)
|
||||
|
||||
## CSCP: Cycling Cadence and Speed Service
|
||||
|
||||
@@ -39,4 +40,5 @@ Also the distance is not computed.
|
||||
* Elite drivo II
|
||||
* QUARQ Red DZero Powermeter
|
||||
* Tacx Satori Smart
|
||||
* Wahoo Kickr v4.0
|
||||
* Wahoo Kickr v4.0
|
||||
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ cp "$CHANGELOG_DIR/next_release.txt" "$CHANGELOG_FILE"
|
||||
sed -i "s/(versionName)/$VERSIONNAME/" "$CHANGELOG_FILE"
|
||||
|
||||
echo -e "\nGit commit since last release\n------------"
|
||||
git log $(git describe --tags --abbrev=0)..HEAD --no-merges --oneline
|
||||
git log "$(git describe --tags --abbrev=0)..HEAD" --no-merges --oneline
|
||||
|
||||
echo -e "\nPlease edit the changelog for the new release"
|
||||
gedit -w "$CHANGELOG_FILE"
|
||||
|
||||
+3
-3
@@ -51,8 +51,8 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "de.dennisguse.opentracks"
|
||||
versionCode 3737
|
||||
versionName "v3.13.1"
|
||||
versionCode 3761
|
||||
versionName "v3.14.0"
|
||||
|
||||
buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\""
|
||||
|
||||
@@ -98,5 +98,5 @@ dependencies {
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test:rules:1.3.0'
|
||||
androidTestImplementation 'androidx.test:runner:1.3.0'
|
||||
androidTestImplementation 'org.mockito:mockito-android:3.6.0'
|
||||
androidTestImplementation 'org.mockito:mockito-android:3.6.28'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
v3.13.2: OpenTracks
|
||||
|
||||
Bugfix:
|
||||
- Crash in landscape mode
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
v3.14.0: OpenTracks
|
||||
|
||||
Changes:
|
||||
- Properly support for right-to-left
|
||||
- Import: faster cleanup after import failure
|
||||
- Text in charts scales according to Android settings
|
||||
- Heart rate: support for Huami devices (requires Gadgetbridge)
|
||||
|
||||
Developer:
|
||||
- Import is now handled in-memory
|
||||
@@ -48,7 +48,9 @@ public class ChartValueSeriesTest {
|
||||
R.string.description_elevation_metric,
|
||||
R.string.description_elevation_imperial,
|
||||
R.color.chart_elevation_fill,
|
||||
R.color.chart_elevation_border) {
|
||||
R.color.chart_elevation_border,
|
||||
15,
|
||||
18) {
|
||||
@Override
|
||||
double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
return chartPoint.getElevation();
|
||||
|
||||
@@ -9,6 +9,7 @@ import androidx.test.filters.LargeTest;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
@@ -196,6 +197,7 @@ public class ExportImportTest {
|
||||
assertNull(importedTrack);
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@LargeTest
|
||||
@Test
|
||||
public void kmz_only_track() {
|
||||
@@ -203,6 +205,7 @@ public class ExportImportTest {
|
||||
Log.e(TAG, "Test not implemented.");
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@LargeTest
|
||||
@Test
|
||||
public void kmz_with_trackdetail() {
|
||||
@@ -210,6 +213,7 @@ public class ExportImportTest {
|
||||
Log.e(TAG, "Test not implemented.");
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@LargeTest
|
||||
@Test
|
||||
public void kmz_with_trackdetail_and_sensordata() {
|
||||
@@ -217,6 +221,7 @@ public class ExportImportTest {
|
||||
Log.e(TAG, "Test not implemented.");
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@LargeTest
|
||||
@Test
|
||||
public void kmz_with_trackdetail_and_sensordata_and_pictures() {
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
package de.dennisguse.opentracks.io.file.importer;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.filters.LargeTest;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* Imports a legacy kml file with a statistics marker at the beginning
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
public class LegacyKmlImportTest {
|
||||
|
||||
private final Context context = ApplicationProvider.getApplicationContext();
|
||||
private final ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context);
|
||||
|
||||
private Track.Id importTrackId;
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
if (importTrackId != null) {
|
||||
contentProviderUtils.deleteTrack(context, importTrackId);
|
||||
}
|
||||
}
|
||||
|
||||
@LargeTest
|
||||
@Test
|
||||
public void kml_legacy_track_import() {
|
||||
// given
|
||||
KmlFileTrackImporter trackImporter = new KmlFileTrackImporter(context);
|
||||
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.legacy_track);
|
||||
|
||||
// when
|
||||
// 1. import
|
||||
importTrackId = trackImporter.importFile(inputStream);
|
||||
|
||||
// then
|
||||
// 1. track
|
||||
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
|
||||
assertNotNull(importedTrack);
|
||||
assertEquals("unknown", importedTrack.getCategory());
|
||||
assertEquals("Test Track", importedTrack.getDescription());
|
||||
assertEquals("2020-11-28 18:06", importedTrack.getName());
|
||||
assertEquals("UNKNOWN", importedTrack.getIcon());
|
||||
|
||||
// 2. markers
|
||||
assertEquals(0, contentProviderUtils.getMarkerCount(importTrackId));
|
||||
|
||||
// 3. trackpoints
|
||||
List<TrackPoint> importedTrackPoints = contentProviderUtils.getTrackPoints(importTrackId);
|
||||
assertEquals(8, importedTrackPoints.size()); // 6 trackpoints + pause and resume
|
||||
|
||||
// first 3 trackpoints
|
||||
assertTrackpoint(importedTrackPoints.get(0), "2020-11-28T17:06:22.401Z", 1.234156, 12.340097, 469.286376953125);
|
||||
assertTrackpoint(importedTrackPoints.get(1), "2020-11-28T17:06:25.448Z", 1.23415, 12.340036, 439.1626281738281);
|
||||
assertTrackpoint(importedTrackPoints.get(2), "2020-11-28T17:06:47.888Z", 1.23405, 12.340057, 421.8070983886719);
|
||||
|
||||
// created pause trackpoint with time of previous valid trackpoint
|
||||
assertTrackpoint(importedTrackPoints.get(3), "2020-11-28T17:06:47.888Z", 0.0, 100, 0.0);
|
||||
// created resume trackpoint with time of next valid trackpoint
|
||||
assertTrackpoint(importedTrackPoints.get(4), "2020-11-28T17:06:55.861Z", 0.0, 200, 0.0);
|
||||
|
||||
// last 3 trackpoints
|
||||
assertTrackpoint(importedTrackPoints.get(5), "2020-11-28T17:06:55.861Z", 1.23405, 12.340057, 419.93902587890625);
|
||||
assertTrackpoint(importedTrackPoints.get(6), "2020-11-28T17:06:56.905Z", 1.23405, 12.340057, 419.9036560058594);
|
||||
assertTrackpoint(importedTrackPoints.get(7), "2020-11-28T17:07:20.870Z", 1.234046, 12.340082, 417.99432373046875);
|
||||
}
|
||||
|
||||
private void assertTrackpoint(final TrackPoint trackPoint, final String when, final double longitude, final double latitude, final double altitude) {
|
||||
assertEquals(StringUtils.parseTime(when), trackPoint.getTime());
|
||||
assertEquals(latitude, trackPoint.getLatitude(), 0.001d);
|
||||
assertEquals(longitude, trackPoint.getLongitude(), 0.001d);
|
||||
assertEquals(altitude, trackPoint.getAltitude(), 0.001d);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -9,7 +9,7 @@ import org.junit.Test;
|
||||
*/
|
||||
public class ElevationSumManagerTest {
|
||||
|
||||
private ElevationSumManager elevationSumManager = new ElevationSumManager();
|
||||
private final ElevationSumManager elevationSumManager = new ElevationSumManager();
|
||||
|
||||
private static void addSensorValue(ElevationSumManager elevationSumManager, float[] values) {
|
||||
for (float f : values) {
|
||||
|
||||
@@ -226,4 +226,13 @@ public class StringUtilsTest {
|
||||
assertEquals("min/km", StringUtils.getSpeedParts(context, 0, true, false).second);
|
||||
assertEquals("min/mi", StringUtils.getSpeedParts(context, 0, false, false).second);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormatSpeed() {
|
||||
assertEquals("4:59 min/km", StringUtils.formatSpeed(context, 3.34, true, false));
|
||||
assertEquals("8:02 min/mi", StringUtils.formatSpeed(context, 3.34, false, false));
|
||||
|
||||
assertEquals("12.02 km/h", StringUtils.formatSpeed(context, 3.34, true, true));
|
||||
assertEquals("7.47 mph", StringUtils.formatSpeed(context, 3.34, false, true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kml xmlns="http://www.opengis.net/kml/2.2"
|
||||
xmlns:gx="http://www.google.com/kml/ext/2.2"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom"
|
||||
xmlns:opentracks="http://opentracksapp.com/xmlschemas/v1">
|
||||
<Document>
|
||||
<open>1</open>
|
||||
<visibility>1</visibility>
|
||||
<name><![CDATA[2020-11-28 18:06]]></name>
|
||||
<atom:generator><![CDATA[OpenTracks (Debug)]]></atom:generator>
|
||||
<Style id="track">
|
||||
<LineStyle><color>7f0000ff</color><width>4</width></LineStyle>
|
||||
<IconStyle>
|
||||
<scale>1.3</scale>
|
||||
<Icon><href>http://earth.google.com/images/kml-icons/track-directional/track-0.png</href></Icon>
|
||||
</IconStyle>
|
||||
</Style>
|
||||
<Style id="start"><IconStyle>
|
||||
<scale>1.3</scale>
|
||||
<Icon><href>http://maps.google.com/mapfiles/kml/paddle/grn-circle.png</href></Icon>
|
||||
<hotSpot x="32" y="1" xunits="pixels" yunits="pixels"/>
|
||||
</IconStyle></Style>
|
||||
<Style id="end"><IconStyle>
|
||||
<scale>1.3</scale>
|
||||
<Icon><href>http://maps.google.com/mapfiles/kml/paddle/red-circle.png</href></Icon>
|
||||
<hotSpot x="32" y="1" xunits="pixels" yunits="pixels"/>
|
||||
</IconStyle></Style>
|
||||
<Style id="waypoint"><IconStyle>
|
||||
<scale>1.3</scale>
|
||||
<Icon><href>http://maps.google.com/mapfiles/kml/pushpin/blue-pushpin.png</href></Icon>
|
||||
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
|
||||
</IconStyle></Style>
|
||||
<Schema id="schema">
|
||||
<gx:SimpleArrayField name="speed" type="float">
|
||||
<displayName><![CDATA[Speed (m/s)]]></displayName>
|
||||
</gx:SimpleArrayField>
|
||||
<gx:SimpleArrayField name="power" type="float">
|
||||
<displayName><![CDATA[Power (W)]]></displayName>
|
||||
</gx:SimpleArrayField>
|
||||
<gx:SimpleArrayField name="cadence" type="float">
|
||||
<displayName><![CDATA[Cadence (rpm)]]></displayName>
|
||||
</gx:SimpleArrayField>
|
||||
<gx:SimpleArrayField name="heart_rate" type="float">
|
||||
<displayName><![CDATA[Heart rate (bpm)]]></displayName>
|
||||
</gx:SimpleArrayField>
|
||||
</Schema>
|
||||
<Folder>
|
||||
<name><![CDATA[Sun, 28 Nov 2020 18:06 Markers]]></name>
|
||||
<open>1</open>
|
||||
<Placemark>
|
||||
<name><![CDATA[Split 0]]></name>
|
||||
<description><![CDATA[Total distance: 0.00 km (0.0 mi)
|
||||
Total time: 00:00
|
||||
Moving time: 00:00
|
||||
Average speed: 0.00 km/h (0.0 mi/h)
|
||||
Average moving speed: 0.00 km/h (0.0 mi/h)
|
||||
Max speed: 0.00 km/h (0.0 mi/h)
|
||||
Average pace: 0:00 min/km (0:00 min/mi)
|
||||
Average moving pace: 0:00 min/km (0:00 min/mi)
|
||||
Fastest pace: 0:00 min/km (0:00 min/mi)
|
||||
Max elevation: -9223372036854775808 m (-9223372036854775808 ft)
|
||||
Min elevation: 9223372036854775807 m (9223372036854775807 ft)
|
||||
Elevation gain: 0 m (0 ft)
|
||||
Max grade: 0 %
|
||||
Min grade: 0 %
|
||||
Recorded: 6/23 11:29
|
||||
]]></description>
|
||||
<TimeStamp><when>1970-01-01T00:00:00Z</when></TimeStamp>
|
||||
<styleUrl>#waypoint</styleUrl>
|
||||
<Point>
|
||||
<coordinates>180.0,100.0</coordinates>
|
||||
</Point>
|
||||
</Placemark>
|
||||
</Folder>
|
||||
<Placemark>
|
||||
<name><![CDATA[2020-11-28 18:06 (Start)]]></name>
|
||||
<description><![CDATA[]]></description>
|
||||
<TimeStamp><when>2020-11-28T17:06:22.401Z</when></TimeStamp>
|
||||
<styleUrl>#start</styleUrl>
|
||||
<Point>
|
||||
<coordinates>1.234156,12.340097,469.286376953125</coordinates>
|
||||
</Point>
|
||||
</Placemark>
|
||||
<Placemark>
|
||||
<name><![CDATA[2020-11-28 18:06]]></name>
|
||||
<description><![CDATA[Test Track]]></description>
|
||||
<icon><![CDATA[UNKNOWN]]></icon>
|
||||
<opentracks:trackid>2f170875-55d7-445d-b2b8-22a573c81dbc</opentracks:trackid>
|
||||
<styleUrl>#track</styleUrl>
|
||||
<ExtendedData>
|
||||
<Data name="type"><value><![CDATA[unknown]]></value></Data>
|
||||
</ExtendedData>
|
||||
<gx:MultiTrack>
|
||||
<altitudeMode>absolute</altitudeMode>
|
||||
<gx:interpolate>1</gx:interpolate>
|
||||
<gx:Track>
|
||||
<when>2020-11-28T17:06:22.401Z</when>
|
||||
<gx:coord>1.234156 12.340097 469.286376953125</gx:coord>
|
||||
<when>2020-11-28T17:06:25.448Z</when>
|
||||
<gx:coord>1.23415 12.340036 439.1626281738281</gx:coord>
|
||||
<when>2020-11-28T17:06:47.888Z</when>
|
||||
<gx:coord>1.23405 12.340057 421.8070983886719</gx:coord>
|
||||
<ExtendedData>
|
||||
<SchemaData schemaUrl="#schema">
|
||||
<gx:SimpleArrayData name="speed">
|
||||
<gx:value>0.5391469</gx:value>
|
||||
<gx:value>0.15777911</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
</gx:SimpleArrayData>
|
||||
<gx:SimpleArrayData name="elevation_gain">
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
</gx:SimpleArrayData>
|
||||
</SchemaData>
|
||||
</ExtendedData>
|
||||
</gx:Track>
|
||||
<gx:Track>
|
||||
<when>2020-11-28T17:06:55.861Z</when>
|
||||
<gx:coord>1.23405 12.340057 419.93902587890625</gx:coord>
|
||||
<when>2020-11-28T17:06:56.905Z</when>
|
||||
<gx:coord>1.23405 12.340057 419.9036560058594</gx:coord>
|
||||
<when>2020-11-28T17:07:20.870Z</when>
|
||||
<gx:coord>1.234046 12.340082 417.99432373046875</gx:coord>
|
||||
<ExtendedData>
|
||||
<SchemaData schemaUrl="#schema">
|
||||
<gx:SimpleArrayData name="speed">
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
</gx:SimpleArrayData>
|
||||
<gx:SimpleArrayData name="elevation_gain">
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
</gx:SimpleArrayData>
|
||||
</SchemaData>
|
||||
</ExtendedData>
|
||||
</gx:Track>
|
||||
</gx:MultiTrack>
|
||||
</Placemark>
|
||||
<Placemark>
|
||||
<name><![CDATA[2020-11-28 18:06 (End)]]></name>
|
||||
<description><![CDATA[OpenTracks (Debug)
|
||||
|
||||
Name: 2020-11-28 18:06
|
||||
Activity type: unknown
|
||||
Description: -
|
||||
Total distance: 0.01 km (0.0 mi)
|
||||
Total time: 01:04
|
||||
Moving time: 00:00
|
||||
Average speed: 0.49 km/h (0.3 mi/h)
|
||||
Average moving speed: 0.00 km/h (0.0 mi/h)
|
||||
Max speed: 0.00 km/h (0.0 mi/h)
|
||||
Average pace: 122:30 min/km (197:08 min/mi)
|
||||
Average moving pace: 0:00 min/km (0:00 min/mi)
|
||||
Fastest pace: 0:00 min/km (0:00 min/mi)
|
||||
Max elevation: 469 m (1540 ft)
|
||||
Min elevation: 419 m (1376 ft)
|
||||
Elevation gain: 0 m (0 ft)
|
||||
Recorded: 11/28 18:06
|
||||
]]></description>
|
||||
<TimeStamp><when>2020-11-28T17:07:20.870Z</when></TimeStamp>
|
||||
<styleUrl>#end</styleUrl>
|
||||
<Point>
|
||||
<coordinates>1.234046,12.340082,417.99432373046875</coordinates>
|
||||
</Point>
|
||||
</Placemark>
|
||||
</Document>
|
||||
</kml>
|
||||
@@ -50,10 +50,11 @@ limitations under the License.
|
||||
<application
|
||||
android:name=".Startup"
|
||||
android:allowBackup="false"
|
||||
android:hasFragileUserData="true"
|
||||
android:hardwareAccelerated="true"
|
||||
android:hasFragileUserData="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/ThemeCustom">
|
||||
|
||||
<activity android:name=".AboutActivity" />
|
||||
@@ -71,14 +72,14 @@ limitations under the License.
|
||||
<activity android:name=".io.file.importer.ImportActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<data android:mimeType="application/gpx+xml"/>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="application/gpx+xml" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<data android:mimeType="application/gpx"/>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="application/gpx" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter
|
||||
@@ -86,13 +87,15 @@ limitations under the License.
|
||||
android:priority="50">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="file"/>
|
||||
<data android:scheme="content"/>
|
||||
<data android:scheme="data"/>
|
||||
<data android:host="*"/>
|
||||
<data android:mimeType="*/*"/>
|
||||
|
||||
<data android:scheme="file" />
|
||||
<data android:scheme="content" />
|
||||
<data android:scheme="data" />
|
||||
<data android:host="*" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:pathPattern=".*\\.gpx" />
|
||||
<data android:pathPattern=".*\\..*\\.gpx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.gpx" />
|
||||
@@ -110,12 +113,14 @@ limitations under the License.
|
||||
android:priority="50">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="file"/>
|
||||
<data android:scheme="content"/>
|
||||
<data android:scheme="data"/>
|
||||
<data android:host="*"/>
|
||||
|
||||
<data android:scheme="file" />
|
||||
<data android:scheme="content" />
|
||||
<data android:scheme="data" />
|
||||
<data android:host="*" />
|
||||
<data android:pathPattern=".*\\.gpx" />
|
||||
<data android:pathPattern=".*\\..*\\.gpx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.gpx" />
|
||||
@@ -129,9 +134,9 @@ limitations under the License.
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<data android:mimeType="application/vnd.google-earth.kmz"/>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="application/vnd.google-earth.kmz" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter
|
||||
@@ -139,13 +144,15 @@ limitations under the License.
|
||||
android:priority="50">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="file"/>
|
||||
<data android:scheme="content"/>
|
||||
<data android:scheme="data"/>
|
||||
<data android:host="*"/>
|
||||
<data android:mimeType="*/*"/>
|
||||
|
||||
<data android:scheme="file" />
|
||||
<data android:scheme="content" />
|
||||
<data android:scheme="data" />
|
||||
<data android:host="*" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:pathPattern=".*\\.kmz" />
|
||||
<data android:pathPattern=".*\\..*\\.kmz" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.kmz" />
|
||||
@@ -163,12 +170,14 @@ limitations under the License.
|
||||
android:priority="50">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="file"/>
|
||||
<data android:scheme="content"/>
|
||||
<data android:scheme="data"/>
|
||||
<data android:host="*"/>
|
||||
|
||||
<data android:scheme="file" />
|
||||
<data android:scheme="content" />
|
||||
<data android:scheme="data" />
|
||||
<data android:host="*" />
|
||||
<data android:pathPattern=".*\\.kmz" />
|
||||
<data android:pathPattern=".*\\..*\\.kmz" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.kmz" />
|
||||
@@ -182,9 +191,9 @@ limitations under the License.
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<data android:mimeType="application/vnd.google-earth.kml+xml"/>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="application/vnd.google-earth.kml+xml" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter
|
||||
@@ -192,13 +201,15 @@ limitations under the License.
|
||||
android:priority="50">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="file"/>
|
||||
<data android:scheme="content"/>
|
||||
<data android:scheme="data"/>
|
||||
<data android:host="*"/>
|
||||
<data android:mimeType="*/*"/>
|
||||
|
||||
<data android:scheme="file" />
|
||||
<data android:scheme="content" />
|
||||
<data android:scheme="data" />
|
||||
<data android:host="*" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:pathPattern=".*\\.kml" />
|
||||
<data android:pathPattern=".*\\..*\\.kml" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.kml" />
|
||||
@@ -216,12 +227,14 @@ limitations under the License.
|
||||
android:priority="50">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="file"/>
|
||||
<data android:scheme="content"/>
|
||||
<data android:scheme="data"/>
|
||||
<data android:host="*"/>
|
||||
|
||||
<data android:scheme="file" />
|
||||
<data android:scheme="content" />
|
||||
<data android:scheme="data" />
|
||||
<data android:host="*" />
|
||||
<data android:pathPattern=".*\\.kml" />
|
||||
<data android:pathPattern=".*\\..*\\.kml" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.kml" />
|
||||
@@ -237,7 +250,7 @@ limitations under the License.
|
||||
|
||||
<activity android:name=".MarkerDetailActivity">
|
||||
<intent-filter>
|
||||
<action android:name="de.dennisguse.opentracks.MarkerDetails"/>
|
||||
<action android:name="de.dennisguse.opentracks.MarkerDetails" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
@@ -258,8 +271,8 @@ limitations under the License.
|
||||
|
||||
<activity
|
||||
android:name=".TrackListActivity"
|
||||
android:theme="@style/SplashTheme"
|
||||
android:launchMode="singleTop">
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/SplashTheme">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
||||
@@ -73,7 +73,7 @@ public class MarkerEditActivity extends AbstractActivity {
|
||||
|
||||
private Uri photoUri;
|
||||
private Uri photoUriOriginal;
|
||||
private List<Uri> photoUriDeleteList = new ArrayList<>();
|
||||
private final List<Uri> photoUriDeleteList = new ArrayList<>();
|
||||
private boolean hasCamera;
|
||||
|
||||
private boolean isNewMarker;
|
||||
|
||||
@@ -95,9 +95,7 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit
|
||||
}
|
||||
|
||||
setActivityTypeIcon(iconValue);
|
||||
viewBinding.trackEditActivityTypeIcon.setOnClickListener(v -> {
|
||||
ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), viewBinding.trackEditActivityType.getText().toString());
|
||||
});
|
||||
viewBinding.trackEditActivityTypeIcon.setOnClickListener(v -> ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), viewBinding.trackEditActivityType.getText().toString()));
|
||||
|
||||
viewBinding.trackEditDescription.setText(track.getDescription());
|
||||
|
||||
|
||||
@@ -22,11 +22,14 @@ import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
|
||||
import de.dennisguse.opentracks.content.TrackDataHub;
|
||||
import de.dennisguse.opentracks.content.data.Marker;
|
||||
@@ -75,8 +78,10 @@ public class TrackRecordedActivity extends AbstractListActivity implements Confi
|
||||
|
||||
trackDataHub = new TrackDataHub(this);
|
||||
|
||||
viewBinding.trackDetailActivityViewPager.setAdapter(new CustomFragmentPagerAdapter(getSupportFragmentManager(), FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT));
|
||||
viewBinding.trackDetailActivityTablayout.setupWithViewPager(viewBinding.trackDetailActivityViewPager);
|
||||
CustomFragmentPagerAdapter pagerAdapter = new CustomFragmentPagerAdapter(this);
|
||||
viewBinding.trackDetailActivityViewPager.setAdapter(pagerAdapter);
|
||||
new TabLayoutMediator(viewBinding.trackDetailActivityTablayout, viewBinding.trackDetailActivityViewPager,
|
||||
(tab, position) -> tab.setText(pagerAdapter.getPageTitle(position))).attach();
|
||||
if (savedInstanceState != null) {
|
||||
viewBinding.trackDetailActivityViewPager.setCurrentItem(savedInstanceState.getInt(CURRENT_TAB_TAG_KEY));
|
||||
}
|
||||
@@ -220,20 +225,15 @@ public class TrackRecordedActivity extends AbstractListActivity implements Confi
|
||||
}
|
||||
}
|
||||
|
||||
private class CustomFragmentPagerAdapter extends FragmentPagerAdapter {
|
||||
private class CustomFragmentPagerAdapter extends FragmentStateAdapter {
|
||||
|
||||
public CustomFragmentPagerAdapter(@NonNull FragmentManager fm, int behavior) {
|
||||
super(fm, behavior);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 4;
|
||||
public CustomFragmentPagerAdapter(@NonNull FragmentActivity fa) {
|
||||
super(fa);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
public Fragment createFragment(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return StatisticsRecordedFragment.newInstance(trackId);
|
||||
@@ -249,6 +249,10 @@ public class TrackRecordedActivity extends AbstractListActivity implements Confi
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
public CharSequence getPageTitle(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
|
||||
@@ -13,8 +13,10 @@ import android.view.WindowManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
|
||||
import de.dennisguse.opentracks.content.TrackDataHub;
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
@@ -148,8 +150,10 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(bindChangedCallback);
|
||||
trackDataHub = new TrackDataHub(this);
|
||||
|
||||
viewBinding.trackDetailActivityViewPager.setAdapter(new CustomFragmentPagerAdapter(getSupportFragmentManager(), FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT));
|
||||
viewBinding.trackDetailActivityTablayout.setupWithViewPager(viewBinding.trackDetailActivityViewPager);
|
||||
CustomFragmentPagerAdapter pagerAdapter = new CustomFragmentPagerAdapter(this);
|
||||
viewBinding.trackDetailActivityViewPager.setAdapter(pagerAdapter);
|
||||
new TabLayoutMediator(viewBinding.trackDetailActivityTablayout, viewBinding.trackDetailActivityViewPager,
|
||||
(tab, position) -> tab.setText(pagerAdapter.getPageTitle(position))).attach();
|
||||
if (savedInstanceState != null) {
|
||||
viewBinding.trackDetailActivityViewPager.setCurrentItem(savedInstanceState.getInt(CURRENT_TAB_TAG_KEY));
|
||||
}
|
||||
@@ -358,20 +362,15 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
finish();
|
||||
}
|
||||
|
||||
private class CustomFragmentPagerAdapter extends FragmentPagerAdapter {
|
||||
private class CustomFragmentPagerAdapter extends FragmentStateAdapter {
|
||||
|
||||
public CustomFragmentPagerAdapter(@NonNull FragmentManager fm, int behavior) {
|
||||
super(fm, behavior);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 4;
|
||||
public CustomFragmentPagerAdapter(@NonNull FragmentActivity fa) {
|
||||
super(fa);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
public Fragment createFragment(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return StatisticsRecordingFragment.newInstance();
|
||||
@@ -387,6 +386,10 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
public CharSequence getPageTitle(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package de.dennisguse.opentracks.adapters;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Pair;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -20,10 +19,10 @@ import de.dennisguse.opentracks.viewmodels.IntervalStatistics;
|
||||
|
||||
public class IntervalStatisticsAdapter extends ArrayAdapter<IntervalStatistics.Interval> {
|
||||
|
||||
private StackMode stackMode;
|
||||
private boolean metricUnits;
|
||||
private final StackMode stackMode;
|
||||
private final boolean metricUnits;
|
||||
private float sumDistance_m;
|
||||
private String category;
|
||||
private final String category;
|
||||
|
||||
public IntervalStatisticsAdapter(Context context, List<IntervalStatistics.Interval> intervalList, String category, StackMode stackMode) {
|
||||
super(context, R.layout.interval_stats_list_item, intervalList);
|
||||
@@ -61,15 +60,12 @@ public class IntervalStatisticsAdapter extends ArrayAdapter<IntervalStatistics.I
|
||||
viewHolder.distance.setText(StringUtils.formatDistance(getContext(), sumDistance_m, metricUnits));
|
||||
|
||||
if (PreferencesUtils.isReportSpeed(getContext(), category)) {
|
||||
Pair<String, String> speedParts = StringUtils.getSpeedParts(getContext(), interval.getSpeed_ms(), metricUnits, true);
|
||||
viewHolder.rate.setText(speedParts.first + " " + speedParts.second);
|
||||
viewHolder.rate.setText(StringUtils.formatSpeed(getContext(), interval.getSpeed_ms(), metricUnits, true));
|
||||
} else {
|
||||
Pair<String, String> paceParts = StringUtils.getSpeedParts(getContext(), interval.getSpeed_ms(), metricUnits, false);
|
||||
viewHolder.rate.setText(paceParts.first + " " + paceParts.second);
|
||||
viewHolder.rate.setText(StringUtils.formatSpeed(getContext(), interval.getSpeed_ms(), metricUnits, false));
|
||||
}
|
||||
|
||||
Pair<String, String> gainParts = StringUtils.formatElevation(getContext(), interval.getGain_m(), metricUnits);
|
||||
viewHolder.gain.setText(gainParts.first + " " + gainParts.second);
|
||||
viewHolder.gain.setText(StringUtils.formatDistance(getContext(), interval.getGain_m(), metricUnits));
|
||||
|
||||
return intervalView;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ abstract class ChartValueSeries {
|
||||
* @param fillColor the fill color
|
||||
* @param strokeColor the stroke color
|
||||
*/
|
||||
ChartValueSeries(Context context, int absoluteMin, int absoluteMax, int[] intervalValues, int metricTitleId, int imperialTitleId, int fillColor, int strokeColor) {
|
||||
ChartValueSeries(Context context, int absoluteMin, int absoluteMax, int[] intervalValues, int metricTitleId, int imperialTitleId, int fillColor, int strokeColor, int fontSizeSmall, int fontSizeMedium) {
|
||||
this.absoluteMin = absoluteMin;
|
||||
this.absoluteMax = absoluteMax;
|
||||
this.intervalValues = intervalValues;
|
||||
@@ -85,16 +85,14 @@ abstract class ChartValueSeries {
|
||||
strokePaint.setColor(context.getResources().getColor(strokeColor));
|
||||
strokePaint.setAntiAlias(true);
|
||||
|
||||
float scale = context.getResources().getDisplayMetrics().density;
|
||||
|
||||
// Make copies of the stroke paint with the default thickness
|
||||
titlePaint = new Paint(strokePaint);
|
||||
titlePaint.setTextSize(ChartView.MEDIUM_TEXT_SIZE * scale);
|
||||
titlePaint.setTextSize(fontSizeMedium);
|
||||
titlePaint.setTextAlign(Align.CENTER);
|
||||
titlePaint.setStyle(Style.FILL_AND_STROKE);
|
||||
|
||||
markerPaint = new Paint(strokePaint);
|
||||
markerPaint.setTextSize(ChartView.SMALL_TEXT_SIZE * scale);
|
||||
markerPaint.setTextSize(fontSizeSmall);
|
||||
markerPaint.setTextAlign(Align.RIGHT);
|
||||
markerPaint.setStyle(Style.FILL_AND_STROKE);
|
||||
|
||||
|
||||
@@ -30,9 +30,11 @@ import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ScaleGestureDetector;
|
||||
import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.Scroller;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.GestureDetectorCompat;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
@@ -58,9 +60,6 @@ import de.dennisguse.opentracks.util.UnitConversions;
|
||||
*/
|
||||
public class ChartView extends View {
|
||||
|
||||
static final float MEDIUM_TEXT_SIZE = 18f;
|
||||
static final float SMALL_TEXT_SIZE = 12f;
|
||||
|
||||
static final int Y_AXIS_INTERVALS = 5;
|
||||
|
||||
private static final int TARGET_X_AXIS_INTERVALS = 4;
|
||||
@@ -114,7 +113,7 @@ public class ChartView extends View {
|
||||
private int effectiveWidth = 0;
|
||||
private int effectiveHeight = 0;
|
||||
|
||||
private boolean chartByDistance;
|
||||
private final boolean chartByDistance;
|
||||
private boolean metricUnits = true;
|
||||
private boolean reportSpeed = true;
|
||||
private boolean showPointer = false;
|
||||
@@ -192,6 +191,9 @@ public class ChartView extends View {
|
||||
public ChartView(Context context, final boolean chartByDistance) {
|
||||
super(context);
|
||||
this.chartByDistance = chartByDistance;
|
||||
int fontSizeSmall = ThemeUtils.getFontSizeSmallInPx(context);
|
||||
int fontSizeMedium = ThemeUtils.getFontSizeMediumInPx(context);
|
||||
|
||||
seriesList.add(new ChartValueSeries(context,
|
||||
Integer.MIN_VALUE,
|
||||
Integer.MAX_VALUE,
|
||||
@@ -199,7 +201,9 @@ public class ChartView extends View {
|
||||
R.string.description_elevation_metric,
|
||||
R.string.description_elevation_imperial,
|
||||
R.color.chart_elevation_fill,
|
||||
R.color.chart_elevation_border) {
|
||||
R.color.chart_elevation_border,
|
||||
fontSizeSmall,
|
||||
fontSizeMedium) {
|
||||
@Override
|
||||
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
return chartPoint.getElevation();
|
||||
@@ -218,7 +222,9 @@ public class ChartView extends View {
|
||||
R.string.description_speed_metric,
|
||||
R.string.description_speed_imperial,
|
||||
R.color.chart_speed_fill,
|
||||
R.color.chart_speed_border) {
|
||||
R.color.chart_speed_border,
|
||||
fontSizeSmall,
|
||||
fontSizeMedium) {
|
||||
@Override
|
||||
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
return chartPoint.getSpeed();
|
||||
@@ -238,7 +244,9 @@ public class ChartView extends View {
|
||||
R.string.description_pace_metric,
|
||||
R.string.description_pace_imperial,
|
||||
R.color.chart_pace_fill,
|
||||
R.color.chart_pace_border) {
|
||||
R.color.chart_pace_border,
|
||||
fontSizeSmall,
|
||||
fontSizeMedium) {
|
||||
@Override
|
||||
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
return chartPoint.getPace();
|
||||
@@ -258,7 +266,9 @@ public class ChartView extends View {
|
||||
R.string.description_sensor_heart_rate,
|
||||
R.string.description_sensor_heart_rate,
|
||||
R.color.chart_heart_rate_fill,
|
||||
R.color.chart_heart_rate_border) {
|
||||
R.color.chart_heart_rate_border,
|
||||
fontSizeSmall,
|
||||
fontSizeMedium) {
|
||||
@Override
|
||||
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
return chartPoint.getHeartRate();
|
||||
@@ -277,7 +287,9 @@ public class ChartView extends View {
|
||||
R.string.description_sensor_cadence,
|
||||
R.string.description_sensor_cadence,
|
||||
R.color.chart_cadence_fill,
|
||||
R.color.chart_cadence_border) {
|
||||
R.color.chart_cadence_border,
|
||||
fontSizeSmall,
|
||||
fontSizeMedium) {
|
||||
@Override
|
||||
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
return chartPoint.getCadence();
|
||||
@@ -295,7 +307,9 @@ public class ChartView extends View {
|
||||
R.string.description_sensor_power,
|
||||
R.string.description_sensor_power,
|
||||
R.color.chart_power_fill,
|
||||
R.color.chart_power_border) {
|
||||
R.color.chart_power_border,
|
||||
fontSizeSmall,
|
||||
fontSizeMedium) {
|
||||
@Override
|
||||
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||
return chartPoint.getPower();
|
||||
@@ -309,13 +323,11 @@ public class ChartView extends View {
|
||||
|
||||
backgroundColor = ThemeUtils.getBackgroundColor(context);
|
||||
|
||||
float scale = context.getResources().getDisplayMetrics().density;
|
||||
|
||||
axisPaint = new Paint();
|
||||
axisPaint.setStyle(Style.FILL_AND_STROKE);
|
||||
axisPaint.setColor(ThemeUtils.getTextColorPrimary(context));
|
||||
axisPaint.setAntiAlias(true);
|
||||
axisPaint.setTextSize(SMALL_TEXT_SIZE * scale);
|
||||
axisPaint.setTextSize(fontSizeSmall);
|
||||
|
||||
xAxisMarkerPaint = new Paint(axisPaint);
|
||||
xAxisMarkerPaint.setTextAlign(Align.CENTER);
|
||||
@@ -330,7 +342,7 @@ public class ChartView extends View {
|
||||
markerPaint.setStyle(Style.STROKE);
|
||||
markerPaint.setAntiAlias(false);
|
||||
|
||||
pointer = context.getResources().getDrawable(R.drawable.ic_logo_color_24dp);
|
||||
pointer = ContextCompat.getDrawable(context, R.drawable.ic_logo_color_24dp);
|
||||
pointer.setBounds(0, 0, pointer.getIntrinsicWidth(), pointer.getIntrinsicHeight());
|
||||
|
||||
markerPin = MarkerUtils.getDefaultPhoto(context);
|
||||
@@ -489,6 +501,18 @@ public class ChartView extends View {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle parent's view disallow touch event.
|
||||
*
|
||||
* @param disallow Does disallow parent touch event?
|
||||
*/
|
||||
private void requestDisallowInterceptTouchEventInParent(boolean disallow) {
|
||||
ViewParent parent = getParent();
|
||||
if (parent != null) {
|
||||
parent.requestDisallowInterceptTouchEvent(disallow);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls the view horizontally by a given amount.
|
||||
*
|
||||
@@ -496,13 +520,15 @@ public class ChartView extends View {
|
||||
*/
|
||||
private void scrollBy(int deltaX) {
|
||||
int scrollX = getScrollX() + deltaX;
|
||||
if (scrollX < 0) {
|
||||
if (scrollX <= 0) {
|
||||
scrollX = 0;
|
||||
}
|
||||
|
||||
int maxWidth = effectiveWidth * (zoomLevel - 1);
|
||||
if (scrollX > maxWidth) {
|
||||
if (scrollX >= maxWidth) {
|
||||
scrollX = maxWidth;
|
||||
}
|
||||
|
||||
scrollTo(scrollX, 0);
|
||||
}
|
||||
|
||||
@@ -527,6 +553,10 @@ public class ChartView extends View {
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
boolean isZoom = detectorZoom.onTouchEvent(event);
|
||||
boolean isScrollTab = detectorScrollFlingTab.onTouchEvent(event);
|
||||
|
||||
// ChartView handles zoom gestures (more than one pointer) and all gestures when zoomed itself
|
||||
requestDisallowInterceptTouchEventInParent(event.getPointerCount() != 1 || zoomLevel != MIN_ZOOM_LEVEL);
|
||||
|
||||
return isZoom || isScrollTab;
|
||||
}
|
||||
|
||||
@@ -881,6 +911,7 @@ public class ChartView extends View {
|
||||
|
||||
/**
|
||||
* Finds the index of the first data point containing data for a series.
|
||||
*
|
||||
* @return -1 if no data point contains data for the series.
|
||||
*/
|
||||
private int getFirstPopulatedChartDataIndex(ChartValueSeries chartValueSeries) {
|
||||
|
||||
@@ -488,7 +488,7 @@ public class ContentProviderUtils {
|
||||
private void deleteMarkerPhoto(Context context, Marker marker) {
|
||||
if (marker != null && marker.hasPhoto()) {
|
||||
Uri uri = marker.getPhotoURI();
|
||||
File file = FileUtils.getPhotoFileIfExists(context, marker.getTrackId(), uri);
|
||||
File file = FileUtils.buildInternalPhotoFile(context, marker.getTrackId(), uri);
|
||||
if (file.exists()) {
|
||||
File parent = file.getParentFile();
|
||||
file.delete();
|
||||
@@ -616,7 +616,7 @@ public class ContentProviderUtils {
|
||||
* @param trackId the trackPoints id
|
||||
* @return the number of trackPoints inserted
|
||||
*/
|
||||
//TODO Only used for testing and file import; might be better to replace it.
|
||||
//TODO Only used for testing; might be better to replace it.
|
||||
public int bulkInsertTrackPoint(TrackPoint[] trackPoints, Track.Id trackId) {
|
||||
ContentValues[] values = new ContentValues[trackPoints.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
@@ -625,6 +625,15 @@ public class ContentProviderUtils {
|
||||
return contentResolver.bulkInsert(TrackPointsColumns.CONTENT_URI_BY_ID, values);
|
||||
}
|
||||
|
||||
//TODO Only used for file import; might be better to replace it.
|
||||
public int bulkInsertTrackPoint(List<TrackPoint> trackPoints, Track.Id trackId) {
|
||||
ContentValues[] values = new ContentValues[trackPoints.size()];
|
||||
for (int i = 0; i < trackPoints.size(); i++) {
|
||||
values[i] = createContentValues(trackPoints.get(i), trackId);
|
||||
}
|
||||
return contentResolver.bulkInsert(TrackPointsColumns.CONTENT_URI_BY_ID, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the first location id for a track.
|
||||
* Returns null if it doesn't exist.
|
||||
|
||||
@@ -76,7 +76,8 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
||||
|
||||
private ChartBinding viewBinding;
|
||||
|
||||
//TODO Why is this needed?
|
||||
//TODO REMOVE: Used to restore the TrackStatistics via TrackStatisticsUpdater; for the diagrams we should consider not this setting and just use all data that is in the database
|
||||
@Deprecated
|
||||
private int recordingDistanceInterval;
|
||||
private String category = "";
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public class IntervalsFragment extends Fragment implements TrackDataListener {
|
||||
protected IntervalStatisticsAdapter.StackMode stackModeListView;
|
||||
private IntervalStatisticsModel.IntervalOption selectedInterval;
|
||||
|
||||
private String intervalUnit;
|
||||
private boolean metricUnits;
|
||||
private IntervalStatisticsAdapter adapter;
|
||||
private ArrayAdapter<IntervalStatisticsModel.IntervalOption> spinnerAdapter;
|
||||
|
||||
@@ -51,7 +51,7 @@ public class IntervalsFragment extends Fragment implements TrackDataListener {
|
||||
|
||||
protected final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (preferences, key) -> {
|
||||
if (PreferencesUtils.isKey(getContext(), R.string.stats_units_key, key) || PreferencesUtils.isKey(getContext(), R.string.stats_rate_key, key)) {
|
||||
intervalUnit = PreferencesUtils.isMetricUnits(getContext()) ? getContext().getString(R.string.unit_kilometer) : getContext().getString(R.string.unit_mile);
|
||||
metricUnits = PreferencesUtils.isMetricUnits(getContext());
|
||||
if (adapter != null) {
|
||||
adapter.notifyDataSetChanged();
|
||||
spinnerAdapter.notifyDataSetChanged();
|
||||
@@ -74,7 +74,7 @@ public class IntervalsFragment extends Fragment implements TrackDataListener {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
PreferencesUtils.register(getContext(), sharedPreferenceChangeListener);
|
||||
intervalUnit = PreferencesUtils.isMetricUnits(getContext()) ? getContext().getString(R.string.unit_kilometer) : getContext().getString(R.string.unit_mile);
|
||||
metricUnits = PreferencesUtils.isMetricUnits(getContext());
|
||||
|
||||
viewBinding.intervalList.setEmptyView(viewBinding.intervalListEmptyView);
|
||||
|
||||
@@ -87,15 +87,17 @@ public class IntervalsFragment extends Fragment implements TrackDataListener {
|
||||
@Override
|
||||
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
|
||||
TextView v = (TextView) super.getView(position, convertView, parent);
|
||||
v.setText(v.getText() + " " + intervalUnit);
|
||||
if (metricUnits) {
|
||||
v.setText(getContext().getString(R.string.value_integer_kilometer, Integer.parseInt(v.getText().toString())));
|
||||
} else {
|
||||
v.setText(getContext().getString(R.string.value_integer_mile, Integer.parseInt(v.getText().toString())));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
|
||||
TextView v = (TextView) super.getDropDownView(position, convertView, parent);
|
||||
v.setText(v.getText() + " " + intervalUnit);
|
||||
return v;
|
||||
return getView(position, convertView, parent);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -149,7 +151,6 @@ public class IntervalsFragment extends Fragment implements TrackDataListener {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean metricUnits = PreferencesUtils.isMetricUnits(getContext());
|
||||
IntervalStatistics intervalStatistics = viewModel.getIntervalStats(metricUnits, selectedInterval);
|
||||
adapter = new IntervalStatisticsAdapter(getContext(), intervalStatistics.getIntervalList(), category, stackModeListView);
|
||||
viewBinding.intervalList.setAdapter(adapter);
|
||||
|
||||
@@ -109,9 +109,7 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
|
||||
handlerUpdateUI = new Handler();
|
||||
|
||||
|
||||
viewBinding.statsActivityTypeIcon.setOnClickListener(v -> {
|
||||
((TrackRecordingActivity) getActivity()).chooseActivityType(category);
|
||||
});
|
||||
viewBinding.statsActivityTypeIcon.setOnClickListener(v -> ((TrackRecordingActivity) getActivity()).chooseActivityType(category));
|
||||
|
||||
sensorsAdapter = new SensorsAdapter(getContext());
|
||||
sensorsRecyclerView = viewBinding.statsSensorsRecyclerView;
|
||||
|
||||
@@ -360,7 +360,7 @@ public class ExportActivity extends FragmentActivity implements ExportServiceRes
|
||||
public boolean resolve() {
|
||||
if (autoConflict == CONFLICT_NONE) {
|
||||
Track track = contentProviderUtils.getTrack(trackId);
|
||||
viewBinding.exportProgressAlertIcon.setImageDrawable(getDrawable(R.drawable.ic_report_problem_24));
|
||||
viewBinding.exportProgressAlertIcon.setImageDrawable(ContextCompat.getDrawable(ExportActivity.this, R.drawable.ic_report_problem_24));
|
||||
viewBinding.exportProgressAlertMsg.setText(getString(R.string.export_track_already_exists_msg, track.getName()));
|
||||
setConflictVisibility(View.VISIBLE);
|
||||
return false;
|
||||
|
||||
@@ -167,7 +167,7 @@ public class KmlTrackWriter implements TrackWriter {
|
||||
@Override
|
||||
public void writeMarker(Marker marker) {
|
||||
if (printWriter != null && exportTrackDetail) {
|
||||
boolean existsPhoto = FileUtils.getPhotoFileIfExists(context, marker.getTrackId(), marker.getPhotoURI()) != null;
|
||||
boolean existsPhoto = FileUtils.buildInternalPhotoFile(context, marker.getTrackId(), marker.getPhotoURI()) != null;
|
||||
if (marker.hasPhoto() && exportPhotos && existsPhoto) {
|
||||
float heading = getHeading(marker.getTrackId(), marker.getLocation());
|
||||
writePhotoOverlay(marker, heading);
|
||||
|
||||
@@ -53,7 +53,7 @@ public class KmzTrackExporter implements TrackExporter {
|
||||
private final FileTrackExporter fileTrackExporter;
|
||||
|
||||
private final boolean exportPhotos;
|
||||
private Context context;
|
||||
private final Context context;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -108,7 +108,7 @@ public class KmzTrackExporter implements TrackExporter {
|
||||
Marker marker = contentProviderUtils.createMarker(cursor);
|
||||
if (marker.hasPhoto()) {
|
||||
Uri uriPhoto = marker.getPhotoURI();
|
||||
boolean existsPhoto = FileUtils.getPhotoFileIfExists(context, track.getId(), uriPhoto) != null;
|
||||
boolean existsPhoto = FileUtils.buildInternalPhotoFile(context, track.getId(), uriPhoto) != null;
|
||||
if (existsPhoto) {
|
||||
addImage(context, zipOutputStream, uriPhoto, marker);
|
||||
}
|
||||
|
||||
+23
-28
@@ -29,7 +29,6 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
@@ -61,9 +60,6 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
||||
|
||||
private static final String TAG = AbstractFileTrackImporter.class.getSimpleName();
|
||||
|
||||
// The maximum number of buffered locations for bulk-insertion
|
||||
private static final int MAX_BUFFERED_LOCATIONS = 512;
|
||||
|
||||
private final Context context;
|
||||
private final ContentProviderUtils contentProviderUtils;
|
||||
private final int recordingDistanceInterval;
|
||||
@@ -127,18 +123,15 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
||||
|
||||
saxParser.parse(inputStream, this);
|
||||
Log.d(TAG, "Total import time: " + (System.currentTimeMillis() - start) + "ms");
|
||||
if (trackIds.size() != 1) {
|
||||
// TODO Multi track is not supported yet.
|
||||
throw new ImportParserException("Multi track not supported");
|
||||
}
|
||||
return trackIds.get(0);
|
||||
} catch (IOException | SAXException | ParserConfigurationException e) {
|
||||
Log.e(TAG, "Unable to import file", e);
|
||||
cleanImport();
|
||||
if (trackIds.size() > 0) {
|
||||
cleanImport();
|
||||
}
|
||||
throw new ImportParserException(e);
|
||||
} catch (SQLiteConstraintException e) {
|
||||
Log.e(TAG, "Unable to import file", e);
|
||||
cleanImport();
|
||||
throw new ImportAlreadyExistsException(e);
|
||||
}
|
||||
}
|
||||
@@ -228,17 +221,12 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
||||
*/
|
||||
protected void onTrackStart() throws SAXException {
|
||||
trackData = new TrackData();
|
||||
Uri uri = contentProviderUtils.insertTrack(trackData.track);
|
||||
Track.Id trackId = new Track.Id(Long.parseLong(uri.getLastPathSegment()));
|
||||
trackIds.add(trackId);
|
||||
trackData.track.setId(trackId);
|
||||
}
|
||||
|
||||
/**
|
||||
* On track end.
|
||||
*/
|
||||
protected void onTrackEnd() {
|
||||
flushLocations(trackData);
|
||||
if (name != null) {
|
||||
trackData.track.setName(name);
|
||||
}
|
||||
@@ -268,17 +256,27 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
||||
}
|
||||
trackData.track.setTrackStatistics(trackData.trackStatisticsUpdater.getTrackStatistics());
|
||||
|
||||
try {
|
||||
contentProviderUtils.updateTrack(trackData.track);
|
||||
} catch (SQLiteConstraintException e) {
|
||||
Track track = contentProviderUtils.getTrack(trackData.track.getUuid());
|
||||
if (track != null) {
|
||||
if (PreferencesUtils.getPreventReimportTracks(context)) {
|
||||
throw e;
|
||||
throw new ImportAlreadyExistsException(context.getString(R.string.import_prevent_reimport));
|
||||
}
|
||||
|
||||
//TODO This is a workaround until we have proper UI.
|
||||
trackData.track.setUuid(UUID.randomUUID());
|
||||
contentProviderUtils.updateTrack(trackData.track);
|
||||
}
|
||||
|
||||
if (trackIds.size() > 0) {
|
||||
// TODO Multi track is not supported yet.
|
||||
cleanImport();
|
||||
throw new ImportParserException("Multi track not supported");
|
||||
}
|
||||
Uri uri = contentProviderUtils.insertTrack(trackData.track);
|
||||
Track.Id trackId = new Track.Id(Long.parseLong(uri.getLastPathSegment()));
|
||||
trackIds.add(trackId);
|
||||
trackData.track.setId(trackId);
|
||||
|
||||
flushLocations(trackData);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -303,7 +301,8 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
||||
TrackPoint trackPoint = createTrackPoint();
|
||||
|
||||
if (!LocationUtils.isValidLocation(trackPoint.getLocation())) {
|
||||
throw new SAXException(createErrorMessage("Invalid location detected: " + trackPoint));
|
||||
Log.w(TAG, "Marker with invalid coordinates ignored: " + trackPoint.getLocation());
|
||||
return;
|
||||
}
|
||||
Marker marker = new Marker(trackPoint.getLocation());
|
||||
|
||||
@@ -482,13 +481,9 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
||||
}
|
||||
trackData.trackStatisticsUpdater.addTrackPoint(trackPoint, recordingDistanceInterval);
|
||||
|
||||
trackData.bufferedTrackPoints[trackData.numBufferedTrackPoints] = trackPoint;
|
||||
trackData.bufferedTrackPoints.add(trackPoint);
|
||||
trackData.numBufferedTrackPoints++;
|
||||
trackData.numberOfLocations++;
|
||||
|
||||
if (trackData.numBufferedTrackPoints >= MAX_BUFFERED_LOCATIONS) {
|
||||
flushLocations(trackData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -500,7 +495,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
||||
if (data.numBufferedTrackPoints <= 0) {
|
||||
return;
|
||||
}
|
||||
contentProviderUtils.bulkInsertTrackPoint(Arrays.copyOfRange(data.bufferedTrackPoints, 0, data.numBufferedTrackPoints), data.track.getId());
|
||||
contentProviderUtils.bulkInsertTrackPoint(data.bufferedTrackPoints, data.track.getId());
|
||||
data.numBufferedTrackPoints = 0;
|
||||
}
|
||||
|
||||
@@ -537,7 +532,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
||||
final long importTime = System.currentTimeMillis();
|
||||
|
||||
// The buffered locations
|
||||
final TrackPoint[] bufferedTrackPoints = new TrackPoint[MAX_BUFFERED_LOCATIONS];
|
||||
final List<TrackPoint> bufferedTrackPoints = new ArrayList<>();
|
||||
|
||||
// The number of buffered locations
|
||||
int numBufferedTrackPoints = 0;
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
@@ -161,12 +162,12 @@ public class ImportActivity extends FragmentActivity {
|
||||
viewBinding.importProgressLeftButton.setVisibility(View.VISIBLE);
|
||||
viewBinding.importProgressLeftButton.setText(getString(R.string.generic_show_errors));
|
||||
viewBinding.importProgressLeftButton.setOnClickListener((view) -> ErrorListDialog.showDialog(getSupportFragmentManager(), getString(R.string.import_error_list_dialog_title), summary.getFileErrors()));
|
||||
viewBinding.importProgressAlertIcon.setImageDrawable(getDrawable(R.drawable.ic_report_problem_24));
|
||||
viewBinding.importProgressAlertIcon.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_report_problem_24));
|
||||
String msg = getResources().getQuantityString(R.plurals.generic_completed_with_errors, summary.getErrorCount(), summary.getErrorCount());
|
||||
viewBinding.importProgressAlertMsg.setText(msg);
|
||||
} else {
|
||||
viewBinding.importProgressLeftButton.setVisibility(View.GONE);
|
||||
viewBinding.importProgressAlertIcon.setImageDrawable(getDrawable(R.drawable.ic_dialog_success_24dp));
|
||||
viewBinding.importProgressAlertIcon.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_dialog_success_24dp));
|
||||
viewBinding.importProgressAlertMsg.setText(getString(R.string.generic_completed));
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -4,4 +4,8 @@ class ImportAlreadyExistsException extends RuntimeException {
|
||||
public ImportAlreadyExistsException(Exception e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
public ImportAlreadyExistsException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,12 +63,12 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
|
||||
|
||||
private boolean trackStarted = false;
|
||||
private String extendedDataType;
|
||||
private ArrayList<TrackPoint> trackPoints = new ArrayList<>();
|
||||
private ArrayList<Float> speedList = new ArrayList<>();
|
||||
private ArrayList<Float> cadenceList = new ArrayList<>();
|
||||
private ArrayList<Float> heartRateList = new ArrayList<>();
|
||||
private ArrayList<Float> powerList = new ArrayList<>();
|
||||
private ArrayList<Float> elevationGainList = new ArrayList<>();
|
||||
private final ArrayList<TrackPoint> trackPoints = new ArrayList<>();
|
||||
private final ArrayList<Float> speedList = new ArrayList<>();
|
||||
private final ArrayList<Float> cadenceList = new ArrayList<>();
|
||||
private final ArrayList<Float> heartRateList = new ArrayList<>();
|
||||
private final ArrayList<Float> powerList = new ArrayList<>();
|
||||
private final ArrayList<Float> elevationGainList = new ArrayList<>();
|
||||
|
||||
public KmlFileTrackImporter(Context context) {
|
||||
this(context, new ContentProviderUtils(context));
|
||||
|
||||
@@ -177,6 +177,10 @@ public class KmzTrackImporter implements TrackImporter {
|
||||
|
||||
zipInputStream.closeEntry();
|
||||
}
|
||||
if (trackId == null) {
|
||||
Log.d(TAG, "Unable to find doc.kml in kmz");
|
||||
throw new RuntimeException(context.getString(R.string.import_no_kml_file_found));
|
||||
}
|
||||
return trackId;
|
||||
} catch (ImportParserException | ImportAlreadyExistsException e) {
|
||||
Log.e(TAG, "Unable to import file", e);
|
||||
@@ -271,6 +275,7 @@ public class KmzTrackImporter implements TrackImporter {
|
||||
* Reads an image file (zipInputStream) and save it in a file called fileName inside photo folder.
|
||||
*
|
||||
* @param zipInputStream the zip input stream
|
||||
* @param trackId the track's id which image belongs to.
|
||||
* @param fileName the file name
|
||||
*/
|
||||
private void readAndSaveImageFile(ZipInputStream zipInputStream, Track.Id trackId, String fileName) throws IOException {
|
||||
|
||||
@@ -25,7 +25,7 @@ class GpsStatus {
|
||||
|
||||
private GpsStatusValue gpsStatus = GpsStatusValue.GPS_NONE;
|
||||
private GpsStatusListener client;
|
||||
private Context context;
|
||||
private final Context context;
|
||||
|
||||
// Last location. It can be null.
|
||||
private Location lastLocation = null;
|
||||
@@ -51,7 +51,7 @@ class GpsStatus {
|
||||
}
|
||||
}
|
||||
|
||||
private Handler gpsStatusHandler;
|
||||
private final Handler gpsStatusHandler;
|
||||
private GpsStatusRunner gpsStatusRunner = null;
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
|
||||
public class HandlerServer {
|
||||
|
||||
private static String TAG = HandlerServer.class.getSimpleName();
|
||||
private static final String TAG = HandlerServer.class.getSimpleName();
|
||||
|
||||
private final LocationHandler locationHandler;
|
||||
private final HandlerServerInterface service;
|
||||
|
||||
@@ -95,9 +95,7 @@ public class ActivityTypePreference extends DialogPreference {
|
||||
});
|
||||
|
||||
iconView = view.findViewById(R.id.activity_type_preference_spinner);
|
||||
iconView.setOnClickListener((it) -> {
|
||||
showIconSelectDialog();
|
||||
});
|
||||
iconView.setOnClickListener((it) -> showIconSelectDialog());
|
||||
|
||||
updateIcon(TrackIconUtils.getIconValue(context, category));
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ public class SettingsActivity extends AppCompatActivity implements ChooseActivit
|
||||
activityPreferenceDialog = ActivityTypePreference.ActivityPreferenceDialog.newInstance(preference.getKey());
|
||||
dialogFragment = activityPreferenceDialog;
|
||||
} else if (preference instanceof BluetoothLeHeartRatePreference) {
|
||||
dialogFragment = BluetoothLeSensorPreference.BluetoothLeSensorPreferenceDialog.newInstance(preference.getKey(), BluetoothUtils.HEART_RATE_SERVICE_UUID);
|
||||
dialogFragment = BluetoothLeSensorPreference.BluetoothLeSensorPreferenceDialog.newInstance(preference.getKey(), BluetoothUtils.HEART_RATE_SUPPORTING_DEVICES);
|
||||
} else if (preference instanceof BluetoothLeCyclingCadenceAndSpeedPreference) {
|
||||
dialogFragment = BluetoothLeSensorPreference.BluetoothLeSensorPreferenceDialog.newInstance(preference.getKey(), BluetoothUtils.CYCLING_SPEED_CADENCE_SERVICE_UUID);
|
||||
} else if (preference instanceof BluetoothLeCyclingPowerPreference) {
|
||||
|
||||
+30
-16
@@ -8,8 +8,6 @@ import android.bluetooth.le.ScanResult;
|
||||
import android.bluetooth.le.ScanSettings;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelUuid;
|
||||
import android.text.TextUtils;
|
||||
@@ -18,13 +16,15 @@ import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.preference.DialogPreference;
|
||||
import androidx.preference.PreferenceDialogFragmentCompat;
|
||||
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.settings.BluetoothLeAdapter;
|
||||
@@ -39,7 +39,7 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference {
|
||||
|
||||
private static final String TAG = BluetoothLeSensorPreference.class.getSimpleName();
|
||||
|
||||
private static final String ARG_BLUETOOTH_UUID = "bluetoothUUID";
|
||||
private static final String ARG_BLE_SERVICE_UUIDS = "bluetoothUUID";
|
||||
|
||||
private static final int DEVICE_NONE_RESOURCEID = R.string.value_none;
|
||||
|
||||
@@ -94,6 +94,8 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference {
|
||||
|
||||
public static class BluetoothLeSensorPreferenceDialog extends PreferenceDialogFragmentCompat {
|
||||
|
||||
private AnimatedVectorDrawableCompat bluetoothIcon;
|
||||
|
||||
private int selectedEntryIndex;
|
||||
private final BluetoothLeAdapter listAdapter = new BluetoothLeAdapter();
|
||||
|
||||
@@ -109,8 +111,9 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference {
|
||||
|
||||
@Override
|
||||
public void onBatchScanResults(List<ScanResult> results) {
|
||||
for (ScanResult scanResult : results) {
|
||||
listAdapter.add(scanResult.getDevice());
|
||||
for (ScanResult result : results) {
|
||||
Log.d(TAG, "Found device " + result.getDevice().getName() + " " + result);
|
||||
listAdapter.add(result.getDevice());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,10 +127,14 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference {
|
||||
};
|
||||
|
||||
public static BluetoothLeSensorPreferenceDialog newInstance(String preferenceKey, UUID sensorUUID) {
|
||||
return newInstance(preferenceKey, Collections.singletonList(sensorUUID));
|
||||
}
|
||||
|
||||
public static BluetoothLeSensorPreferenceDialog newInstance(String preferenceKey, List<UUID> sensorUUIDs) {
|
||||
final BluetoothLeSensorPreferenceDialog fragment = new BluetoothLeSensorPreferenceDialog();
|
||||
final Bundle b = new Bundle(1);
|
||||
b.putString(ARG_KEY, preferenceKey);
|
||||
b.putSerializable(ARG_BLUETOOTH_UUID, sensorUUID);
|
||||
b.putParcelableArrayList(ARG_BLE_SERVICE_UUIDS, new ArrayList<>(sensorUUIDs.stream().map(ParcelUuid::new).collect(Collectors.toList())));
|
||||
fragment.setArguments(b);
|
||||
return fragment;
|
||||
}
|
||||
@@ -136,8 +143,12 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
UUID sensorUUID = (UUID) getArguments().getSerializable(ARG_BLUETOOTH_UUID);
|
||||
Log.i(TAG, "UUID: " + sensorUUID);
|
||||
List<ParcelUuid> serviceUUIDs = getArguments().getParcelableArrayList(ARG_BLE_SERVICE_UUIDS);
|
||||
|
||||
// Don't know why: need to load the drawable _twice_, so that animation is actually started.
|
||||
bluetoothIcon = AnimatedVectorDrawableCompat.create(getContext(), R.drawable.ic_bluetooth_searching_animated_24dp);
|
||||
bluetoothIcon = AnimatedVectorDrawableCompat.create(getContext(), R.drawable.ic_bluetooth_searching_animated_24dp);
|
||||
bluetoothIcon.start();
|
||||
|
||||
BluetoothAdapter bluetoothAdapter = BluetoothUtils.getAdapter(getContext());
|
||||
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
|
||||
@@ -148,7 +159,7 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference {
|
||||
}
|
||||
|
||||
if (bluetoothAdapter.isDiscovering()) {
|
||||
Log.i(TAG, "Cancelling ongoing B<aluetooth discovery.");
|
||||
Log.i(TAG, "Cancelling ongoing Bluetooth discovery.");
|
||||
bluetoothAdapter.cancelDiscovery();
|
||||
}
|
||||
|
||||
@@ -170,9 +181,7 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference {
|
||||
selectedEntryIndex = 1;
|
||||
}
|
||||
|
||||
ScanFilter.Builder scanFilterBuilder = new ScanFilter.Builder().setServiceUuid(new ParcelUuid(sensorUUID));
|
||||
List<ScanFilter> scanFilter = new ArrayList<>();
|
||||
scanFilter.add(scanFilterBuilder.build());
|
||||
List<ScanFilter> scanFilter = serviceUUIDs.stream().map(it -> new ScanFilter.Builder().setServiceUuid(it).build()).collect(Collectors.toList());
|
||||
|
||||
ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder();
|
||||
scanSettingsBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
|
||||
@@ -193,9 +202,7 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference {
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
Drawable icon = ContextCompat.getDrawable(getContext(), R.drawable.ic_bluetooth_searching_animated_24dp);
|
||||
((Animatable) icon).start();
|
||||
builder.setIcon(icon);
|
||||
builder.setIcon(bluetoothIcon);
|
||||
|
||||
builder.setPositiveButton(null, null);
|
||||
}
|
||||
@@ -214,5 +221,12 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
bluetoothIcon = null;
|
||||
scanner = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@ import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.dennisguse.opentracks.content.sensor.SensorDataCycling;
|
||||
@@ -39,6 +42,12 @@ public class BluetoothUtils {
|
||||
public static final UUID HEART_RATE_SERVICE_UUID = new UUID(0x180D00001000L, 0x800000805f9b34fbL);
|
||||
public static final UUID HEART_RATE_MEASUREMENT_CHAR_UUID = new UUID(0x2A3700001000L, 0x800000805f9b34fbL);
|
||||
|
||||
public static final List<UUID> HEART_RATE_SUPPORTING_DEVICES = Collections.unmodifiableList(Arrays.asList(
|
||||
BluetoothUtils.HEART_RATE_SERVICE_UUID,
|
||||
//Devices that support HEART_RATE_SERVICE_UUID, but do not announce HEART_RATE_SERVICE_UUID in there BLE announcement messages (during device discovery).
|
||||
UUID.fromString("0000fee0-0000-1000-8000-00805f9b34fb") //Miband3
|
||||
));
|
||||
|
||||
public static final UUID CYCLING_POWER_UUID = new UUID(0x181800001000L, 0x800000805f9b34fbL);
|
||||
public static final UUID CYCLING_POWER_MEASUREMENT_CHAR_UUID = new UUID(0x2A6300001000L, 0x800000805f9b34fbL);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
|
||||
@@ -15,6 +16,6 @@ public class MarkerUtils {
|
||||
}
|
||||
|
||||
public static Drawable getDefaultPhoto(@NonNull Context context) {
|
||||
return context.getResources().getDrawable(ICON_ID);
|
||||
return ContextCompat.getDrawable(context, ICON_ID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,18 +5,18 @@ import android.hardware.SensorManager;
|
||||
public class PressureSensorUtils {
|
||||
|
||||
//Everything above is considered a meaningful change in elevation.
|
||||
private static float ELEVATION_CHANGE_DIFF_M = 3.0f;
|
||||
private static final float ELEVATION_CHANGE_DIFF_M = 3.0f;
|
||||
|
||||
private static float EXPONENTIAL_SMOOTHING = 0.3f;
|
||||
private static final float EXPONENTIAL_SMOOTHING = 0.3f;
|
||||
|
||||
private PressureSensorUtils() {
|
||||
}
|
||||
|
||||
public static class ElevationChange {
|
||||
|
||||
private float currentSensorValue_hPa;
|
||||
private final float currentSensorValue_hPa;
|
||||
|
||||
private float elevationChange_m;
|
||||
private final float elevationChange_m;
|
||||
|
||||
public ElevationChange(float currentSensorValue_hPa, float elevationChange_m) {
|
||||
this.currentSensorValue_hPa = currentSensorValue_hPa;
|
||||
|
||||
@@ -118,6 +118,34 @@ public class StringUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static String formatSpeed(Context context, double speed_mps, boolean metricUnits, boolean reportSpeed) {
|
||||
if (Double.isNaN(speed_mps) || Double.isInfinite(speed_mps)) {
|
||||
speed_mps = 0;
|
||||
}
|
||||
|
||||
double speed = speed_mps * UnitConversions.M_TO_KM; //KM p sec
|
||||
if (!metricUnits) {
|
||||
speed *= UnitConversions.KM_TO_MI;
|
||||
}
|
||||
|
||||
if (reportSpeed) {
|
||||
if (metricUnits) {
|
||||
return context.getString(R.string.value_float_kilometer_hour, speed * UnitConversions.S_TO_HR);
|
||||
} else {
|
||||
return context.getString(R.string.value_float_mile_hour, speed * UnitConversions.S_TO_HR);
|
||||
}
|
||||
} else {
|
||||
int pace = speed == 0 ? 0 : (int) Math.round(1 / speed); //sec / [KM | MI]
|
||||
int minutes = pace / 60;
|
||||
int seconds = pace % 60;
|
||||
if (metricUnits) {
|
||||
return context.getString(R.string.value_pace_kilometer, minutes, seconds);
|
||||
} else {
|
||||
return context.getString(R.string.value_pace_mile, minutes, seconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String formatDecimal(double value) {
|
||||
return StringUtils.formatDecimal(value, 2);
|
||||
}
|
||||
|
||||
@@ -2,10 +2,13 @@ package de.dennisguse.opentracks.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.TypedValue;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
|
||||
public class ThemeUtils {
|
||||
|
||||
private ThemeUtils() {
|
||||
@@ -37,4 +40,18 @@ public class ThemeUtils {
|
||||
|
||||
return ContextCompat.getColor(context, typedValue.resourceId);
|
||||
}
|
||||
|
||||
public static int getFontSizeSmallInPx(Context context) {
|
||||
TypedArray typedArray = context.obtainStyledAttributes(R.style.TextSmall, new int[]{android.R.attr.textSize});
|
||||
int fontSize = typedArray.getDimensionPixelSize(0, 12);
|
||||
typedArray.recycle();
|
||||
return fontSize;
|
||||
}
|
||||
|
||||
public static int getFontSizeMediumInPx(Context context) {
|
||||
TypedArray typedArray = context.obtainStyledAttributes(R.style.TextMedium, new int[]{android.R.attr.textSize});
|
||||
int fontSize = typedArray.getDimensionPixelSize(0, 15);
|
||||
typedArray.recycle();
|
||||
return fontSize;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import de.dennisguse.opentracks.util.LocationUtils;
|
||||
import de.dennisguse.opentracks.util.UnitConversions;
|
||||
|
||||
public class IntervalStatistics {
|
||||
private List<Interval> intervalList = new ArrayList<>();
|
||||
private final List<Interval> intervalList = new ArrayList<>();
|
||||
private float distanceInterval_m;
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,10 +19,10 @@ limitations under the License.
|
||||
android:id="@+id/track_controller_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/track_controller_background_normal"
|
||||
android:background="@drawable/track_controller_background"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp">
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/track_controller_record"
|
||||
|
||||
@@ -47,10 +47,10 @@ limitations under the License.
|
||||
android:id="@+id/track_list_arrow_long"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingRight="16dp">
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="16dp">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
@@ -73,7 +73,7 @@ limitations under the License.
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toRightOf="@id/track_list_arrow_long"
|
||||
android:layout_toEndOf="@id/track_list_arrow_long"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/track_detail_activity_view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
|
||||
@@ -20,21 +20,18 @@
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<TextView
|
||||
style="@style/TextLarge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="4"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:text="@string/aggregated_stats_empty_message" />
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
@@ -33,9 +33,9 @@
|
||||
android:id="@+id/aggregated_stats_sport_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintLeft_toLeftOf="@id/guideline1"
|
||||
app:layout_constraintStart_toStartOf="@id/guideline1"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_activity_bike_24dp" />
|
||||
|
||||
@@ -45,10 +45,10 @@
|
||||
android:layout_marginTop="0dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/aggregated_stats_sport_icon"
|
||||
app:layout_constraintLeft_toRightOf="@+id/aggregated_stats_sport_icon"
|
||||
app:layout_constraintStart_toEndOf="@+id/aggregated_stats_sport_icon"
|
||||
app:layout_constraintTop_toTopOf="@+id/aggregated_stats_sport_icon"
|
||||
tools:text="@string/activity_type_cycling"
|
||||
android:layout_marginLeft="16dp" />
|
||||
android:layout_marginStart="16dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/aggregated_stats_num_tracks"
|
||||
@@ -56,36 +56,36 @@
|
||||
android:layout_marginTop="0dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/aggregated_stats_type_label"
|
||||
app:layout_constraintLeft_toRightOf="@+id/aggregated_stats_type_label"
|
||||
app:layout_constraintStart_toEndOf="@+id/aggregated_stats_type_label"
|
||||
app:layout_constraintTop_toTopOf="@+id/aggregated_stats_type_label"
|
||||
tools:text="(1)"
|
||||
android:layout_marginLeft="4dp" />
|
||||
android:layout_marginStart="4dp" />
|
||||
|
||||
<!-- Distance -->
|
||||
<TextView
|
||||
android:id="@+id/aggregated_stats_distance"
|
||||
style="@style/StatsLargeValue"
|
||||
app:layout_constraintLeft_toLeftOf="@id/guideline1"
|
||||
app:layout_constraintStart_toStartOf="@id/guideline1"
|
||||
app:layout_constraintTop_toBottomOf="@+id/aggregated_stats_sport_icon"
|
||||
tools:text="100000"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/aggregated_stats_distance_unit"
|
||||
style="@style/StatsUnit"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/aggregated_stats_distance"
|
||||
app:layout_constraintLeft_toRightOf="@+id/aggregated_stats_distance"
|
||||
app:layout_constraintStart_toEndOf="@+id/aggregated_stats_distance"
|
||||
tools:text="km" />
|
||||
|
||||
<!-- Time -->
|
||||
<TextView
|
||||
android:id="@+id/aggregated_stats_time"
|
||||
style="@style/StatsLargeValue"
|
||||
app:layout_constraintRight_toRightOf="@id/guideline3"
|
||||
app:layout_constraintEnd_toEndOf="@id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@+id/aggregated_stats_sport_icon"
|
||||
tools:text="00:00:00"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginTop="16dp" />
|
||||
|
||||
<!-- Avg. rate -->
|
||||
@@ -94,8 +94,8 @@
|
||||
style="@style/StatsSmallValue"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintTop_toBottomOf="@id/aggregated_stats_distance"
|
||||
app:layout_constraintLeft_toRightOf="@id/guideline1"
|
||||
app:layout_constraintRight_toLeftOf="@+id/aggregated_stats_avg_rate_unit"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline1"
|
||||
app:layout_constraintEnd_toStartOf="@+id/aggregated_stats_avg_rate_unit"
|
||||
android:layout_marginTop="24dp"
|
||||
tools:text="30" />
|
||||
|
||||
@@ -103,8 +103,8 @@
|
||||
android:id="@+id/aggregated_stats_avg_rate_unit"
|
||||
style="@style/StatsUnit"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/aggregated_stats_avg_rate"
|
||||
app:layout_constraintLeft_toRightOf="@+id/aggregated_stats_avg_rate"
|
||||
app:layout_constraintRight_toRightOf="@id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/aggregated_stats_avg_rate"
|
||||
app:layout_constraintEnd_toEndOf="@id/guideline2"
|
||||
tools:text="km/h" />
|
||||
|
||||
<TextView
|
||||
@@ -112,8 +112,8 @@
|
||||
style="@style/StatsTinyLabel"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintTop_toBottomOf="@+id/aggregated_stats_avg_rate"
|
||||
app:layout_constraintLeft_toRightOf="@id/guideline1"
|
||||
app:layout_constraintRight_toRightOf="@id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline1"
|
||||
app:layout_constraintEnd_toEndOf="@id/guideline2"
|
||||
tools:text="@string/stats_average_moving_speed" />
|
||||
|
||||
<!-- Max. rate -->
|
||||
@@ -122,8 +122,8 @@
|
||||
style="@style/StatsSmallValue"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintTop_toBottomOf="@id/aggregated_stats_time"
|
||||
app:layout_constraintLeft_toRightOf="@id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/aggregated_stats_max_rate_unit"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/aggregated_stats_max_rate_unit"
|
||||
android:layout_marginTop="24dp"
|
||||
tools:text="70" />
|
||||
|
||||
@@ -131,8 +131,8 @@
|
||||
android:id="@+id/aggregated_stats_max_rate_unit"
|
||||
style="@style/StatsUnit"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/aggregated_stats_max_rate"
|
||||
app:layout_constraintLeft_toRightOf="@+id/aggregated_stats_max_rate"
|
||||
app:layout_constraintRight_toLeftOf="@id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/aggregated_stats_max_rate"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline3"
|
||||
tools:text="km/h" />
|
||||
|
||||
<TextView
|
||||
@@ -140,8 +140,8 @@
|
||||
style="@style/StatsTinyLabel"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintTop_toBottomOf="@+id/aggregated_stats_max_rate"
|
||||
app:layout_constraintLeft_toRightOf="@id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline3"
|
||||
tools:text="@string/stats_max_speed" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -14,7 +14,7 @@
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_weight="1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="0dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_weight="1"
|
||||
@@ -62,9 +62,9 @@
|
||||
style="@style/ProgressBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginRight="24dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/export_progress_done"
|
||||
@@ -113,8 +113,8 @@
|
||||
android:id="@+id/export_progress_apply_to_all"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:layout_marginRight="24dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:checked="false"
|
||||
android:text="@string/export_all_do_it_for_all"
|
||||
@@ -144,7 +144,7 @@
|
||||
<Button
|
||||
android:id="@+id/export_progress_right_button"
|
||||
style="@style/BottomButton"
|
||||
android:layout_gravity="right"
|
||||
android:layout_gravity="end"
|
||||
android:text="@string/generic_overwrite"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_weight="1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="0dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_weight="1"
|
||||
@@ -60,9 +60,9 @@
|
||||
style="@style/ProgressBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginRight="24dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/import_progress_done"
|
||||
@@ -126,7 +126,7 @@
|
||||
<Button
|
||||
android:id="@+id/import_progress_right_button"
|
||||
style="@style/BottomButton"
|
||||
android:layout_gravity="right"
|
||||
android:layout_gravity="end"
|
||||
android:text="@string/generic_ok"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_margin="8dp">
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
style="@style/TextMediumPrimary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/stats_split_interval"
|
||||
style="@style/TextMedium" />
|
||||
android:text="@string/stats_split_interval" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinner_intervals"
|
||||
@@ -28,56 +29,39 @@
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_margin="8dp">
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/interval_distance"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
style="@style/TextMedium"
|
||||
android:layout_margin="1dp"
|
||||
android:textAlignment="center"
|
||||
android:layout_gravity="center"
|
||||
style="@style/IntervalLabel"
|
||||
android:text="@string/stats_distance" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/interval_rate"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
style="@style/TextMedium"
|
||||
android:layout_margin="1dp"
|
||||
android:textAlignment="center"
|
||||
android:layout_gravity="center"
|
||||
tools:text="Speed"/>
|
||||
style="@style/IntervalLabel"
|
||||
tools:text="Speed" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/interval_elevation"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
style="@style/TextMedium"
|
||||
android:layout_margin="1dp"
|
||||
android:textAlignment="center"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/stats_elevation" />
|
||||
style="@style/IntervalLabel"
|
||||
android:text="@string/stats_gain" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:background="@color/stats_separator"/>
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@color/stats_separator" />
|
||||
|
||||
<ListView
|
||||
android:id="@+id/interval_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"/>
|
||||
android:layout_margin="8dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/interval_list_empty_view"
|
||||
|
||||
@@ -1,47 +1,31 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/interval_item_distance"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_gravity="center_vertical"
|
||||
style="@style/TextMedium"
|
||||
tools:text="1 km" />
|
||||
<TextView
|
||||
android:id="@+id/interval_item_distance"
|
||||
style="@style/TextMedium"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
tools:text="1 km" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/interval_item_rate"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_gravity="center_vertical"
|
||||
style="@style/TextMedium"
|
||||
tools:text="15 km/h" />
|
||||
<TextView
|
||||
android:id="@+id/interval_item_rate"
|
||||
style="@style/TextMedium"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
tools:text="15 km/h" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_arrow_drop_up_24" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/interval_item_gain"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
style="@style/TextMedium"
|
||||
tools:text="100 m" />
|
||||
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/interval_item_gain"
|
||||
style="@style/TextMedium"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
app:drawableStartCompat="@drawable/ic_arrow_drop_up_24"
|
||||
tools:text="100 m" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -44,7 +44,8 @@ limitations under the License.
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:shrinkColumns="1"
|
||||
android:stretchColumns="1">
|
||||
@@ -56,8 +57,8 @@ limitations under the License.
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:contentDescription="@string/image_track"
|
||||
app:tint="?android:textColorPrimary" />
|
||||
<!-- Table 1: Row 1: Column 2: (Table 2) -->
|
||||
@@ -105,8 +106,8 @@ limitations under the License.
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginLeft="2dp"
|
||||
android:layout_marginRight="2dp"
|
||||
android:layout_marginStart="2dp"
|
||||
android:layout_marginEnd="2dp"
|
||||
android:layout_marginBottom="1dp"
|
||||
android:contentDescription="@string/image_marker_count"
|
||||
android:scaleType="centerInside"
|
||||
|
||||
@@ -116,12 +116,12 @@ limitations under the License.
|
||||
<Button
|
||||
android:id="@+id/marker_edit_cancel"
|
||||
style="@style/BottomButton"
|
||||
android:layout_gravity="left"
|
||||
android:layout_gravity="start"
|
||||
android:text="@string/generic_cancel" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/marker_edit_done"
|
||||
style="@style/BottomButton"
|
||||
android:layout_gravity="right" />
|
||||
android:layout_gravity="end" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -19,9 +19,9 @@ limitations under the License.
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingRight="8dp">
|
||||
android:paddingEnd="8dp">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/activity_type_preference_text_view"
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
style="@style/StatsLargeLabel"
|
||||
android:text="@string/stats_distance"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
@@ -45,8 +45,8 @@
|
||||
style="@style/StatsLargeValue"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/stats_distance_unit"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/stats_distance_unit"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_distance_label"
|
||||
tools:text="100" />
|
||||
|
||||
@@ -54,8 +54,8 @@
|
||||
android:id="@+id/stats_distance_unit"
|
||||
style="@style/StatsUnit"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/stats_distance_value"
|
||||
app:layout_constraintLeft_toRightOf="@+id/stats_distance_value"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/stats_distance_value"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
tools:text="km" />
|
||||
|
||||
<!-- Activity Type -->
|
||||
@@ -64,16 +64,16 @@
|
||||
style="@style/StatsLargeLabel"
|
||||
android:text="@string/track_edit_activity_type_hint"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/stats_activity_type_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/stats_distance_value"
|
||||
app:layout_constraintTop_toTopOf="@+id/stats_distance_value"
|
||||
app:tint="?android:attr/textColorPrimary"
|
||||
@@ -85,15 +85,15 @@
|
||||
style="@style/StatsLargeLabel"
|
||||
android:text="@string/stats_total_time"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_distance_value" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_total_time_value"
|
||||
style="@style/StatsLargeValue"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_total_time_label"
|
||||
tools:text="00:00:00" />
|
||||
|
||||
@@ -103,8 +103,8 @@
|
||||
style="@style/StatsLargeLabel"
|
||||
android:text="@string/stats_moving_time"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toTopOf="@+id/stats_total_time_label"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/stats_total_time_label" />
|
||||
|
||||
@@ -112,8 +112,8 @@
|
||||
android:id="@+id/stats_moving_time_value"
|
||||
style="@style/StatsLargeValue"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_moving_time_label"
|
||||
tools:text="00:00:00" />
|
||||
|
||||
@@ -130,8 +130,8 @@
|
||||
android:id="@+id/stats_speed_horizontal_line"
|
||||
style="@style/StatsHorizontalLine"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_time_barrier" />
|
||||
|
||||
<!-- Average speed/pace -->
|
||||
@@ -139,8 +139,8 @@
|
||||
android:id="@+id/stats_average_speed_label"
|
||||
style="@style/StatsSmallLabel"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_speed_horizontal_line"
|
||||
tools:text="Avg. Speed" />
|
||||
|
||||
@@ -149,8 +149,8 @@
|
||||
style="@style/StatsSmallValue"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/stats_average_speed_unit"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/stats_average_speed_unit"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_average_speed_label"
|
||||
tools:text="30.00" />
|
||||
|
||||
@@ -158,8 +158,8 @@
|
||||
android:id="@+id/stats_average_speed_unit"
|
||||
style="@style/StatsUnit"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/stats_average_speed_value"
|
||||
app:layout_constraintLeft_toRightOf="@+id/stats_average_speed_value"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/stats_average_speed_value"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
tools:text="km/h" />
|
||||
|
||||
<!-- Speed max -->
|
||||
@@ -167,8 +167,8 @@
|
||||
android:id="@+id/stats_max_speed_label"
|
||||
style="@style/StatsSmallLabel"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_average_speed_value"
|
||||
tools:text="Max. Speed" />
|
||||
|
||||
@@ -177,8 +177,8 @@
|
||||
style="@style/StatsSmallValue"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/stats_max_speed_unit"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/stats_max_speed_unit"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_max_speed_label"
|
||||
tools:text="30.00" />
|
||||
|
||||
@@ -186,8 +186,8 @@
|
||||
android:id="@+id/stats_max_speed_unit"
|
||||
style="@style/StatsUnit"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/stats_max_speed_value"
|
||||
app:layout_constraintLeft_toRightOf="@+id/stats_max_speed_value"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/stats_max_speed_value"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
tools:text="km/h" />
|
||||
|
||||
<!-- Moving speed max -->
|
||||
@@ -195,8 +195,8 @@
|
||||
android:id="@+id/stats_moving_speed_label"
|
||||
style="@style/StatsSmallLabel"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_average_speed_value"
|
||||
tools:text="Max. Moving Speed" />
|
||||
|
||||
@@ -205,8 +205,8 @@
|
||||
style="@style/StatsSmallValue"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/stats_moving_speed_unit"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/stats_moving_speed_unit"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_moving_speed_label"
|
||||
tools:text="30.00" />
|
||||
|
||||
@@ -214,8 +214,8 @@
|
||||
android:id="@+id/stats_moving_speed_unit"
|
||||
style="@style/StatsUnit"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/stats_moving_speed_value"
|
||||
app:layout_constraintLeft_toRightOf="@+id/stats_moving_speed_value"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/stats_moving_speed_value"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
tools:text="km/h" />
|
||||
|
||||
<!-- Barrier -->
|
||||
@@ -231,8 +231,8 @@
|
||||
android:id="@+id/stats_elevation_horizontal_line"
|
||||
style="@style/StatsHorizontalLine"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_speed_barrier" />
|
||||
|
||||
<!-- Elevation gain -->
|
||||
@@ -247,8 +247,8 @@
|
||||
style="@style/StatsSmallLabel"
|
||||
android:text="@string/stats_gain"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_elevation_horizontal_line" />
|
||||
|
||||
<TextView
|
||||
@@ -256,8 +256,8 @@
|
||||
style="@style/StatsSmallValue"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/stats_elevation_gain_unit"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/stats_elevation_gain_unit"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_elevation_gain_label"
|
||||
tools:text="100" />
|
||||
|
||||
@@ -265,8 +265,8 @@
|
||||
android:id="@+id/stats_elevation_gain_unit"
|
||||
style="@style/StatsUnit"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/stats_elevation_gain_value"
|
||||
app:layout_constraintLeft_toRightOf="@+id/stats_elevation_gain_value"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/stats_elevation_gain_value"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
tools:text="m" />
|
||||
|
||||
<!-- Barrier -->
|
||||
@@ -282,8 +282,8 @@
|
||||
android:id="@+id/stats_end_horizontal_line"
|
||||
style="@style/StatsHorizontalLine"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_elevation_barrier" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
style="@style/StatsLargeLabel"
|
||||
android:text="@string/stats_distance"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
@@ -45,8 +45,8 @@
|
||||
style="@style/StatsLargeValue"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/stats_distance_unit"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/stats_distance_unit"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_distance_label"
|
||||
tools:text="100" />
|
||||
|
||||
@@ -54,8 +54,8 @@
|
||||
android:id="@+id/stats_distance_unit"
|
||||
style="@style/StatsUnit"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/stats_distance_value"
|
||||
app:layout_constraintLeft_toRightOf="@+id/stats_distance_value"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/stats_distance_value"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
tools:text="km" />
|
||||
|
||||
<!-- Activity Type -->
|
||||
@@ -64,8 +64,8 @@
|
||||
style="@style/StatsLargeLabel"
|
||||
android:text="@string/track_edit_activity_type_hint"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
@@ -73,8 +73,8 @@
|
||||
style="@style/StatsLargeValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/stats_distance_value"
|
||||
app:layout_constraintTop_toTopOf="@+id/stats_distance_value" />
|
||||
|
||||
@@ -84,15 +84,15 @@
|
||||
style="@style/StatsLargeLabel"
|
||||
android:text="@string/stats_total_time"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_distance_value" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_total_time_value"
|
||||
style="@style/StatsLargeValue"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_total_time_label"
|
||||
tools:text="00:00:00" />
|
||||
|
||||
@@ -102,8 +102,8 @@
|
||||
style="@style/StatsLargeLabel"
|
||||
android:text="@string/stats_moving_time"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toTopOf="@+id/stats_total_time_label"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/stats_total_time_label" />
|
||||
|
||||
@@ -111,8 +111,8 @@
|
||||
android:id="@+id/stats_moving_time_value"
|
||||
style="@style/StatsLargeValue"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_moving_time_label"
|
||||
tools:text="00:00:00" />
|
||||
|
||||
@@ -129,8 +129,8 @@
|
||||
android:id="@+id/stats_speed_horizontal_line"
|
||||
style="@style/StatsHorizontalLine"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_time_barrier" />
|
||||
|
||||
<!-- Speed/pace -->
|
||||
@@ -138,8 +138,8 @@
|
||||
android:id="@+id/stats_speed_label"
|
||||
style="@style/StatsSmallLabel"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_speed_horizontal_line"
|
||||
tools:text="Speed" />
|
||||
|
||||
@@ -148,8 +148,8 @@
|
||||
style="@style/StatsSmallValue"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/stats_speed_unit"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/stats_speed_unit"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_speed_label"
|
||||
tools:text="30.00" />
|
||||
|
||||
@@ -157,8 +157,8 @@
|
||||
android:id="@+id/stats_speed_unit"
|
||||
style="@style/StatsUnit"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/stats_speed_value"
|
||||
app:layout_constraintLeft_toRightOf="@+id/stats_speed_value"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/stats_speed_value"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
tools:text="km/h" />
|
||||
|
||||
<!-- Average speed/pace -->
|
||||
@@ -166,8 +166,8 @@
|
||||
android:id="@+id/stats_average_speed_label"
|
||||
style="@style/StatsSmallLabel"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_speed_horizontal_line"
|
||||
tools:text="Avg. Speed" />
|
||||
|
||||
@@ -176,8 +176,8 @@
|
||||
style="@style/StatsSmallValue"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/stats_average_speed_unit"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/stats_average_speed_unit"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_average_speed_label"
|
||||
tools:text="30.00" />
|
||||
|
||||
@@ -185,8 +185,8 @@
|
||||
android:id="@+id/stats_average_speed_unit"
|
||||
style="@style/StatsUnit"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/stats_average_speed_value"
|
||||
app:layout_constraintLeft_toRightOf="@+id/stats_average_speed_value"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/stats_average_speed_value"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
tools:text="km/h" />
|
||||
|
||||
<!-- Speed max -->
|
||||
@@ -194,8 +194,8 @@
|
||||
android:id="@+id/stats_max_speed_label"
|
||||
style="@style/StatsSmallLabel"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_average_speed_value"
|
||||
tools:text="Max. Speed" />
|
||||
|
||||
@@ -204,8 +204,8 @@
|
||||
style="@style/StatsSmallValue"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/stats_max_speed_unit"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/stats_max_speed_unit"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_max_speed_label"
|
||||
tools:text="30.00" />
|
||||
|
||||
@@ -213,8 +213,8 @@
|
||||
android:id="@+id/stats_max_speed_unit"
|
||||
style="@style/StatsUnit"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/stats_max_speed_value"
|
||||
app:layout_constraintLeft_toRightOf="@+id/stats_max_speed_value"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/stats_max_speed_value"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
tools:text="km/h" />
|
||||
|
||||
<!-- Moving speed max -->
|
||||
@@ -222,8 +222,8 @@
|
||||
android:id="@+id/stats_moving_speed_label"
|
||||
style="@style/StatsSmallLabel"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_average_speed_value"
|
||||
tools:text="Max. Moving Speed" />
|
||||
|
||||
@@ -232,8 +232,8 @@
|
||||
style="@style/StatsSmallValue"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/stats_moving_speed_unit"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/stats_moving_speed_unit"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_moving_speed_label"
|
||||
tools:text="30.00" />
|
||||
|
||||
@@ -241,8 +241,8 @@
|
||||
android:id="@+id/stats_moving_speed_unit"
|
||||
style="@style/StatsUnit"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/stats_moving_speed_value"
|
||||
app:layout_constraintLeft_toRightOf="@+id/stats_moving_speed_value"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/stats_moving_speed_value"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
tools:text="km/h" />
|
||||
|
||||
<!-- Barrier -->
|
||||
@@ -258,8 +258,8 @@
|
||||
android:id="@+id/stats_elevation_horizontal_line"
|
||||
style="@style/StatsHorizontalLine"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_speed_barrier" />
|
||||
|
||||
<!-- Elevation -->
|
||||
@@ -275,8 +275,8 @@
|
||||
style="@style/StatsSmallLabel"
|
||||
android:text="@string/stats_elevation"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_elevation_horizontal_line" />
|
||||
|
||||
<TextView
|
||||
@@ -284,8 +284,8 @@
|
||||
style="@style/StatsSmallValue"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/stats_elevation_current_unit"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/stats_elevation_current_unit"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_elevation_current_label"
|
||||
tools:text="100" />
|
||||
|
||||
@@ -293,8 +293,8 @@
|
||||
android:id="@+id/stats_elevation_current_unit"
|
||||
style="@style/StatsUnit"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/stats_elevation_current_value"
|
||||
app:layout_constraintLeft_toRightOf="@+id/stats_elevation_current_value"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/stats_elevation_current_value"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
tools:text="m" />
|
||||
|
||||
<!-- Current elevation -->
|
||||
@@ -303,8 +303,8 @@
|
||||
style="@style/StatsSmallLabel"
|
||||
android:text="@string/stats_gain"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_elevation_horizontal_line" />
|
||||
|
||||
<TextView
|
||||
@@ -312,8 +312,8 @@
|
||||
style="@style/StatsSmallValue"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/stats_elevation_gain_unit"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/stats_elevation_gain_unit"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_elevation_gain_label"
|
||||
tools:text="100" />
|
||||
|
||||
@@ -321,8 +321,8 @@
|
||||
android:id="@+id/stats_elevation_gain_unit"
|
||||
style="@style/StatsUnit"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/stats_elevation_gain_value"
|
||||
app:layout_constraintLeft_toRightOf="@+id/stats_elevation_gain_value"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/stats_elevation_gain_value"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
tools:text="m" />
|
||||
|
||||
<!-- Coordinate group -->
|
||||
@@ -345,8 +345,8 @@
|
||||
android:id="@+id/stats_coordinate_horizontal_line"
|
||||
style="@style/StatsHorizontalLine"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_elevation_barrier" />
|
||||
|
||||
<!-- Latitude -->
|
||||
@@ -355,15 +355,15 @@
|
||||
style="@style/StatsSmallLabel"
|
||||
android:text="@string/stats_latitude"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_coordinate_horizontal_line" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_latitude_value"
|
||||
style="@style/StatsSmallValue"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_latitude_label"
|
||||
tools:text="0.834937848" />
|
||||
|
||||
@@ -373,16 +373,16 @@
|
||||
style="@style/StatsSmallLabel"
|
||||
android:text="@string/stats_longitude"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_coordinate_horizontal_line" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stats_longitude_value"
|
||||
style="@style/StatsSmallValue"
|
||||
android:value="@string/value_unknown"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline2"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline2"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_longitude_label"
|
||||
tools:text="0.834937848" />
|
||||
|
||||
@@ -399,8 +399,8 @@
|
||||
android:id="@+id/stats_sensor_horizontal_line"
|
||||
style="@style/StatsHorizontalLine"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats_location_barrier" />
|
||||
|
||||
<!-- Sensors data -->
|
||||
@@ -408,8 +408,8 @@
|
||||
android:id="@+id/stats_sensors_recycler_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toRightOf="@+id/guideline"
|
||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline3"
|
||||
app:layout_constraintTop_toBottomOf="@id/stats_sensor_horizontal_line" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@@ -95,13 +95,13 @@ limitations under the License.
|
||||
<Button
|
||||
android:id="@+id/track_edit_cancel"
|
||||
style="@style/BottomButton"
|
||||
android:layout_gravity="left"
|
||||
android:layout_gravity="start"
|
||||
android:text="@string/generic_cancel" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/track_edit_save"
|
||||
style="@style/BottomButton"
|
||||
android:layout_gravity="right"
|
||||
android:layout_gravity="end"
|
||||
android:text="@string/generic_save" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -73,7 +73,7 @@ limitations under the License.
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="22"
|
||||
android:gravity="left"
|
||||
android:gravity="start"
|
||||
android:text="@string/track_list_empty_message" />
|
||||
|
||||
<View
|
||||
|
||||
@@ -25,7 +25,7 @@ limitations under the License.
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/track_detail_activity_view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/track_detail_activity_view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
|
||||
@@ -38,12 +38,12 @@ limitations under the License.
|
||||
a)
|
||||
(live updates) Install <a href="https://github.com/OpenTracksApp/OSMDashboard">OSMDashboard</a>.
|
||||
It provides online or offline maps via <a href="https://www.openstreetmap.org">OpenStreetMap</a>.\n
|
||||
Actually, OSMDashboard is a separate app that only can access (temporarily) access the data of track(s) that are going to be shown.
|
||||
Actually, OSMDashboard is a separate app that only can access (temporarily) the data of track(s) that are going to be shown.
|
||||
|
||||
\n
|
||||
b)
|
||||
Via a "normal" map application (e.g., <a href="http://osmand.net/">OsmAnd</a> and <a href="https://maps.me/">MAPS.ME</a>).
|
||||
Those app need to support the KMZ file format (only locations and timestamps).
|
||||
These apps need to support the KMZ file format (only locations and timestamps).
|
||||
In fact, an app needs to support <i>ACTION_VIEW</i> with MIME <i>application/vnd.google-earth.kmz</i>.
|
||||
</string>
|
||||
|
||||
@@ -77,7 +77,7 @@ limitations under the License.
|
||||
What you can do:\n
|
||||
a) check if GPS is enabled,\n
|
||||
b) improve GPS reception (e.g., go outdoors),\n
|
||||
c) check if with <a href="https://f-droid.org/en/packages/com.android.gpstest.osmdroid/">GPSTest</a> app, and\n
|
||||
c) check with <a href="https://f-droid.org/en/packages/com.android.gpstest.osmdroid/">GPSTest</a> app, and\n
|
||||
d) disable power saving.\n
|
||||
\n
|
||||
If everything does not help please report a bug.
|
||||
@@ -290,10 +290,12 @@ limitations under the License.
|
||||
<string name="import_unsupported_format">Unsupported file format</string>
|
||||
<string name="import_parser_error">Parser error: %1$s</string>
|
||||
<string name="import_unable_to_import_file">Unable to import file: %1$s</string>
|
||||
<string name="import_no_kml_file_found">No doc.kml file found in KMZ</string>
|
||||
<string name="import_error_info">%1$s: %2$s</string>
|
||||
<string name="import_error_list_dialog_title">Files not imported</string>
|
||||
<string name="import_file_imported">File %1$s imported</string>
|
||||
<string name="import_error">Imported %1$d of %2$s from %3$s</string>
|
||||
<string name="import_prevent_reimport">You have set prevent re-import track</string>
|
||||
<string name="import_no_directory">%1$s does not exist</string>
|
||||
<string name="import_no_file">There were no files to import. Connect your device to your computer and place the files to import in %1$s.</string>
|
||||
<string name="import_no_file_title">Import files</string>
|
||||
@@ -507,8 +509,11 @@ limitations under the License.
|
||||
<string name="value_always">Always</string>
|
||||
<string name="value_float_feet">%1$.2f ft</string>
|
||||
<string name="value_float_kilometer">%1$.2f km</string>
|
||||
<string name="value_float_kilometer_hour">%1$.2f km/h</string>
|
||||
<string name="value_float_meter">%1$.2f m</string>
|
||||
<string name="value_float_mile">%1$.2f mi</string>
|
||||
<string name="value_float_mile_hour">%1$.2f mph</string>
|
||||
|
||||
<string name="value_float_mile_poor_gps">%1$.1f mi (poor GPS)</string>
|
||||
<string name="value_integer_feet">%1$d ft</string>
|
||||
<string name="value_integer_feet_excellent_gps">%1$d ft (excellent GPS)</string>
|
||||
@@ -524,6 +529,8 @@ limitations under the License.
|
||||
<string name="value_integer_minute">%1$d min</string>
|
||||
<string name="value_integer_percent">%1$d %%</string>
|
||||
<string name="value_integer_second">%1$d s</string>
|
||||
<string name="value_pace_mile">%1$d:%2$02d min/mi</string>
|
||||
<string name="value_pace_kilometer">%1$d:%2$02d min/km</string>
|
||||
<string name="value_none">None</string>
|
||||
<string name="value_off">Off</string>
|
||||
<string name="value_smallest">Smallest</string>
|
||||
|
||||
@@ -117,7 +117,23 @@ limitations under the License.
|
||||
<item name="android:paddingTop">6dp</item>
|
||||
</style>
|
||||
|
||||
<style name="StatsLargeLabel" parent="@style/TextSmall">
|
||||
<style name="LargeLabel" parent="@style/TextSmall">
|
||||
<item name="android:textAllCaps">true</item>
|
||||
<item name="android:textColor">?attr/colorAccent</item>
|
||||
<item name="android:textStyle">bold</item>
|
||||
</style>
|
||||
|
||||
<style name="IntervalLabel" parent="@style/LargeLabel">
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:layout_margin">1dp</item>
|
||||
<item name="android:textAlignment">textStart</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:layout_weight">1</item>
|
||||
<item name="android:layout_width">1dp</item>
|
||||
<item name="android:layout_gravity">center</item>
|
||||
</style>
|
||||
|
||||
<style name="StatsLargeLabel" parent="@style/LargeLabel">
|
||||
<item name="android:gravity">center</item>
|
||||
<item name="android:layout_gravity">center</item>
|
||||
<item name="android:singleLine">false</item>
|
||||
|
||||
@@ -25,16 +25,7 @@ limitations under the License.
|
||||
<item name="windowActionModeOverlay">true</item>
|
||||
</style>
|
||||
|
||||
<style name="ThemeCustomNotTransparentDialog" parent="ThemeCustom">
|
||||
<!-- TODO Remove when moving to settings to fragments. -->
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowIsFloating">true</item>
|
||||
<item name="android:backgroundDimEnabled">true</item>
|
||||
</style>
|
||||
|
||||
<style name="TrackDeleteActivity" parent="ThemeCustom">
|
||||
<!-- TODO Remove when moving to TrackDeleteActivity to fragments. -->
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:windowIsFloating">true</item>
|
||||
|
||||
Reference in New Issue
Block a user