mirror of
https://github.com/russok/FitoTrack.git
synced 2025-10-29 00:32:11 -07:00
Better layout for workout map and diagrams
This commit is contained in:
parent
ec73699411
commit
b8a0012f7d
@ -22,13 +22,14 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="de.tadris.fitness">
|
package="de.tadris.fitness">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
@ -36,8 +37,13 @@
|
|||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
|
android:appCategory="productivity"
|
||||||
tools:ignore="GoogleAppIndexingWarning">
|
tools:ignore="GoogleAppIndexingWarning">
|
||||||
<activity android:name=".activity.SettingsActivity"></activity>
|
<activity android:name=".activity.ShowWorkoutMapActivity"
|
||||||
|
android:screenOrientation="portrait"></activity>
|
||||||
|
<activity android:name=".activity.ShowWorkoutMapDiagramActivity"
|
||||||
|
android:screenOrientation="portrait"></activity>
|
||||||
|
<activity android:name=".activity.SettingsActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.ShowWorkoutActivity"
|
android:name=".activity.ShowWorkoutActivity"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait" />
|
||||||
@ -56,15 +62,17 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="de.tadris.fitness.fileprovider"
|
android:authorities="de.tadris.fitness.fileprovider"
|
||||||
android:grantUriPermissions="true"
|
android:exported="false"
|
||||||
android:exported="false">
|
android:grantUriPermissions="true">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
android:resource="@xml/filepaths" />
|
android:resource="@xml/filepaths" />
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<service android:name=".recording.LocationListener" />
|
<service android:name=".recording.LocationListener" />
|
||||||
<service android:name=".recording.PressureService" />
|
<service android:name=".recording.PressureService" />
|
||||||
</application>
|
</application>
|
||||||
|
|||||||
@ -20,101 +20,42 @@
|
|||||||
package de.tadris.fitness.activity;
|
package de.tadris.fitness.activity;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.res.Resources;
|
import android.content.Intent;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
|
||||||
import android.transition.Scene;
|
|
||||||
import android.transition.TransitionManager;
|
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.core.content.FileProvider;
|
import androidx.core.content.FileProvider;
|
||||||
|
|
||||||
import com.github.mikephil.charting.charts.LineChart;
|
|
||||||
import com.github.mikephil.charting.components.Description;
|
|
||||||
import com.github.mikephil.charting.data.Entry;
|
|
||||||
import com.github.mikephil.charting.data.LineData;
|
|
||||||
import com.github.mikephil.charting.data.LineDataSet;
|
|
||||||
import com.github.mikephil.charting.highlight.Highlight;
|
|
||||||
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
|
|
||||||
|
|
||||||
import org.mapsforge.core.graphics.Paint;
|
|
||||||
import org.mapsforge.core.model.BoundingBox;
|
|
||||||
import org.mapsforge.core.model.MapPosition;
|
|
||||||
import org.mapsforge.core.util.LatLongUtils;
|
|
||||||
import org.mapsforge.map.android.graphics.AndroidGraphicFactory;
|
|
||||||
import org.mapsforge.map.android.view.MapView;
|
|
||||||
import org.mapsforge.map.layer.download.TileDownloadLayer;
|
|
||||||
import org.mapsforge.map.layer.overlay.FixedPixelCircle;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import de.tadris.fitness.Instance;
|
import de.tadris.fitness.Instance;
|
||||||
import de.tadris.fitness.R;
|
import de.tadris.fitness.R;
|
||||||
import de.tadris.fitness.data.Workout;
|
|
||||||
import de.tadris.fitness.data.WorkoutManager;
|
|
||||||
import de.tadris.fitness.data.WorkoutSample;
|
|
||||||
import de.tadris.fitness.map.MapManager;
|
|
||||||
import de.tadris.fitness.map.WorkoutLayer;
|
|
||||||
import de.tadris.fitness.map.tilesource.TileSources;
|
|
||||||
import de.tadris.fitness.util.ThemeManager;
|
|
||||||
import de.tadris.fitness.util.WorkoutTypeCalculator;
|
|
||||||
import de.tadris.fitness.util.gpx.GpxExporter;
|
import de.tadris.fitness.util.gpx.GpxExporter;
|
||||||
import de.tadris.fitness.util.unit.UnitUtils;
|
import de.tadris.fitness.util.unit.UnitUtils;
|
||||||
import de.tadris.fitness.view.ProgressDialogController;
|
import de.tadris.fitness.view.ProgressDialogController;
|
||||||
|
|
||||||
public class ShowWorkoutActivity extends FitoTrackActivity {
|
public class ShowWorkoutActivity extends WorkoutActivity {
|
||||||
static Workout selectedWorkout;
|
|
||||||
|
|
||||||
List<WorkoutSample> samples;
|
|
||||||
Workout workout;
|
|
||||||
ViewGroup root;
|
|
||||||
Resources.Theme theme;
|
|
||||||
MapView map;
|
|
||||||
TileDownloadLayer downloadLayer;
|
|
||||||
FixedPixelCircle highlightingCircle;
|
|
||||||
Handler mHandler= new Handler();
|
|
||||||
|
|
||||||
Scene sceneOverview;
|
|
||||||
Scene speedDiagramScene;
|
|
||||||
Scene heightDiagramScene;
|
|
||||||
Scene mapScene;
|
|
||||||
LineChart speedDiagram;
|
|
||||||
LineChart heightDiagram;
|
|
||||||
ViewGroup sceneRoot;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
workout= selectedWorkout;
|
initBeforeContent();
|
||||||
samples= Arrays.asList(Instance.getInstance(this).db.workoutDao().getAllSamplesOfWorkout(workout.id));
|
|
||||||
setTheme(ThemeManager.getThemeByWorkout(workout));
|
|
||||||
setContentView(R.layout.activity_show_workout);
|
setContentView(R.layout.activity_show_workout);
|
||||||
|
|
||||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
|
||||||
setTitle(WorkoutTypeCalculator.getType(workout));
|
|
||||||
|
|
||||||
theme= getTheme();
|
|
||||||
|
|
||||||
root= findViewById(R.id.showWorkoutRoot);
|
root= findViewById(R.id.showWorkoutRoot);
|
||||||
sceneRoot= findViewById(R.id.showWorkoutSceneRoot);
|
|
||||||
ViewGroup sceneLayout= findViewById(R.id.showWorkoutDefaultSceneRoot);
|
initAfterContent();
|
||||||
sceneOverview= new Scene(sceneRoot, sceneLayout);
|
|
||||||
|
|
||||||
addText(getString(R.string.comment) + ": " + workout.comment).setOnClickListener(v -> {
|
addText(getString(R.string.comment) + ": " + workout.comment).setOnClickListener(v -> {
|
||||||
TextView textView= (TextView)v;
|
TextView textView= (TextView)v;
|
||||||
@ -134,6 +75,9 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
|
|||||||
|
|
||||||
addMap();
|
addMap();
|
||||||
|
|
||||||
|
map.setClickable(false);
|
||||||
|
mapRoot.setOnClickListener(v -> startActivity(new Intent(ShowWorkoutActivity.this, ShowWorkoutMapActivity.class)));
|
||||||
|
|
||||||
addTitle(getString(R.string.workoutSpeed));
|
addTitle(getString(R.string.workoutSpeed));
|
||||||
|
|
||||||
addKeyValue(getString(R.string.workoutAvgSpeed), UnitUtils.getSpeed(workout.avgSpeed),
|
addKeyValue(getString(R.string.workoutAvgSpeed), UnitUtils.getSpeed(workout.avgSpeed),
|
||||||
@ -141,6 +85,8 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
|
|||||||
|
|
||||||
addSpeedDiagram();
|
addSpeedDiagram();
|
||||||
|
|
||||||
|
speedDiagram.setOnClickListener(v -> startDiagramActivity(ShowWorkoutMapDiagramActivity.DIAGRAM_TYPE_SPEED));
|
||||||
|
|
||||||
addTitle(getString(R.string.workoutBurnedEnergy));
|
addTitle(getString(R.string.workoutBurnedEnergy));
|
||||||
addKeyValue(getString(R.string.workoutTotalEnergy), workout.calorie + " kcal",
|
addKeyValue(getString(R.string.workoutTotalEnergy), workout.calorie + " kcal",
|
||||||
getString(R.string.workoutEnergyConsumption), UnitUtils.getRelativeEnergyConsumption((double)workout.calorie / ((double)workout.length / 1000)));
|
getString(R.string.workoutEnergyConsumption), UnitUtils.getRelativeEnergyConsumption((double)workout.calorie / ((double)workout.length / 1000)));
|
||||||
@ -152,23 +98,16 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
|
|||||||
|
|
||||||
addHeightDiagram();
|
addHeightDiagram();
|
||||||
|
|
||||||
createScenes();
|
heightDiagram.setOnClickListener(v -> startDiagramActivity(ShowWorkoutMapDiagramActivity.DIAGRAM_TYPE_HEIGHT));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void createScenes(){
|
void startDiagramActivity(String diagramType){
|
||||||
speedDiagramScene= createDiagramScene(speedDiagram);
|
ShowWorkoutMapDiagramActivity.DIAGRAM_TYPE= diagramType;
|
||||||
heightDiagramScene= createDiagramScene(heightDiagram);
|
startActivity(new Intent(ShowWorkoutActivity.this, ShowWorkoutMapDiagramActivity.class));
|
||||||
mapScene= new Scene(sceneRoot, map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Scene createDiagramScene(LineChart chart){
|
|
||||||
LinearLayout layout= new LinearLayout(this);
|
|
||||||
layout.setOrientation(LinearLayout.VERTICAL);
|
|
||||||
layout.addView(map, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getMapHeight()));
|
|
||||||
layout.addView(chart, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
|
||||||
return new Scene(sceneRoot, layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void openEditCommentDialog(final TextView change){
|
void openEditCommentDialog(final TextView change){
|
||||||
final EditText editText= new EditText(this);
|
final EditText editText= new EditText(this);
|
||||||
@ -235,219 +174,6 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
|
|||||||
root.addView(v);
|
root.addView(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addDiagram(SampleConverter converter){
|
|
||||||
LineChart chart= new LineChart(this);
|
|
||||||
|
|
||||||
converter.onCreate();
|
|
||||||
|
|
||||||
List<Entry> entries = new ArrayList<>();
|
|
||||||
for (WorkoutSample sample : samples) {
|
|
||||||
// turn your data into Entry objects
|
|
||||||
Entry e= new Entry((float)(sample.relativeTime) / 1000f / 60f, converter.getValue(sample));
|
|
||||||
entries.add(e);
|
|
||||||
converter.sampleGetsEntry(sample, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
LineDataSet dataSet = new LineDataSet(entries, converter.getName()); // add entries to dataset
|
|
||||||
dataSet.setColor(getThemePrimaryColor());
|
|
||||||
dataSet.setValueTextColor(getThemePrimaryColor());
|
|
||||||
dataSet.setDrawCircles(false);
|
|
||||||
dataSet.setLineWidth(4);
|
|
||||||
dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
|
|
||||||
|
|
||||||
Description description= new Description();
|
|
||||||
description.setText(converter.getDescription());
|
|
||||||
|
|
||||||
LineData lineData = new LineData(dataSet);
|
|
||||||
chart.setData(lineData);
|
|
||||||
chart.setScaleXEnabled(true);
|
|
||||||
chart.setScaleYEnabled(false);
|
|
||||||
chart.setDescription(description);
|
|
||||||
chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
|
|
||||||
@Override
|
|
||||||
public void onValueSelected(Entry e, Highlight h) {
|
|
||||||
onNothingSelected();
|
|
||||||
Paint p= AndroidGraphicFactory.INSTANCE.createPaint();
|
|
||||||
p.setColor(Color.BLUE);
|
|
||||||
highlightingCircle= new FixedPixelCircle(findSample(converter, e).toLatLong(), 10, p, null);
|
|
||||||
map.addLayer(highlightingCircle);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNothingSelected() {
|
|
||||||
if(highlightingCircle != null){
|
|
||||||
map.getLayerManager().getLayers().remove(highlightingCircle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
chart.invalidate();
|
|
||||||
|
|
||||||
converter.afterAdd(chart);
|
|
||||||
|
|
||||||
root.addView(chart, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getWindowManager().getDefaultDisplay().getWidth()*3/4));
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SampleConverter{
|
|
||||||
void onCreate();
|
|
||||||
float getValue(WorkoutSample sample);
|
|
||||||
void sampleGetsEntry(WorkoutSample sample, Entry entry);
|
|
||||||
String getName();
|
|
||||||
String getDescription();
|
|
||||||
boolean compare(WorkoutSample sample, Entry entry);
|
|
||||||
void afterAdd(LineChart chart);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addHeightDiagram(){
|
|
||||||
addDiagram(new SampleConverter() {
|
|
||||||
@Override
|
|
||||||
public void onCreate() { }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getValue(WorkoutSample sample) {
|
|
||||||
return (float)UnitUtils.CHOSEN_SYSTEM.getDistanceFromMeters(sample.elevation);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sampleGetsEntry(WorkoutSample sample, Entry entry) {
|
|
||||||
sample.tmpHeightEntry= entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return getString(R.string.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return "min - " + UnitUtils.CHOSEN_SYSTEM.getShortDistanceUnit();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean compare(WorkoutSample sample, Entry entry) {
|
|
||||||
return sample.tmpHeightEntry.equalTo(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterAdd(LineChart chart) {
|
|
||||||
heightDiagram= chart;
|
|
||||||
heightDiagram.setOnClickListener(v -> TransitionManager.go(heightDiagramScene));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void addSpeedDiagram(){
|
|
||||||
addDiagram(new SampleConverter() {
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
WorkoutManager.roundSpeedValues(samples);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getValue(WorkoutSample sample) {
|
|
||||||
return (float)UnitUtils.CHOSEN_SYSTEM.getSpeedFromMeterPerSecond(sample.tmpRoundedSpeed);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sampleGetsEntry(WorkoutSample sample, Entry entry) {
|
|
||||||
sample.tmpSpeedEntry= entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return getString(R.string.workoutSpeed);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return "min - " + UnitUtils.CHOSEN_SYSTEM.getSpeedUnit();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean compare(WorkoutSample sample, Entry entry) {
|
|
||||||
return sample.tmpSpeedEntry.equalTo(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterAdd(LineChart chart) {
|
|
||||||
speedDiagram= chart;
|
|
||||||
heightDiagram.setOnClickListener(v -> TransitionManager.go(speedDiagramScene));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
WorkoutSample findSample(SampleConverter converter, Entry entry){
|
|
||||||
for(WorkoutSample sample : samples){
|
|
||||||
if(converter.compare(sample, entry)){
|
|
||||||
return sample;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addMap(){
|
|
||||||
map= new MapView(this);
|
|
||||||
downloadLayer= MapManager.setupMap(map, TileSources.Purpose.DEFAULT);
|
|
||||||
|
|
||||||
WorkoutLayer workoutLayer= new WorkoutLayer(samples, getThemePrimaryColor());
|
|
||||||
map.addLayer(workoutLayer);
|
|
||||||
|
|
||||||
final BoundingBox bounds= new BoundingBox(workoutLayer.getLatLongs()).extendMeters(50);
|
|
||||||
mHandler.postDelayed(() -> {
|
|
||||||
map.getModel().mapViewPosition.setMapPosition(new MapPosition(bounds.getCenterPoint(),
|
|
||||||
(LatLongUtils.zoomForBounds(map.getDimension(), bounds, map.getModel().displayModel.getTileSize()))));
|
|
||||||
map.animate().alpha(1f).setDuration(1000).start();
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
map.getModel().mapViewPosition.setMapLimit(bounds);
|
|
||||||
|
|
||||||
|
|
||||||
root.addView(map, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getMapHeight()));
|
|
||||||
map.setAlpha(0);
|
|
||||||
|
|
||||||
|
|
||||||
Paint pGreen= AndroidGraphicFactory.INSTANCE.createPaint();
|
|
||||||
pGreen.setColor(Color.GREEN);
|
|
||||||
map.addLayer(new FixedPixelCircle(samples.get(0).toLatLong(), 20, pGreen, null));
|
|
||||||
Paint pRed= AndroidGraphicFactory.INSTANCE.createPaint();
|
|
||||||
pRed.setColor(Color.RED);
|
|
||||||
map.addLayer(new FixedPixelCircle(samples.get(samples.size()-1).toLatLong(), 20, pRed, null));
|
|
||||||
|
|
||||||
map.setOnClickListener(v -> goToMapScene());
|
|
||||||
|
|
||||||
goToMapScene();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void goToMapScene(){
|
|
||||||
TransitionManager.go(mapScene);
|
|
||||||
map.setOnClickListener(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void leaveMapScene(){
|
|
||||||
TransitionManager.go(sceneOverview);
|
|
||||||
map.setOnClickListener(v -> goToMapScene());
|
|
||||||
}
|
|
||||||
|
|
||||||
int getMapHeight(){
|
|
||||||
return getWindowManager().getDefaultDisplay().getWidth()*3/4;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
map.destroyAll();
|
|
||||||
AndroidGraphicFactory.clearResourceMemoryCache();
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause(){
|
|
||||||
super.onPause();
|
|
||||||
downloadLayer.onPause();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onResume(){
|
|
||||||
super.onResume();
|
|
||||||
downloadLayer.onResume();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
@ -500,9 +226,6 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
|
|||||||
case R.id.actionExportGpx:
|
case R.id.actionExportGpx:
|
||||||
exportToGpx();
|
exportToGpx();
|
||||||
return true;
|
return true;
|
||||||
case android.R.id.home:
|
|
||||||
finish();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.activity;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import de.tadris.fitness.R;
|
||||||
|
|
||||||
|
public class ShowWorkoutMapActivity extends WorkoutActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
initBeforeContent();
|
||||||
|
|
||||||
|
setContentView(R.layout.activity_show_workout_map);
|
||||||
|
root= findViewById(R.id.showWorkoutMapParent);
|
||||||
|
|
||||||
|
initAfterContent();
|
||||||
|
|
||||||
|
fullScreenItems = true;
|
||||||
|
addMap();
|
||||||
|
|
||||||
|
map.setClickable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.activity;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import de.tadris.fitness.R;
|
||||||
|
|
||||||
|
public class ShowWorkoutMapDiagramActivity extends WorkoutActivity {
|
||||||
|
|
||||||
|
public static final String DIAGRAM_TYPE_HEIGHT= "height";
|
||||||
|
public static final String DIAGRAM_TYPE_SPEED= "speed";
|
||||||
|
|
||||||
|
static String DIAGRAM_TYPE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
initBeforeContent();
|
||||||
|
|
||||||
|
setContentView(R.layout.activity_show_workout_map_diagram);
|
||||||
|
root= findViewById(R.id.showWorkoutMapParent);
|
||||||
|
|
||||||
|
initAfterContent();
|
||||||
|
|
||||||
|
fullScreenItems = true;
|
||||||
|
addMap();
|
||||||
|
map.setClickable(true);
|
||||||
|
|
||||||
|
diagramsInteractive= true;
|
||||||
|
root= findViewById(R.id.showWorkoutDiagramParent);
|
||||||
|
switch (DIAGRAM_TYPE){
|
||||||
|
case DIAGRAM_TYPE_HEIGHT: addHeightDiagram(); break;
|
||||||
|
case DIAGRAM_TYPE_SPEED: addSpeedDiagram(); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,316 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.activity;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import com.github.mikephil.charting.charts.LineChart;
|
||||||
|
import com.github.mikephil.charting.components.Description;
|
||||||
|
import com.github.mikephil.charting.data.Entry;
|
||||||
|
import com.github.mikephil.charting.data.LineData;
|
||||||
|
import com.github.mikephil.charting.data.LineDataSet;
|
||||||
|
import com.github.mikephil.charting.highlight.Highlight;
|
||||||
|
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
|
||||||
|
|
||||||
|
import org.mapsforge.core.graphics.Paint;
|
||||||
|
import org.mapsforge.core.model.BoundingBox;
|
||||||
|
import org.mapsforge.core.model.MapPosition;
|
||||||
|
import org.mapsforge.core.util.LatLongUtils;
|
||||||
|
import org.mapsforge.map.android.graphics.AndroidGraphicFactory;
|
||||||
|
import org.mapsforge.map.android.view.MapView;
|
||||||
|
import org.mapsforge.map.layer.download.TileDownloadLayer;
|
||||||
|
import org.mapsforge.map.layer.overlay.FixedPixelCircle;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.tadris.fitness.Instance;
|
||||||
|
import de.tadris.fitness.R;
|
||||||
|
import de.tadris.fitness.data.Workout;
|
||||||
|
import de.tadris.fitness.data.WorkoutManager;
|
||||||
|
import de.tadris.fitness.data.WorkoutSample;
|
||||||
|
import de.tadris.fitness.map.MapManager;
|
||||||
|
import de.tadris.fitness.map.WorkoutLayer;
|
||||||
|
import de.tadris.fitness.map.tilesource.TileSources;
|
||||||
|
import de.tadris.fitness.util.ThemeManager;
|
||||||
|
import de.tadris.fitness.util.WorkoutTypeCalculator;
|
||||||
|
import de.tadris.fitness.util.unit.UnitUtils;
|
||||||
|
|
||||||
|
public abstract class WorkoutActivity extends FitoTrackActivity {
|
||||||
|
|
||||||
|
public static Workout selectedWorkout;
|
||||||
|
|
||||||
|
protected List<WorkoutSample> samples;
|
||||||
|
protected Workout workout;
|
||||||
|
protected ViewGroup root;
|
||||||
|
protected Resources.Theme theme;
|
||||||
|
protected MapView map;
|
||||||
|
protected TileDownloadLayer downloadLayer;
|
||||||
|
protected FixedPixelCircle highlightingCircle;
|
||||||
|
protected Handler mHandler= new Handler();
|
||||||
|
|
||||||
|
protected LineChart speedDiagram, heightDiagram;
|
||||||
|
|
||||||
|
protected void initBeforeContent(){
|
||||||
|
workout= selectedWorkout;
|
||||||
|
samples= Arrays.asList(Instance.getInstance(this).db.workoutDao().getAllSamplesOfWorkout(workout.id));
|
||||||
|
setTheme(ThemeManager.getThemeByWorkout(workout));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initAfterContent(){
|
||||||
|
getActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
setTitle(WorkoutTypeCalculator.getType(workout));
|
||||||
|
|
||||||
|
theme= getTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
void addDiagram(SampleConverter converter){
|
||||||
|
root.addView(getDiagram(converter), new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, fullScreenItems ? ViewGroup.LayoutParams.MATCH_PARENT : getWindowManager().getDefaultDisplay().getWidth()*3/4));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean diagramsInteractive= false;
|
||||||
|
|
||||||
|
LineChart getDiagram(SampleConverter converter){
|
||||||
|
LineChart chart= new LineChart(this);
|
||||||
|
|
||||||
|
converter.onCreate();
|
||||||
|
|
||||||
|
List<Entry> entries = new ArrayList<>();
|
||||||
|
for (WorkoutSample sample : samples) {
|
||||||
|
// turn your data into Entry objects
|
||||||
|
Entry e= new Entry((float)(sample.relativeTime) / 1000f / 60f, converter.getValue(sample));
|
||||||
|
entries.add(e);
|
||||||
|
converter.sampleGetsEntry(sample, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
LineDataSet dataSet = new LineDataSet(entries, converter.getName()); // add entries to dataset
|
||||||
|
dataSet.setColor(getThemePrimaryColor());
|
||||||
|
dataSet.setValueTextColor(getThemePrimaryColor());
|
||||||
|
dataSet.setDrawCircles(false);
|
||||||
|
dataSet.setLineWidth(4);
|
||||||
|
dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
|
||||||
|
|
||||||
|
Description description= new Description();
|
||||||
|
description.setText(converter.getDescription());
|
||||||
|
|
||||||
|
LineData lineData = new LineData(dataSet);
|
||||||
|
chart.setData(lineData);
|
||||||
|
chart.setScaleXEnabled(diagramsInteractive);
|
||||||
|
chart.setScaleYEnabled(false);
|
||||||
|
chart.setDescription(description);
|
||||||
|
if(diagramsInteractive){
|
||||||
|
chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onValueSelected(Entry e, Highlight h) {
|
||||||
|
onNothingSelected();
|
||||||
|
Paint p= AndroidGraphicFactory.INSTANCE.createPaint();
|
||||||
|
p.setColor(Color.BLUE);
|
||||||
|
highlightingCircle= new FixedPixelCircle(findSample(converter, e).toLatLong(), 10, p, null);
|
||||||
|
map.addLayer(highlightingCircle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected() {
|
||||||
|
if(highlightingCircle != null){
|
||||||
|
map.getLayerManager().getLayers().remove(highlightingCircle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
chart.invalidate();
|
||||||
|
|
||||||
|
converter.afterAdd(chart);
|
||||||
|
|
||||||
|
return chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SampleConverter{
|
||||||
|
void onCreate();
|
||||||
|
float getValue(WorkoutSample sample);
|
||||||
|
void sampleGetsEntry(WorkoutSample sample, Entry entry);
|
||||||
|
String getName();
|
||||||
|
String getDescription();
|
||||||
|
boolean compare(WorkoutSample sample, Entry entry);
|
||||||
|
void afterAdd(LineChart chart);
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkoutSample findSample(SampleConverter converter, Entry entry){
|
||||||
|
for(WorkoutSample sample : samples){
|
||||||
|
if(converter.compare(sample, entry)){
|
||||||
|
return sample;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addHeightDiagram(){
|
||||||
|
addDiagram(new SampleConverter() {
|
||||||
|
@Override
|
||||||
|
public void onCreate() { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getValue(WorkoutSample sample) {
|
||||||
|
return (float) UnitUtils.CHOSEN_SYSTEM.getDistanceFromMeters(sample.elevation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sampleGetsEntry(WorkoutSample sample, Entry entry) {
|
||||||
|
sample.tmpHeightEntry= entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return getString(R.string.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "min - " + UnitUtils.CHOSEN_SYSTEM.getShortDistanceUnit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean compare(WorkoutSample sample, Entry entry) {
|
||||||
|
return sample.tmpHeightEntry.equalTo(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterAdd(LineChart chart) {
|
||||||
|
heightDiagram= chart;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void addSpeedDiagram(){
|
||||||
|
addDiagram(new SampleConverter() {
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
WorkoutManager.roundSpeedValues(samples);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getValue(WorkoutSample sample) {
|
||||||
|
return (float)UnitUtils.CHOSEN_SYSTEM.getSpeedFromMeterPerSecond(sample.tmpRoundedSpeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sampleGetsEntry(WorkoutSample sample, Entry entry) {
|
||||||
|
sample.tmpSpeedEntry= entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return getString(R.string.workoutSpeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "min - " + UnitUtils.CHOSEN_SYSTEM.getSpeedUnit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean compare(WorkoutSample sample, Entry entry) {
|
||||||
|
return sample.tmpSpeedEntry.equalTo(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterAdd(LineChart chart) {
|
||||||
|
speedDiagram= chart;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean fullScreenItems = false;
|
||||||
|
protected LinearLayout mapRoot;
|
||||||
|
|
||||||
|
void addMap(){
|
||||||
|
map= new MapView(this);
|
||||||
|
downloadLayer= MapManager.setupMap(map, TileSources.Purpose.DEFAULT);
|
||||||
|
|
||||||
|
WorkoutLayer workoutLayer= new WorkoutLayer(samples, getThemePrimaryColor());
|
||||||
|
map.addLayer(workoutLayer);
|
||||||
|
|
||||||
|
final BoundingBox bounds= new BoundingBox(workoutLayer.getLatLongs()).extendMeters(50);
|
||||||
|
mHandler.postDelayed(() -> {
|
||||||
|
map.getModel().mapViewPosition.setMapPosition(new MapPosition(bounds.getCenterPoint(),
|
||||||
|
(LatLongUtils.zoomForBounds(map.getDimension(), bounds, map.getModel().displayModel.getTileSize()))));
|
||||||
|
map.animate().alpha(1f).setDuration(1000).start();
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
map.getModel().mapViewPosition.setMapLimit(bounds);
|
||||||
|
|
||||||
|
mapRoot= new LinearLayout(this);
|
||||||
|
mapRoot.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
mapRoot.addView(map);
|
||||||
|
|
||||||
|
root.addView(mapRoot, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, fullScreenItems ? ViewGroup.LayoutParams.MATCH_PARENT : getMapHeight()));
|
||||||
|
map.setAlpha(0);
|
||||||
|
|
||||||
|
|
||||||
|
Paint pGreen= AndroidGraphicFactory.INSTANCE.createPaint();
|
||||||
|
pGreen.setColor(Color.GREEN);
|
||||||
|
map.addLayer(new FixedPixelCircle(samples.get(0).toLatLong(), 20, pGreen, null));
|
||||||
|
Paint pRed= AndroidGraphicFactory.INSTANCE.createPaint();
|
||||||
|
pRed.setColor(Color.RED);
|
||||||
|
|
||||||
|
map.addLayer(new FixedPixelCircle(samples.get(samples.size()-1).toLatLong(), 20, pRed, null));
|
||||||
|
|
||||||
|
map.setClickable(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int getMapHeight(){
|
||||||
|
return getWindowManager().getDefaultDisplay().getWidth()*3/4;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
map.destroyAll();
|
||||||
|
AndroidGraphicFactory.clearResourceMemoryCache();
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause(){
|
||||||
|
super.onPause();
|
||||||
|
downloadLayer.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResume(){
|
||||||
|
super.onResume();
|
||||||
|
downloadLayer.onResume();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
int id = item.getItemId();
|
||||||
|
if (id == android.R.id.home) {
|
||||||
|
finish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
37
app/src/main/res/layout/activity_show_workout_map.xml
Normal file
37
app/src/main/res/layout/activity_show_workout_map.xml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
~
|
||||||
|
~ This file is part of FitoTrack
|
||||||
|
~
|
||||||
|
~ FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/showWorkoutMapRoot"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:context=".activity.ShowWorkoutMapActivity">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/showWorkoutMapParent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
~
|
||||||
|
~ This file is part of FitoTrack
|
||||||
|
~
|
||||||
|
~ FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<android.support.constraint.ConstraintLayout 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:id="@+id/showWorkoutMapRoot"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:context=".activity.ShowWorkoutMapActivity" >
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.Guideline
|
||||||
|
android:id="@+id/guideline4"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintGuide_percent="0.6"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/showWorkoutMapParent"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/guideline4"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/showWorkoutDiagramParent"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/guideline4"></LinearLayout>
|
||||||
|
|
||||||
|
</android.support.constraint.ConstraintLayout>
|
||||||
Loading…
x
Reference in New Issue
Block a user