mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-09-01 03:55:47 +02:00
Garmin body energy level (#3964)
Co-authored-by: a0z <a0z@tutamail.com> Co-committed-by: a0z <a0z@tutamail.com>
This commit is contained in:
parent
69441a6a79
commit
82657febf8
@ -122,7 +122,7 @@ public class GBApplication extends Application {
|
|||||||
private static SharedPreferences sharedPrefs;
|
private static SharedPreferences sharedPrefs;
|
||||||
private static final String PREFS_VERSION = "shared_preferences_version";
|
private static final String PREFS_VERSION = "shared_preferences_version";
|
||||||
//if preferences have to be migrated, increment the following and add the migration logic in migratePrefs below; see http://stackoverflow.com/questions/16397848/how-can-i-migrate-android-preferences-with-a-new-version
|
//if preferences have to be migrated, increment the following and add the migration logic in migratePrefs below; see http://stackoverflow.com/questions/16397848/how-can-i-migrate-android-preferences-with-a-new-version
|
||||||
private static final int CURRENT_PREFS_VERSION = 31;
|
private static final int CURRENT_PREFS_VERSION = 32;
|
||||||
|
|
||||||
private static final LimitedQueue<Integer, String> mIDSenderLookup = new LimitedQueue<>(16);
|
private static final LimitedQueue<Integer, String> mIDSenderLookup = new LimitedQueue<>(16);
|
||||||
private static GBPrefs prefs;
|
private static GBPrefs prefs;
|
||||||
@ -1513,6 +1513,36 @@ public class GBApplication extends Application {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oldVersion < 32) {
|
||||||
|
// Add the new HRV Status tab to all devices
|
||||||
|
try (DBHandler db = acquireDB()) {
|
||||||
|
final DaoSession daoSession = db.getDaoSession();
|
||||||
|
final List<Device> activeDevices = DBHelper.getActiveDevices(daoSession);
|
||||||
|
|
||||||
|
for (final Device dbDevice : activeDevices) {
|
||||||
|
final SharedPreferences deviceSharedPrefs = GBApplication.getDeviceSpecificSharedPrefs(dbDevice.getIdentifier());
|
||||||
|
|
||||||
|
final String chartsTabsValue = deviceSharedPrefs.getString("charts_tabs", null);
|
||||||
|
if (chartsTabsValue == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String newPrefValue;
|
||||||
|
if (!StringUtils.isBlank(chartsTabsValue)) {
|
||||||
|
newPrefValue = chartsTabsValue + ",bodyenergy";
|
||||||
|
} else {
|
||||||
|
newPrefValue = "bodyenergy";
|
||||||
|
}
|
||||||
|
|
||||||
|
final SharedPreferences.Editor deviceSharedPrefsEdit = deviceSharedPrefs.edit();
|
||||||
|
deviceSharedPrefsEdit.putString("charts_tabs", newPrefValue);
|
||||||
|
deviceSharedPrefsEdit.apply();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.w(TAG, "error acquiring DB lock");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
editor.putString(PREFS_VERSION, Integer.toString(CURRENT_PREFS_VERSION));
|
editor.putString(PREFS_VERSION, Integer.toString(CURRENT_PREFS_VERSION));
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,9 @@ public class ActivityChartsActivity extends AbstractChartsActivity {
|
|||||||
if (!coordinator.supportsHrvMeasurement()) {
|
if (!coordinator.supportsHrvMeasurement()) {
|
||||||
tabList.remove("hrvstatus");
|
tabList.remove("hrvstatus");
|
||||||
}
|
}
|
||||||
|
if (!coordinator.supportsBodyEnergy()) {
|
||||||
|
tabList.remove("bodyenergy");
|
||||||
|
}
|
||||||
return tabList;
|
return tabList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,6 +148,8 @@ public class ActivityChartsActivity extends AbstractChartsActivity {
|
|||||||
return new WeekSleepChartFragment();
|
return new WeekSleepChartFragment();
|
||||||
case "hrvstatus":
|
case "hrvstatus":
|
||||||
return new HRVStatusFragment();
|
return new HRVStatusFragment();
|
||||||
|
case "bodyenergy":
|
||||||
|
return new BodyEnergyFragment();
|
||||||
case "stress":
|
case "stress":
|
||||||
return new StressChartFragment();
|
return new StressChartFragment();
|
||||||
case "pai":
|
case "pai":
|
||||||
@ -199,6 +204,8 @@ public class ActivityChartsActivity extends AbstractChartsActivity {
|
|||||||
return getSleepTitle();
|
return getSleepTitle();
|
||||||
case "hrvstatus":
|
case "hrvstatus":
|
||||||
return getString(R.string.pref_header_hrv_status);
|
return getString(R.string.pref_header_hrv_status);
|
||||||
|
case "bodyenergy":
|
||||||
|
return getString(R.string.body_energy);
|
||||||
case "stress":
|
case "stress":
|
||||||
return getString(R.string.menuitem_stress);
|
return getString(R.string.menuitem_stress);
|
||||||
case "pai":
|
case "pai":
|
||||||
|
@ -0,0 +1,291 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.activities.charts;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
|
|
||||||
|
import com.github.mikephil.charting.charts.Chart;
|
||||||
|
import com.github.mikephil.charting.charts.LineChart;
|
||||||
|
import com.github.mikephil.charting.components.LegendEntry;
|
||||||
|
import com.github.mikephil.charting.components.XAxis;
|
||||||
|
import com.github.mikephil.charting.components.YAxis;
|
||||||
|
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.formatter.ValueFormatter;
|
||||||
|
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.TimeSampleProvider;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.BodyEnergySample;
|
||||||
|
|
||||||
|
|
||||||
|
public class BodyEnergyFragment extends AbstractChartFragment<BodyEnergyFragment.BodyEnergyData> {
|
||||||
|
protected static final Logger LOG = LoggerFactory.getLogger(BodyEnergyFragment.class);
|
||||||
|
|
||||||
|
private TextView mDateView;
|
||||||
|
private ImageView bodyEnergyGauge;
|
||||||
|
private TextView bodyEnergyGained;
|
||||||
|
private TextView bodyEnergyLost;
|
||||||
|
private LineChart bodyEnergyChart;
|
||||||
|
|
||||||
|
protected int CHART_TEXT_COLOR;
|
||||||
|
protected int LEGEND_TEXT_COLOR;
|
||||||
|
protected int TEXT_COLOR;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
View rootView = inflater.inflate(R.layout.fragment_body_energy, container, false);
|
||||||
|
|
||||||
|
mDateView = rootView.findViewById(R.id.body_energy_date_view);
|
||||||
|
bodyEnergyGauge = rootView.findViewById(R.id.body_energy_gauge);
|
||||||
|
bodyEnergyGained = rootView.findViewById(R.id.body_energy_gained);
|
||||||
|
bodyEnergyLost = rootView.findViewById(R.id.body_energy_lost);
|
||||||
|
bodyEnergyChart = rootView.findViewById(R.id.body_energy_chart);
|
||||||
|
setupBodyEnergyLevelChart();
|
||||||
|
refresh();
|
||||||
|
|
||||||
|
|
||||||
|
return rootView;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTitle() {
|
||||||
|
return getString(R.string.body_energy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
TEXT_COLOR = GBApplication.getTextColor(requireContext());
|
||||||
|
LEGEND_TEXT_COLOR = GBApplication.getTextColor(requireContext());
|
||||||
|
CHART_TEXT_COLOR = GBApplication.getSecondaryTextColor(requireContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected BodyEnergyData refreshInBackground(ChartsHost chartsHost, DBHandler db, GBDevice device) {
|
||||||
|
String formattedDate = new SimpleDateFormat("E, MMM dd").format(getEndDate());
|
||||||
|
mDateView.setText(formattedDate);
|
||||||
|
List<? extends BodyEnergySample> samples = getBodyEnergySamples(db, device, getTSStart(), getTSEnd());
|
||||||
|
return new BodyEnergyData(samples);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateChartsnUIThread(BodyEnergyData bodyEnergyData) {
|
||||||
|
|
||||||
|
List<Entry> lineEntries = new ArrayList<>();
|
||||||
|
final List<ILineDataSet> lineDataSets = new ArrayList<>();
|
||||||
|
final AtomicInteger gainedValue = new AtomicInteger(0);
|
||||||
|
final AtomicInteger drainedValue = new AtomicInteger(0);
|
||||||
|
int newestValue = 0;
|
||||||
|
long referencedTimestamp;
|
||||||
|
if (!bodyEnergyData.samples.isEmpty()) {
|
||||||
|
newestValue = bodyEnergyData.samples.get(bodyEnergyData.samples.size() - 1).getEnergy();
|
||||||
|
referencedTimestamp = bodyEnergyData.samples.get(0).getTimestamp();
|
||||||
|
final AtomicInteger[] lastValue = {new AtomicInteger(0)};
|
||||||
|
bodyEnergyData.samples.forEach((sample) -> {
|
||||||
|
if (sample.getEnergy() < lastValue[0].intValue()) {
|
||||||
|
drainedValue.set(drainedValue.get() + lastValue[0].intValue() - sample.getEnergy());
|
||||||
|
} else if (lastValue[0].intValue() > 0 && sample.getEnergy() > lastValue[0].intValue()) {
|
||||||
|
gainedValue.set(gainedValue.get() + sample.getEnergy() - lastValue[0].intValue());
|
||||||
|
}
|
||||||
|
lastValue[0].set(sample.getEnergy());
|
||||||
|
float x = (float) sample.getTimestamp() / 1000 - (float) referencedTimestamp / 1000;
|
||||||
|
lineEntries.add(new Entry(x, sample.getEnergy()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
final LineDataSet lineDataSet = new LineDataSet(lineEntries, getString(R.string.body_energy_legend_level));
|
||||||
|
lineDataSet.setColor(getResources().getColor(R.color.body_energy_level_color));
|
||||||
|
lineDataSet.setDrawCircles(false);
|
||||||
|
lineDataSet.setLineWidth(2f);
|
||||||
|
lineDataSet.setFillAlpha(255);
|
||||||
|
lineDataSet.setDrawCircles(false);
|
||||||
|
lineDataSet.setCircleColor(getResources().getColor(R.color.body_energy_level_color));
|
||||||
|
lineDataSet.setAxisDependency(YAxis.AxisDependency.LEFT);
|
||||||
|
lineDataSet.setDrawValues(false);
|
||||||
|
lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
|
||||||
|
lineDataSet.setDrawFilled(true);
|
||||||
|
lineDataSet.setFillAlpha(60);
|
||||||
|
lineDataSet.setFillColor(getResources().getColor(R.color.body_energy_level_color ));
|
||||||
|
|
||||||
|
List<LegendEntry> legendEntries = new ArrayList<>(1);
|
||||||
|
LegendEntry activityEntry = new LegendEntry();
|
||||||
|
activityEntry.label = getString(R.string.body_energy_legend_level);
|
||||||
|
activityEntry.formColor = getResources().getColor(R.color.body_energy_level_color);
|
||||||
|
legendEntries.add(activityEntry);
|
||||||
|
bodyEnergyChart.getLegend().setTextColor(LEGEND_TEXT_COLOR);
|
||||||
|
bodyEnergyChart.getLegend().setCustom(legendEntries);
|
||||||
|
|
||||||
|
lineDataSets.add(lineDataSet);
|
||||||
|
final LineData lineData = new LineData(lineDataSets);
|
||||||
|
bodyEnergyChart.setData(lineData);
|
||||||
|
bodyEnergyGauge.setImageBitmap(drawGauge(
|
||||||
|
300,
|
||||||
|
20,
|
||||||
|
getResources().getColor(R.color.body_energy_level_color),
|
||||||
|
newestValue,
|
||||||
|
100
|
||||||
|
));
|
||||||
|
bodyEnergyGained.setText(String.format("+ %s", gainedValue.intValue()));
|
||||||
|
bodyEnergyLost.setText(String.format("- %s", drainedValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderCharts() {
|
||||||
|
bodyEnergyChart.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<? extends BodyEnergySample> getBodyEnergySamples(final DBHandler db, final GBDevice device, int tsFrom, int tsTo) {
|
||||||
|
Calendar day = Calendar.getInstance();
|
||||||
|
day.setTimeInMillis(tsTo * 1000L); //we need today initially, which is the end of the time range
|
||||||
|
day.set(Calendar.HOUR_OF_DAY, 0); //and we set time for the start and end of the same day
|
||||||
|
day.set(Calendar.MINUTE, 0);
|
||||||
|
day.set(Calendar.SECOND, 0);
|
||||||
|
tsFrom = (int) (day.getTimeInMillis() / 1000);
|
||||||
|
tsTo = tsFrom + 24 * 60 * 60 - 1;
|
||||||
|
|
||||||
|
final DeviceCoordinator coordinator = device.getDeviceCoordinator();
|
||||||
|
final TimeSampleProvider<? extends BodyEnergySample> sampleProvider = coordinator.getBodyEnergySampleProvider(device, db.getDaoSession());
|
||||||
|
return sampleProvider.getAllSamples(tsFrom * 1000L, tsTo * 1000L);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setupLegend(Chart<?> chart) {}
|
||||||
|
|
||||||
|
Bitmap drawGauge(int width, int barWidth, @ColorInt int filledColor, int value, int maxValue) {
|
||||||
|
int height = width;
|
||||||
|
int barMargin = (int) Math.ceil(barWidth / 2f);
|
||||||
|
float filledFactor = (float) value / maxValue;
|
||||||
|
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||||
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
Paint paint = new Paint();
|
||||||
|
paint.setAntiAlias(true);
|
||||||
|
paint.setStyle(Paint.Style.STROKE);
|
||||||
|
paint.setStrokeCap(Paint.Cap.ROUND);
|
||||||
|
paint.setStrokeWidth(barWidth);
|
||||||
|
paint.setColor(getResources().getColor(R.color.gauge_line_color));
|
||||||
|
canvas.drawArc(
|
||||||
|
barMargin,
|
||||||
|
barMargin,
|
||||||
|
width - barMargin,
|
||||||
|
width - barMargin,
|
||||||
|
120,
|
||||||
|
300,
|
||||||
|
false,
|
||||||
|
paint);
|
||||||
|
paint.setStrokeWidth(barWidth);
|
||||||
|
paint.setColor(filledColor);
|
||||||
|
canvas.drawArc(
|
||||||
|
barMargin,
|
||||||
|
barMargin,
|
||||||
|
width - barMargin,
|
||||||
|
height - barMargin,
|
||||||
|
120,
|
||||||
|
300 * filledFactor,
|
||||||
|
false,
|
||||||
|
paint
|
||||||
|
);
|
||||||
|
|
||||||
|
Paint textPaint = new Paint();
|
||||||
|
textPaint.setColor(TEXT_COLOR);
|
||||||
|
float textPixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 18, requireContext().getResources().getDisplayMetrics());
|
||||||
|
textPaint.setTextSize(textPixels);
|
||||||
|
textPaint.setTextAlign(Paint.Align.CENTER);
|
||||||
|
int yPos = (int) ((float) height / 2 - ((textPaint.descent() + textPaint.ascent()) / 2)) ;
|
||||||
|
canvas.drawText(String.valueOf(value), width / 2f, yPos, textPaint);
|
||||||
|
Paint textLowerPaint = new Paint();
|
||||||
|
textLowerPaint.setColor(TEXT_COLOR);
|
||||||
|
textLowerPaint.setTextAlign(Paint.Align.CENTER);
|
||||||
|
float textLowerPixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 8, requireContext().getResources().getDisplayMetrics());
|
||||||
|
textLowerPaint.setTextSize(textLowerPixels);
|
||||||
|
int yPosLowerText = (int) ((float) height / 2 - textPaint.ascent()) ;
|
||||||
|
canvas.drawText(String.valueOf(maxValue), width / 2f, yPosLowerText, textLowerPaint);
|
||||||
|
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupBodyEnergyLevelChart() {
|
||||||
|
bodyEnergyChart.getDescription().setEnabled(false);
|
||||||
|
bodyEnergyChart.setTouchEnabled(false);
|
||||||
|
bodyEnergyChart.setPinchZoom(false);
|
||||||
|
bodyEnergyChart.setDoubleTapToZoomEnabled(false);
|
||||||
|
|
||||||
|
|
||||||
|
final XAxis xAxisBottom = bodyEnergyChart.getXAxis();
|
||||||
|
xAxisBottom.setPosition(XAxis.XAxisPosition.BOTTOM);
|
||||||
|
xAxisBottom.setDrawLabels(true);
|
||||||
|
xAxisBottom.setDrawGridLines(false);
|
||||||
|
xAxisBottom.setEnabled(true);
|
||||||
|
xAxisBottom.setDrawLimitLinesBehindData(true);
|
||||||
|
xAxisBottom.setTextColor(CHART_TEXT_COLOR);
|
||||||
|
xAxisBottom.setAxisMinimum(0f);
|
||||||
|
xAxisBottom.setAxisMaximum(86400f);
|
||||||
|
xAxisBottom.setLabelCount(7, true);
|
||||||
|
xAxisBottom.setValueFormatter(getBodyEnergyChartXValueFormatter());
|
||||||
|
|
||||||
|
final YAxis yAxisLeft = bodyEnergyChart.getAxisLeft();
|
||||||
|
yAxisLeft.setDrawGridLines(true);
|
||||||
|
yAxisLeft.setAxisMaximum(100);
|
||||||
|
yAxisLeft.setAxisMinimum(0);
|
||||||
|
yAxisLeft.setDrawTopYLabelEntry(true);
|
||||||
|
yAxisLeft.setEnabled(true);
|
||||||
|
yAxisLeft.setTextColor(CHART_TEXT_COLOR);
|
||||||
|
|
||||||
|
final YAxis yAxisRight = bodyEnergyChart.getAxisRight();
|
||||||
|
yAxisRight.setEnabled(true);
|
||||||
|
yAxisRight.setDrawLabels(false);
|
||||||
|
yAxisRight.setDrawGridLines(false);
|
||||||
|
yAxisRight.setDrawAxisLine(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueFormatter getBodyEnergyChartXValueFormatter() {
|
||||||
|
return new ValueFormatter() {
|
||||||
|
@Override
|
||||||
|
public String getFormattedValue(float value) {
|
||||||
|
long timestamp = (long) (value * 1000);
|
||||||
|
Date date = new Date ();
|
||||||
|
date.setTime(timestamp);
|
||||||
|
SimpleDateFormat df = new SimpleDateFormat("HH:mm", Locale.getDefault());
|
||||||
|
df.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
|
return df.format(date);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class BodyEnergyData extends ChartsData {
|
||||||
|
private final List<? extends BodyEnergySample> samples;
|
||||||
|
|
||||||
|
protected BodyEnergyData(List<? extends BodyEnergySample> samples) {
|
||||||
|
this.samples = samples;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
126
app/src/main/res/layout/fragment_body_energy.xml
Normal file
126
app/src/main/res/layout/fragment_body_energy.xml
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<RelativeLayout 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"
|
||||||
|
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.BodyEnergy">
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/body_energy_date_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:layout_marginTop="15dp"
|
||||||
|
android:layout_marginBottom="20dp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="180dp"
|
||||||
|
android:layout_height="180dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:scaleType="fitStart"
|
||||||
|
android:id="@+id/body_energy_gauge" />
|
||||||
|
|
||||||
|
|
||||||
|
<TableLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="183dp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:layout_marginBottom="30dp"
|
||||||
|
android:layout_weight="3"
|
||||||
|
android:shrinkColumns="*"
|
||||||
|
android:stretchColumns="*">
|
||||||
|
|
||||||
|
<TableRow
|
||||||
|
android:id="@+id/tableRow1"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:weightSum="2">
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="20dip"
|
||||||
|
android:paddingTop="20dip"
|
||||||
|
android:paddingRight="20dip">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="5px"
|
||||||
|
android:background="@color/value_line_color" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/body_energy_gained"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="left"
|
||||||
|
android:layout_marginTop="20dip"
|
||||||
|
android:text="+ 0"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="left"
|
||||||
|
android:text="@string/body_energy_gained"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="20dip"
|
||||||
|
android:paddingTop="20dip"
|
||||||
|
android:paddingRight="20dip">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="5px"
|
||||||
|
android:background="@color/value_line_color" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/body_energy_lost"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="left"
|
||||||
|
android:layout_marginTop="20dip"
|
||||||
|
android:text="- 0"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="left"
|
||||||
|
android:text="@string/body_energy_lost"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</TableRow>
|
||||||
|
</TableLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="250sp"
|
||||||
|
>
|
||||||
|
<com.github.mikephil.charting.charts.LineChart
|
||||||
|
android:id="@+id/body_energy_chart"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:layout_weight="2" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
@ -3012,6 +3012,7 @@
|
|||||||
<item>@string/weeksleepchart_sleep_a_week_or_month</item>
|
<item>@string/weeksleepchart_sleep_a_week_or_month</item>
|
||||||
<item>@string/weekstepschart_steps_a_week_or_month</item>
|
<item>@string/weekstepschart_steps_a_week_or_month</item>
|
||||||
<item>@string/pref_header_hrv_status</item>
|
<item>@string/pref_header_hrv_status</item>
|
||||||
|
<item>@string/body_energy</item>
|
||||||
<item>@string/menuitem_stress</item>
|
<item>@string/menuitem_stress</item>
|
||||||
<item>@string/menuitem_pai</item>
|
<item>@string/menuitem_pai</item>
|
||||||
<item>@string/stats_title</item>
|
<item>@string/stats_title</item>
|
||||||
@ -3027,6 +3028,7 @@
|
|||||||
<item>@string/p_sleep_week</item>
|
<item>@string/p_sleep_week</item>
|
||||||
<item>@string/p_steps_week</item>
|
<item>@string/p_steps_week</item>
|
||||||
<item>@string/p_hrv_status</item>
|
<item>@string/p_hrv_status</item>
|
||||||
|
<item>@string/p_body_energy</item>
|
||||||
<item>@string/p_stress</item>
|
<item>@string/p_stress</item>
|
||||||
<item>@string/p_pai</item>
|
<item>@string/p_pai</item>
|
||||||
<item>@string/p_speed_zones</item>
|
<item>@string/p_speed_zones</item>
|
||||||
@ -3042,6 +3044,7 @@
|
|||||||
<item>@string/p_sleep</item>
|
<item>@string/p_sleep</item>
|
||||||
<item>@string/p_sleep_week</item>
|
<item>@string/p_sleep_week</item>
|
||||||
<item>@string/p_hrv_status</item>
|
<item>@string/p_hrv_status</item>
|
||||||
|
<item>@string/p_body_energy</item>
|
||||||
<item>@string/p_steps_week</item>
|
<item>@string/p_steps_week</item>
|
||||||
<item>@string/p_stress</item>
|
<item>@string/p_stress</item>
|
||||||
<item>@string/p_pai</item>
|
<item>@string/p_pai</item>
|
||||||
|
@ -48,8 +48,10 @@
|
|||||||
<color name="hrv_status_low" type="color">#fc5203</color>
|
<color name="hrv_status_low" type="color">#fc5203</color>
|
||||||
<color name="hrv_status_poor" type="color">#be03fc</color>
|
<color name="hrv_status_poor" type="color">#be03fc</color>
|
||||||
<color name="hrv_status_char_line_color" type="color">#d12a2a</color>
|
<color name="hrv_status_char_line_color" type="color">#d12a2a</color>
|
||||||
|
<color name="body_energy_level_color" type="color">#5ac234</color>
|
||||||
|
|
||||||
<color name="value_line_color" type="color">#858585</color>
|
<color name="value_line_color" type="color">#858585</color>
|
||||||
|
<color name="gauge_line_color" type="color">#383838</color>
|
||||||
|
|
||||||
<color name="alternate_row_background_light">#FFEDEDED</color>
|
<color name="alternate_row_background_light">#FFEDEDED</color>
|
||||||
<color name="alternate_row_background_dark">#545254</color>
|
<color name="alternate_row_background_dark">#545254</color>
|
||||||
|
@ -1455,6 +1455,9 @@
|
|||||||
<string name="hrv_status_unit">%1$d ms</string>
|
<string name="hrv_status_unit">%1$d ms</string>
|
||||||
<string name="hrv_status_baseline">%1$d-%2$d ms</string>
|
<string name="hrv_status_baseline">%1$d-%2$d ms</string>
|
||||||
<string name="hrv_status_baseline_label">Baseline</string>
|
<string name="hrv_status_baseline_label">Baseline</string>
|
||||||
|
<string name="body_energy_gained">Gained</string>
|
||||||
|
<string name="body_energy_lost">Lost</string>
|
||||||
|
<string name="body_energy_legend_level">Body Energy Level</string>
|
||||||
<string name="activity_type_biking">Biking</string>
|
<string name="activity_type_biking">Biking</string>
|
||||||
<string name="activity_type_treadmill">Treadmill</string>
|
<string name="activity_type_treadmill">Treadmill</string>
|
||||||
<string name="activity_type_exercise">Exercise</string>
|
<string name="activity_type_exercise">Exercise</string>
|
||||||
@ -2319,6 +2322,7 @@
|
|||||||
<string name="pref_header_stress">Stress</string>
|
<string name="pref_header_stress">Stress</string>
|
||||||
<string name="pref_header_spo2">Blood Oxygen</string>
|
<string name="pref_header_spo2">Blood Oxygen</string>
|
||||||
<string name="pref_header_hrv_status">HRV Status</string>
|
<string name="pref_header_hrv_status">HRV Status</string>
|
||||||
|
<string name="body_energy">Body Energy</string>
|
||||||
<string name="pref_header_sony_ambient_sound_control">Ambient Sound Control</string>
|
<string name="pref_header_sony_ambient_sound_control">Ambient Sound Control</string>
|
||||||
<string name="pref_header_sony_sound_control">Sound Control</string>
|
<string name="pref_header_sony_sound_control">Sound Control</string>
|
||||||
<string name="pref_header_sony_device_info">Device Information</string>
|
<string name="pref_header_sony_device_info">Device Information</string>
|
||||||
|
@ -106,6 +106,7 @@
|
|||||||
<item name="p_pai" type="string">pai</item>
|
<item name="p_pai" type="string">pai</item>
|
||||||
<item name="p_speed_zones" type="string">speedzones</item>
|
<item name="p_speed_zones" type="string">speedzones</item>
|
||||||
<item name="p_hrv_status" type="string">hrvstatus</item>
|
<item name="p_hrv_status" type="string">hrvstatus</item>
|
||||||
|
<item name="p_body_energy" type="string">bodyenergy</item>
|
||||||
<item name="p_live_stats" type="string">livestats</item>
|
<item name="p_live_stats" type="string">livestats</item>
|
||||||
<item name="p_spo2" type="string">spo2</item>
|
<item name="p_spo2" type="string">spo2</item>
|
||||||
<item name="p_temperature" type="string">temperature</item>
|
<item name="p_temperature" type="string">temperature</item>
|
||||||
|
Loading…
Reference in New Issue
Block a user