Add Activity List Dashboard/Summary view

This commit is contained in:
vanous
2020-11-07 17:31:15 +01:00
parent 9c90452f92
commit 551a5c1a66
22 changed files with 1246 additions and 157 deletions

View File

@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="26"
height="26"
tint="#7E7E7E"
viewportWidth="25"
viewportHeight="25"
version="1.1"
id="svg1967"
sodipodi:docname="activity_stacked.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
<metadata
id="metadata1973">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs1971" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1042"
id="namedview1969"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:zoom="16"
inkscape:cx="1.5628297"
inkscape:cy="3.351769"
inkscape:window-x="0"
inkscape:window-y="38"
inkscape:window-maximized="1"
inkscape:current-layer="g5608"
inkscape:document-rotation="0"
inkscape:snap-nodes="false">
<sodipodi:guide
position="18.131447,189.15957"
orientation="0,-1"
id="guide2551" />
<sodipodi:guide
position="6.8118842,20.241473"
orientation="1,0"
id="guide2553" />
</sodipodi:namedview>
<g
id="g5608"
transform="matrix(0.6107681,0,0,0.6107681,-0.50776959,-2.4214301)"
style="stroke-width:1.63728">
<g
id="g2806"
transform="matrix(1.8819341,0,-1.0509142,4.0780968,7.7001407,-9.1852646)"
style="stroke-width:0.591009">
<g
id="g2123"
transform="matrix(1,0,0,0.33594705,0,3.7327618)"
style="stroke-width:1.01966;stroke-miterlimit:4;stroke-dasharray:none">
<path
fill="#000000"
d="m 12,18 a 6,6 0 0 1 -6,-6 6,6 0 0 1 6,-6 6,6 0 0 1 6,6 6,6 0 0 1 -6,6 M 20,15.31 23.31,12 20,8.69 V 4 H 15.31 L 12,0.69 8.69,4 H 4 V 8.69 L 0.69,12 4,15.31 V 20 H 8.69 L 12,23.31 15.31,20 H 20 Z"
id="path1965"
style="stroke-width:1.01966;stroke-miterlimit:4;stroke-dasharray:none" />
<path
fill="currentColor"
d="m 4.4762317,12.388718 h 3.561751 l 2.0837443,-5.0286723 1.932068,5.4893343 1.823648,-2.726785 h 6.48905 l -0.488068,1.38717 H 14.61543 l -2.938854,4.509156 -1.60202,-4.54569 -0.9505983,2.403348 -3.506487,-4.01e-4 z"
id="path2361"
sodipodi:nodetypes="ccccccccccccc"
style="stroke-width:1.01966;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:transform-center-x="1.0957646"
inkscape:transform-center-y="-1.4792654" />
</g>
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.591009;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000"
d="m 3.9815232,10.751128 v 0.490234 h 4.6484375 l 3.3515623,1.126953 3.349609,-1.126953 h 4.650391 v -0.490234 h -4.730469 l -3.269531,1.097656 -3.2714842,-1.097656 z"
id="path2783" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.591009;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000"
d="m 3.9892109,11.549912 v 0.490234 h 4.6503907 l 3.3496094,1.126953 3.349609,-1.126953 h 4.650391 v -0.490234 h -4.730469 l -3.269531,1.097656 -3.2695313,-1.097656 z"
id="path2787" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="24"
viewBox="0 0 24 24"
width="24"
version="1.1"
id="svg6"
sodipodi:docname="ic_intensity_hollow.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1042"
id="namedview8"
showgrid="false"
inkscape:zoom="32.125"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="38"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<path
d="M0 0h24v24H0V0z"
fill="none"
id="path2" />
<path
d="m 13.5,0.67 c 0,0 0.74,2.65 0.74,4.8 0,2.06 -1.35,3.73 -3.41,3.73 C 8.76,9.2 7.2,7.53 7.2,5.47 L 7.23,5.11 C 5.21,7.51 4,10.62 4,14 c 0,4.42 3.58,8 8,8 4.42,0 8,-3.58 8,-8 C 20,8.61 17.41,3.8 13.5,0.67 Z M 12,20 C 8.69,20 6,17.31 6,14 6,12.47 6.3,10.96 6.86,9.57 c 1.01,1.01 2.41,1.63 3.97,1.63 2.66,0 4.75,-1.83 5.28,-4.43 1.23,2.2 1.89,4.67 1.89,7.23 0,3.31 -2.69,6 -6,6 z"
id="path4"
sodipodi:nodetypes="cssccssscsscscss" />
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="24"
height="24"
viewBox="0 0 24 24"
id="svg4"
sodipodi:docname="ic_shoe_prints_many.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1042"
id="namedview6"
showgrid="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:zoom="16.0625"
inkscape:cx="20.274468"
inkscape:cy="17.69706"
inkscape:window-x="0"
inkscape:window-y="38"
inkscape:window-maximized="1"
inkscape:current-layer="svg4"
inkscape:document-rotation="0">
<inkscape:grid
type="xygrid"
id="grid880" />
<sodipodi:guide
position="16,24"
orientation="0,-1"
id="guide882" />
</sodipodi:namedview>
<path
d="m 6.4801431,14.379265 c 0.3823082,1.031063 0.3416371,2.10404 -0.8052874,2.531554 C 3.3159331,17.807761 2.787209,15.452241 2.7546721,15.334884 l 3.725471,-0.955619 M 2.3886324,13.700271 5.9026138,12.80333 c -0.1545501,-0.880176 0.081342,-1.760353 0.081342,-2.799798 0,-1.4082825 -1.0818507,-4.1661681 -2.8063045,-3.7218887 -1.9684802,0.5029579 -2.2531778,2.7578856 -2.1799698,3.8476277 0.097611,1.089742 1.3340114,3.420113 1.3909509,3.571 m 9.8749386,7.494073 C 12.239171,21.320083 11.70231,23.66722 9.343387,22.778661 8.204597,22.342764 8.155792,21.269787 8.5381,20.238724 l 3.725471,0.95562 m 1.748856,-5.197232 c 0.08134,-1.089742 -0.195221,-3.353052 -2.171836,-3.85601 -1.716319,-0.461045 -2.79817,2.313606 -2.79817,3.730271 0,1.031064 0.227758,1.91124 0.08948,2.791416 l 3.497713,0.896942 c 0.06507,-0.150888 1.293341,-2.481259 1.382817,-3.562619 z"
id="path2"
style="stroke-width:0.999999" />
<path
d="M 14.730838,7.4902842 C 14.986006,8.2347895 14.958862,9.00956 14.193361,9.3182576 12.618928,9.9659169 12.266038,8.2650539 12.244321,8.1803133 L 14.730838,7.4902842 M 12.000011,7 14.345374,6.3523407 c -0.103162,-0.6355538 0.05428,-1.2711071 0.05428,-2.0216657 0,-1.0168858 -0.722068,-3.0082871 -1.873034,-2.6874837 -1.313836,0.3631733 -1.503856,1.9914011 -1.454993,2.778277 C 11.136774,5.2083444 11.961996,6.8910478 12,7 m 6.590901,5.411286 c -0.0162,0.09079 -0.374605,1.785603 -1.949038,1.143996 -0.760065,-0.314751 -0.79264,-1.089521 -0.537473,-1.834026 l 2.486519,0.69003 m 1.16726,-3.7527936 c 0.05428,-0.7868766 -0.130305,-2.4211567 -1.449564,-2.78433 -1.145536,-0.3329091 -1.867604,1.670598 -1.867604,2.6935367 0,0.7445054 0.152015,1.3800583 0.05971,2.0156119 l 2.334511,0.647659 c 0.04345,-0.108954 0.863221,-1.7916547 0.922943,-2.5724776 z"
id="path2-3"
style="stroke-width:0.999998" />
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -1,59 +1,273 @@
package nodomain.freeyourgadget.gadgetbridge.activities.charts; package nodomain.freeyourgadget.gadgetbridge.activities.charts;
import android.content.Context; import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.github.mikephil.charting.charts.PieChart;
import com.github.mikephil.charting.data.PieData;
import com.github.mikephil.charting.data.PieDataSet;
import com.github.mikephil.charting.data.PieEntry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.adapter.AbstractActivityListingAdapter; import nodomain.freeyourgadget.gadgetbridge.adapter.AbstractActivityListingAdapter;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySession;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils; import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
public class ActivityListingAdapter extends AbstractActivityListingAdapter<StepAnalysis.StepSession> { public class ActivityListingAdapter extends AbstractActivityListingAdapter<ActivitySession> {
public static final String ACTIVE_STEPS_CHART_COLOR = "#3498db";
public static final String DISTANCE_CHART_COLOR = "#f1c40f";
public static final String ACTIVE_TIME_CHART_COLOR = "#e74c3c";
protected static final Logger LOG = LoggerFactory.getLogger(AbstractWeekChartFragment.class);
private final int SESSION_SUMMARY = ActivitySession.SESSION_SUMMARY;
ActivityUser activityUser = new ActivityUser();
int stepsGoal = activityUser.getStepsGoal();
int distanceMeters = activityUser.getDistanceMeters();
long activeTimeMillis = activityUser.getActiveTimeMinutes() * 60 * 1000L;
public ActivityListingAdapter(Context context) { public ActivityListingAdapter(Context context) {
super(context); super(context);
} }
@Override @Override
protected String getDateLabel(StepAnalysis.StepSession item) { protected View fill_dashboard(ActivitySession item, int position, View view, ViewGroup parent, Context context) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.activity_list_dashboard_item, parent, false);
PieChart ActiveStepsChart;
PieChart DistanceChart;
PieChart ActiveTimeChart;
ActiveStepsChart = view.findViewById(R.id.activity_dashboard_piechart1);
setUpChart(ActiveStepsChart);
setStepsData(item, ActiveStepsChart, context);
DistanceChart = view.findViewById(R.id.activity_dashboard_piechart2);
setUpChart(DistanceChart);
setDistanceData(item, DistanceChart, context);
ActiveTimeChart = view.findViewById(R.id.activity_dashboard_piechart3);
setUpChart(ActiveTimeChart);
setDurationData(item, ActiveTimeChart, context);
TextView stepLabel = view.findViewById(R.id.line_layout_step_label);
TextView stepTotalLabel = view.findViewById(R.id.line_layout_total_step_label);
TextView distanceLabel = view.findViewById(R.id.line_layout_distance_label);
TextView hrLabel = view.findViewById(R.id.heartrate_widget_label);
TextView intensityLabel = view.findViewById(R.id.intensity_widget_label);
TextView intensity2Label = view.findViewById(R.id.line_layout_intensity2_label);
TextView durationLabel = view.findViewById(R.id.line_layout_duration_label);
TextView sessionCountLabel = view.findViewById(R.id.line_layout_count_label);
LinearLayout durationLayout = view.findViewById(R.id.line_layout_duration);
LinearLayout countLayout = view.findViewById(R.id.line_layout_count);
View hrLayout = view.findViewById(R.id.heartrate_widget_icon);
LinearLayout stepsLayout = view.findViewById(R.id.line_layout_step);
LinearLayout stepsTotalLayout = view.findViewById(R.id.line_layout_total_step);
LinearLayout distanceLayout = view.findViewById(R.id.line_layout_distance);
View intensityLayout = view.findViewById(R.id.intensity_widget_icon);
View intensity2Layout = view.findViewById(R.id.line_layout_intensity2);
stepLabel.setText(getStepLabel(item));
stepTotalLabel.setText(getStepTotalLabel(item));
distanceLabel.setText(getDistanceLabel(item));
hrLabel.setText(getHrLabel(item));
intensityLabel.setText(getIntensityLabel(item));
intensity2Label.setText(getIntensityLabel(item));
durationLabel.setText(getDurationLabel(item));
sessionCountLabel.setText(getSessionCountLabel(item));
if (!hasHR(item)) {
hrLayout.setVisibility(View.GONE);
hrLabel.setVisibility(View.GONE);
} else {
hrLayout.setVisibility(View.VISIBLE);
hrLabel.setVisibility(View.VISIBLE);
}
if (!hasIntensity(item)) {
intensityLayout.setVisibility(View.GONE);
intensity2Layout.setVisibility(View.GONE);
intensityLabel.setVisibility(View.GONE);
intensity2Label.setVisibility(View.GONE);
} else {
intensityLayout.setVisibility(View.VISIBLE);
intensity2Layout.setVisibility(View.VISIBLE);
intensityLabel.setVisibility(View.VISIBLE);
intensity2Label.setVisibility(View.VISIBLE);
}
if (!hasDistance(item)) {
distanceLayout.setVisibility(View.GONE);
} else {
distanceLayout.setVisibility(View.VISIBLE);
}
if (!hasSteps(item)) {
stepsLayout.setVisibility(View.GONE);
} else {
stepsLayout.setVisibility(View.VISIBLE);
}
if (!hasTotalSteps(item)) {
stepsTotalLayout.setVisibility(View.GONE);
countLayout.setVisibility(View.GONE);
durationLayout.setVisibility(View.GONE);
} else {
stepsTotalLayout.setVisibility(View.VISIBLE);
countLayout.setVisibility(View.VISIBLE);
durationLayout.setVisibility(View.VISIBLE);
}
return view;
}
private void setStepsData(ActivitySession item, PieChart DashboardChart, Context context) {
ArrayList<PieEntry> entries = new ArrayList<>();
int steps = item.getActiveSteps();
entries.add(new PieEntry((float) steps));
if (steps < stepsGoal) {
entries.add(new PieEntry((float) (stepsGoal - steps)));
}
DashboardChart.setCenterText(String.format("%d%%\n%s", (int) (steps * 100 / stepsGoal), context.getString(R.string.activity_list_summary_active_steps)));
PieDataSet dataSet = new PieDataSet(entries, "");
dataSet.setSliceSpace(0f);
dataSet.setSelectionShift(5f);
dataSet.setColors(Color.parseColor(ACTIVE_STEPS_CHART_COLOR), Color.LTGRAY);
PieData data = new PieData(dataSet);
data.setValueTextSize(0f);
data.setValueTextColor(Color.WHITE);
DashboardChart.setData(data);
DashboardChart.invalidate();
}
private void setDistanceData(ActivitySession item, PieChart DashboardChart, Context context) {
ArrayList<PieEntry> entries = new ArrayList<>();
float distance = item.getDistance();
entries.add(new PieEntry(distance));
if (distance < distanceMeters) {
entries.add(new PieEntry((float) (distanceMeters - distance)));
}
DashboardChart.setCenterText(String.format("%d%%\n%s", (int) (distance * 100 / distanceMeters), context.getString(R.string.distance)));
PieDataSet dataSet = new PieDataSet(entries, "");
dataSet.setSliceSpace(0f);
dataSet.setSelectionShift(5f);
dataSet.setColors(Color.parseColor(DISTANCE_CHART_COLOR), Color.LTGRAY);
PieData data = new PieData(dataSet);
data.setValueTextSize(0f);
data.setValueTextColor(Color.WHITE);
DashboardChart.setData(data);
DashboardChart.invalidate();
}
private void setDurationData(ActivitySession item, PieChart DashboardChart, Context context) {
ArrayList<PieEntry> entries = new ArrayList<>();
long duration = item.getEndTime().getTime() - item.getStartTime().getTime();
entries.add(new PieEntry((float) duration));
if (duration < activeTimeMillis) {
entries.add(new PieEntry((float) (activeTimeMillis - duration)));
}
DashboardChart.setCenterText(String.format("%d%%\n%s", (int) (duration * 100 / activeTimeMillis), context.getString(R.string.activity_list_summary_active_time)));
PieDataSet dataSet = new PieDataSet(entries, "");
dataSet.setSliceSpace(0f);
dataSet.setSelectionShift(5f);
dataSet.setColors(Color.parseColor(ACTIVE_TIME_CHART_COLOR), Color.LTGRAY);
PieData data = new PieData(dataSet);
data.setValueTextSize(0f);
data.setValueTextColor(Color.WHITE);
DashboardChart.setData(data);
DashboardChart.invalidate();
}
private void setUpChart(PieChart DashboardChart) {
DashboardChart.setNoDataText("");
DashboardChart.getLegend().setEnabled(false);
DashboardChart.setDrawHoleEnabled(true);
DashboardChart.setHoleColor(Color.WHITE);
DashboardChart.getDescription().setText("");
DashboardChart.setTransparentCircleColor(Color.WHITE);
DashboardChart.setTransparentCircleAlpha(110);
DashboardChart.setHoleRadius(70f);
DashboardChart.setTransparentCircleRadius(75f);
DashboardChart.setDrawCenterText(true);
DashboardChart.setRotationEnabled(true);
DashboardChart.setHighlightPerTapEnabled(true);
DashboardChart.setCenterTextOffset(0, 0);
}
@Override
protected String getDateLabel(ActivitySession item) {
return ""; return "";
} }
@Override @Override
protected boolean hasGPS(StepAnalysis.StepSession item) { protected boolean hasGPS(ActivitySession item) {
return false; return false;
} }
@Override @Override
protected boolean hasDate(StepAnalysis.StepSession item) { protected boolean hasDate(ActivitySession item) {
return false; return false;
} }
@Override @Override
protected String getTimeFrom(StepAnalysis.StepSession item) { protected String getTimeFrom(ActivitySession item) {
Date time = item.getStartTime(); Date time = item.getStartTime();
return DateTimeUtils.formatTime(time.getHours(), time.getMinutes()); return DateTimeUtils.formatTime(time.getHours(), time.getMinutes());
} }
@Override @Override
protected String getTimeTo(StepAnalysis.StepSession item) { protected String getTimeTo(ActivitySession item) {
Date time = item.getEndTime(); Date time = item.getEndTime();
return DateTimeUtils.formatTime(time.getHours(), time.getMinutes()); return DateTimeUtils.formatTime(time.getHours(), time.getMinutes());
} }
@Override @Override
protected String getActivityName(StepAnalysis.StepSession item) { protected String getActivityName(ActivitySession item) {
return ActivityKind.asString(item.getActivityKind(), getContext()); return ActivityKind.asString(item.getActivityKind(), getContext());
} }
@Override @Override
protected String getStepLabel(StepAnalysis.StepSession item) { protected String getStepLabel(ActivitySession item) {
return String.valueOf(item.getSteps()); return String.valueOf(item.getActiveSteps());
} }
@Override @Override
protected String getDistanceLabel(StepAnalysis.StepSession item) { protected String getDistanceLabel(ActivitySession item) {
float distance = item.getDistance(); float distance = item.getDistance();
String unit = "###m"; String unit = "###m";
if (distance > 2000) { if (distance > 2000) {
@@ -61,69 +275,74 @@ public class ActivityListingAdapter extends AbstractActivityListingAdapter<StepA
unit = "###.#km"; unit = "###.#km";
} }
DecimalFormat df = new DecimalFormat(unit); DecimalFormat df = new DecimalFormat(unit);
//DecimalFormatSymbols symbols = df.getDecimalFormatSymbols();
//symbols.setGroupingSeparator(' ');
return df.format(distance); return df.format(distance);
} }
@Override @Override
protected String getHrLabel(StepAnalysis.StepSession item) { protected String getHrLabel(ActivitySession item) {
return String.valueOf(item.getHeartRateAverage()); return String.valueOf(item.getHeartRateAverage());
} }
@Override @Override
protected String getIntensityLabel(StepAnalysis.StepSession item) { protected String getIntensityLabel(ActivitySession item) {
DecimalFormat df = new DecimalFormat("###.#"); DecimalFormat df = new DecimalFormat("###");
return df.format(item.getIntensity()); return df.format(item.getIntensity());
} }
@Override @Override
protected String getDurationLabel(StepAnalysis.StepSession item) { protected String getDurationLabel(ActivitySession item) {
long duration = item.getEndTime().getTime() - item.getStartTime().getTime(); long duration = item.getEndTime().getTime() - item.getStartTime().getTime();
return DateTimeUtils.formatDurationHoursMinutes(duration, TimeUnit.MILLISECONDS); return DateTimeUtils.formatDurationHoursMinutes(duration, TimeUnit.MILLISECONDS);
} }
@Override @Override
public boolean hasHR(StepAnalysis.StepSession item) { protected String getSessionCountLabel(ActivitySession item) {
if (item.getHeartRateAverage() > 0) { return String.valueOf(item.getSessionCount());
return true;
} else {
return false;
}
} }
@Override @Override
public boolean hasIntensity(StepAnalysis.StepSession item) { public boolean hasHR(ActivitySession item) {
if (item.getIntensity() > 0) { return item.getHeartRateAverage() > 0;
return true;
} else {
return false;
}
} }
@Override @Override
protected boolean hasDistance(StepAnalysis.StepSession item) { public boolean hasIntensity(ActivitySession item) {
if (item.getDistance() > 0) { return item.getIntensity() > 0;
return true;
} else {
return false;
}
} }
@Override @Override
protected boolean hasSteps(StepAnalysis.StepSession item) { protected boolean hasDistance(ActivitySession item) {
if (item.getSteps() > 0) { return item.getDistance() > 0;
return true;
} else {
return false;
}
} }
@Override
protected boolean hasSteps(ActivitySession item) {
return item.getActiveSteps() > 0;
}
@Override @Override
protected int getIcon(StepAnalysis.StepSession item) { protected boolean hasTotalSteps(ActivitySession item) {
return item.getTotalDaySteps() > 0;
}
@Override
protected boolean isSummary(ActivitySession item) {
int sessionType = item.getSessionType();
return sessionType == SESSION_SUMMARY;
}
@Override
protected boolean isEmptySummary(ActivitySession item) {
return item.getIsEmptySummary();
}
@Override
protected String getStepTotalLabel(ActivitySession item) {
return String.valueOf(item.getTotalDaySteps());
}
@Override
protected int getIcon(ActivitySession item) {
return ActivityKind.getIconId(item.getActivityKind()); return ActivityKind.getIconId(item.getActivityKind());
} }
} }

View File

@@ -42,14 +42,14 @@ import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySession;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils; import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
public class ActivityListingChartFragment extends AbstractChartFragment { public class ActivityListingChartFragment extends AbstractChartFragment {
protected static final Logger LOG = LoggerFactory.getLogger(ActivityListingChartFragment.class); protected static final Logger LOG = LoggerFactory.getLogger(ActivityListingChartFragment.class);
int tsDateFrom; int tsDateFrom;
private View rootView; private View rootView;
private List<? extends ActivitySample> activitySamples;
private ActivityListingAdapter stepListAdapter; private ActivityListingAdapter stepListAdapter;
private TextView stepsDateView; private TextView stepsDateView;
@@ -57,18 +57,16 @@ public class ActivityListingChartFragment extends AbstractChartFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_steps_list, container, false); rootView = inflater.inflate(R.layout.fragment_steps_list, container, false);
getChartsHost().enableSwipeRefresh(false);
ListView stepsList = rootView.findViewById(R.id.itemListView); ListView stepsList = rootView.findViewById(R.id.itemListView);
View headerView = inflater.inflate(R.layout.heartrate_average_widget,null, false);
stepsList.addHeaderView(headerView);
stepListAdapter = new ActivityListingAdapter(getContext()); stepListAdapter = new ActivityListingAdapter(getContext());
stepsList.setAdapter(stepListAdapter); stepsList.setAdapter(stepListAdapter);
stepsDateView = rootView.findViewById(R.id.stepsDateView); stepsDateView = rootView.findViewById(R.id.stepsDateView);
refresh(); refresh();
return rootView; return rootView;
} }
@Override @Override
public String getTitle() { public String getTitle() {
return "Steps list"; return "Steps list";
@@ -86,36 +84,40 @@ public class ActivityListingChartFragment extends AbstractChartFragment {
} }
} }
@Override @Override
protected ChartsData refreshInBackground(ChartsHost chartsHost, DBHandler db, GBDevice device) { protected ChartsData refreshInBackground(ChartsHost chartsHost, DBHandler db, GBDevice device) {
//trying to fit found peg into square hole of the Gb Charts fragment system List<? extends ActivitySample> activitySamples;
//get the data
activitySamples = getSamples(db, device); activitySamples = getSamples(db, device);
return null; List<ActivitySession> stepSessions = null;
StepAnalysis stepAnalysis = new StepAnalysis();
boolean isEmptySummary = false;
if (activitySamples != null) {
stepSessions = stepAnalysis.calculateStepSessions(activitySamples);
if (stepSessions.toArray().length == 0) {
isEmptySummary = true;
}
stepSessions = stepAnalysis.calculateSummary(stepSessions, isEmptySummary);
}
return new MyChartsData(stepSessions);
} }
@Override @Override
protected void updateChartsnUIThread(ChartsData chartsData) { protected void updateChartsnUIThread(ChartsData chartsData) {
//top displays selected date MyChartsData mcd = (MyChartsData) chartsData;
stepsDateView.setText(DateTimeUtils.formatDate(new Date(tsDateFrom * 1000L))); if (mcd.getStepSessions().toArray().length == 0) {
//calculate active sessions getChartsHost().enableSwipeRefresh(true); //try to enable pull to refresh, might be needed
StepAnalysis stepAnalysis = new StepAnalysis(); } else {
if (activitySamples != null) { getChartsHost().enableSwipeRefresh(false); //disable pull to refresh as it collides with swipable view
List<StepAnalysis.StepSession> stepSessions = stepAnalysis.calculateStepSessions(activitySamples);
if (stepSessions.toArray().length == 0) {
stepSessions = create_empty_record();
getChartsHost().enableSwipeRefresh(true); //try to enable pull to refresh, might be needed
} else {
getChartsHost().enableSwipeRefresh(false); //disable pull to refresh as it collides with swipable view
}
//push to the adapter
stepListAdapter.setItems(stepSessions, true);
} }
stepsDateView.setText(DateTimeUtils.formatDate(new Date(tsDateFrom * 1000L)));
stepListAdapter.setItems(mcd.getStepSessions(), true);
} }
@Override @Override
protected void renderCharts() { protected void renderCharts() {
} }
@Override @Override
@@ -135,16 +137,17 @@ public class ActivityListingChartFragment extends AbstractChartFragment {
return getAllSamples(db, device, tsFrom, tsTo); return getAllSamples(db, device, tsFrom, tsTo);
} }
private List<StepAnalysis.StepSession> create_empty_record() { private static class MyChartsData extends ChartsData {
//have an "Unknown Activity" in the list in case there are no active sessions private final List<ActivitySession> stepSessions;
List<StepAnalysis.StepSession> result = new ArrayList<>();
int tsTo = tsDateFrom + 24 * 60 * 60 - 1; MyChartsData(List<ActivitySession> stepSessions) {
if (DateUtils.isToday(tsDateFrom * 1000L)) { this.stepSessions = stepSessions;
Calendar day = Calendar.getInstance(); }
day.set(Calendar.SECOND, 0);
tsTo = (int) (day.getTimeInMillis() / 1000); public List<ActivitySession> getStepSessions() {
return stepSessions;
} }
result.add(new StepAnalysis.StepSession(new Date(tsDateFrom * 1000L), new Date(tsTo * 1000L), 0, 0, 0, 0, ActivityKind.TYPE_UNKNOWN));
return result;
} }
} }

View File

@@ -21,7 +21,6 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Color; import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.util.Pair;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -244,7 +243,7 @@ public class SleepChartFragment extends AbstractChartFragment {
int min = Collections.min(heartRateValues); int min = Collections.min(heartRateValues);
int max = Collections.max(heartRateValues); int max = Collections.max(heartRateValues);
int count = heartRateValues.toArray().length; int count = heartRateValues.toArray().length;
float sum = calculateHRSum(heartRateValues); float sum = calculateSumOfInts(heartRateValues);
float average = sum / count; float average = sum / count;
return Triple.of(average, min, max); return Triple.of(average, min, max);
} }
@@ -257,7 +256,7 @@ public class SleepChartFragment extends AbstractChartFragment {
return result; return result;
} }
private float calculateHRSum(List<Integer> samples) { private float calculateSumOfInts(List<Integer> samples) {
float result = 0; float result = 0;
for (Integer sample : samples) { for (Integer sample : samples) {
result += sample; result += sample;

View File

@@ -28,12 +28,14 @@ import nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser; import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySession;
public class StepAnalysis { public class StepAnalysis {
protected static final Logger LOG = LoggerFactory.getLogger(StepAnalysis.class); protected static final Logger LOG = LoggerFactory.getLogger(StepAnalysis.class);
private int totalDailySteps = 0;
public List<StepSession> calculateStepSessions(List<? extends ActivitySample> samples) { public List<ActivitySession> calculateStepSessions(List<? extends ActivitySample> samples) {
List<StepSession> result = new ArrayList<>(); List<ActivitySession> result = new ArrayList<>();
ActivityUser activityUser = new ActivityUser(); ActivityUser activityUser = new ActivityUser();
double STEP_LENGTH_M; double STEP_LENGTH_M;
final int MIN_SESSION_LENGTH = 60 * GBApplication.getPrefs().getInt("chart_list_min_session_length", 5); final int MIN_SESSION_LENGTH = 60 * GBApplication.getPrefs().getInt("chart_list_min_session_length", 5);
@@ -41,6 +43,7 @@ public class StepAnalysis {
final int MIN_STEPS_PER_MINUTE = GBApplication.getPrefs().getInt("chart_list_min_steps_per_minute", 40); final int MIN_STEPS_PER_MINUTE = GBApplication.getPrefs().getInt("chart_list_min_steps_per_minute", 40);
int stepLengthCm = activityUser.getStepLengthCm(); int stepLengthCm = activityUser.getStepLengthCm();
int heightCm = activityUser.getHeightCm(); int heightCm = activityUser.getHeightCm();
totalDailySteps = 0;
if (stepLengthCm == 0 && heightCm != 0) { if (stepLengthCm == 0 && heightCm != 0) {
STEP_LENGTH_M = heightCm * 0.43 * 0.01; STEP_LENGTH_M = heightCm * 0.43 * 0.01;
@@ -68,6 +71,11 @@ public class StepAnalysis {
HeartRateUtils heartRateUtilsInstance = HeartRateUtils.getInstance(); HeartRateUtils heartRateUtilsInstance = HeartRateUtils.getInstance();
for (ActivitySample sample : samples) { for (ActivitySample sample : samples) {
int steps = sample.getSteps();
if (steps > 0) {
totalDailySteps += steps;
}
if (sample.getKind() != ActivityKind.TYPE_SLEEP //anything but sleep counts if (sample.getKind() != ActivityKind.TYPE_SLEEP //anything but sleep counts
&& !(sample instanceof TrailingActivitySample)) { //trailing samples have wrong date and make trailing activity have 0 duration && !(sample instanceof TrailingActivitySample)) { //trailing samples have wrong date and make trailing activity have 0 duration
if (heartRateUtilsInstance.isValidHeartRateValue(sample.getHeartRate())) { if (heartRateUtilsInstance.isValidHeartRateValue(sample.getHeartRate())) {
@@ -119,7 +127,7 @@ public class StepAnalysis {
float distance = (float) (activeSteps * STEP_LENGTH_M); float distance = (float) (activeSteps * STEP_LENGTH_M);
sessionEnd = new Date((sample.getTimestamp() - durationSinceLastActiveStep) * 1000L); sessionEnd = new Date((sample.getTimestamp() - durationSinceLastActiveStep) * 1000L);
activityKind = detect_activity_kind(session_length, activeSteps, heartRateAverage, activeIntensity); activityKind = detect_activity_kind(session_length, activeSteps, heartRateAverage, activeIntensity);
result.add(new StepSession(sessionStart, sessionEnd, activeSteps, heartRateAverage, activeIntensity, distance, activityKind)); result.add(new ActivitySession(sessionStart, sessionEnd, activeSteps, heartRateAverage, activeIntensity, distance, activityKind));
} }
sessionStart = null; sessionStart = null;
} }
@@ -139,12 +147,69 @@ public class StepAnalysis {
float distance = (float) (activeSteps * STEP_LENGTH_M); float distance = (float) (activeSteps * STEP_LENGTH_M);
sessionEnd = getDateFromSample(previousSample); sessionEnd = getDateFromSample(previousSample);
activityKind = detect_activity_kind(session_length, activeSteps, heartRateAverage, activeIntensity); activityKind = detect_activity_kind(session_length, activeSteps, heartRateAverage, activeIntensity);
result.add(new StepSession(sessionStart, sessionEnd, activeSteps, heartRateAverage, activeIntensity, distance, activityKind)); result.add(new ActivitySession(sessionStart, sessionEnd, activeSteps, heartRateAverage, activeIntensity, distance, activityKind));
} }
} }
return result; return result;
} }
public List<ActivitySession> calculateSummary(List<ActivitySession> sessions, boolean empty) {
HeartRateUtils heartRateUtilsInstance = HeartRateUtils.getInstance();
Date startTime = null;
Date endTime = null;
int stepsSum = 0;
int heartRateAverage = 0;
List<Integer> heartRateSum = new ArrayList<>();
int distanceSum = 0;
float intensitySum = 0;
int sessionCount;
int durationSum = 0;
for (ActivitySession session : sessions) {
startTime = session.getStartTime();
endTime = session.getEndTime();
durationSum += endTime.getTime() - startTime.getTime();
stepsSum += session.getActiveSteps();
distanceSum += session.getDistance();
heartRateSum.add(session.getHeartRateAverage());
intensitySum += session.getIntensity();
}
sessionCount = sessions.toArray().length;
if (heartRateSum.toArray().length > 0) {
heartRateAverage = calculateSumOfInts(heartRateSum) / heartRateSum.toArray().length;
}
if (!heartRateUtilsInstance.isValidHeartRateValue(heartRateAverage)) {
heartRateAverage = 0;
}
startTime = new Date(0);
endTime = new Date(durationSum);
ActivitySession stepSessionSummary = new ActivitySession(startTime, endTime,
stepsSum, heartRateAverage, intensitySum, distanceSum, 0);
stepSessionSummary.setSessionCount(sessionCount);
stepSessionSummary.setSessionType(ActivitySession.SESSION_SUMMARY);
stepSessionSummary.setEmptySummary(empty);
stepSessionSummary.setTotalDaySteps(totalDailySteps);
List<ActivitySession> newList = new ArrayList<>();
newList.add(stepSessionSummary);
newList.addAll(sessions);
return newList;
}
private int calculateSumOfInts(List<Integer> samples) {
int result = 0;
for (Integer sample : samples) {
result += sample;
}
return result;
}
private int detect_activity_kind(int session_length, int activeSteps, int heartRateAverage, float intensity) { private int detect_activity_kind(int session_length, int activeSteps, int heartRateAverage, float intensity) {
final int MIN_STEPS_PER_MINUTE_FOR_RUN = GBApplication.getPrefs().getInt("chart_list_min_steps_per_minute_for_run", 120); final int MIN_STEPS_PER_MINUTE_FOR_RUN = GBApplication.getPrefs().getInt("chart_list_min_steps_per_minute_for_run", 120);
int spm = (int) (activeSteps / (session_length / 60)); int spm = (int) (activeSteps / (session_length / 60));
@@ -160,61 +225,7 @@ public class StepAnalysis {
return ActivityKind.TYPE_ACTIVITY; return ActivityKind.TYPE_ACTIVITY;
} }
private boolean isStep(ActivitySample sample) {
return sample.getKind() == ActivityKind.TYPE_WALKING || sample.getKind() == ActivityKind.TYPE_RUNNING || sample.getKind() == ActivityKind.TYPE_ACTIVITY;
}
private Date getDateFromSample(ActivitySample sample) { private Date getDateFromSample(ActivitySample sample) {
return new Date(sample.getTimestamp() * 1000L); return new Date(sample.getTimestamp() * 1000L);
} }
public static class StepSession {
private final Date startTime;
private final Date endTime;
private final int steps;
private final int heartRateAverage;
private final float intensity;
private final float distance;
private final int activityKind;
StepSession(Date startTime,
Date endTime,
int steps, int heartRateAverage, float intensity, float distance, int activityKind) {
this.startTime = startTime;
this.endTime = endTime;
this.steps = steps;
this.heartRateAverage = heartRateAverage;
this.intensity = intensity;
this.distance = distance;
this.activityKind = activityKind;
}
public Date getStartTime() {
return startTime;
}
public Date getEndTime() {
return endTime;
}
public int getSteps() {
return steps;
}
public int getHeartRateAverage() {
return heartRateAverage;
}
public int getActivityKind() {
return activityKind;
}
public float getIntensity() {
return intensity;
}
public float getDistance() {
return distance;
}
}
} }

View File

@@ -35,6 +35,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.StepAnalysis;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySession;
/** /**
* Adapter for displaying generic ItemWithDetails instances. * Adapter for displaying generic ItemWithDetails instances.
@@ -43,6 +45,7 @@ public abstract class AbstractActivityListingAdapter<T> extends ArrayAdapter<T>
private final Context context; private final Context context;
private final List<T> items; private final List<T> items;
private final int SESSION_SUMMARY = ActivitySession.SESSION_SUMMARY;
private int backgroundColor = 0; private int backgroundColor = 0;
private int alternateColor = 0; private int alternateColor = 0;
private boolean zebraStripes = true; private boolean zebraStripes = true;
@@ -67,15 +70,27 @@ public abstract class AbstractActivityListingAdapter<T> extends ArrayAdapter<T>
return typedValue.data; return typedValue.data;
} }
@Override @Override
public View getView(int position, View view, ViewGroup parent) { public View getView(int position, View view, ViewGroup parent) {
T item = getItem(position); T item = getItem(position);
view = null; //this is ugly (probably we get no recycling), but it is required to keep the layout nice. We have only few items, so this should be OK.
if (view == null) { if (isSummary(item)) {
LayoutInflater inflater = (LayoutInflater) context view = fill_dashboard(item, position, view, parent, context);
.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } else {
view = inflater.inflate(R.layout.activity_list_item, parent, false); view = fill_item(item, position, view, parent);
} }
return view;
}
private View fill_item(T item, int position, View view, ViewGroup parent) {
view = null;
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.activity_list_item, parent, false);
TextView timeFrom = view.findViewById(R.id.line_layout_time_from); TextView timeFrom = view.findViewById(R.id.line_layout_time_from);
TextView timeTo = view.findViewById(R.id.line_layout_time_to); TextView timeTo = view.findViewById(R.id.line_layout_time_to);
TextView activityName = view.findViewById(R.id.line_layout_activity_name); TextView activityName = view.findViewById(R.id.line_layout_activity_name);
@@ -160,6 +175,9 @@ public abstract class AbstractActivityListingAdapter<T> extends ArrayAdapter<T>
return view; return view;
} }
protected abstract View fill_dashboard(T item, int position, View view, ViewGroup parent, Context context);
protected abstract String getDateLabel(T item); protected abstract String getDateLabel(T item);
protected abstract boolean hasGPS(T item); protected abstract boolean hasGPS(T item);
@@ -182,6 +200,8 @@ public abstract class AbstractActivityListingAdapter<T> extends ArrayAdapter<T>
protected abstract String getDurationLabel(T item); protected abstract String getDurationLabel(T item);
protected abstract String getSessionCountLabel(T item);
protected abstract boolean hasHR(T item); protected abstract boolean hasHR(T item);
protected abstract boolean hasIntensity(T item); protected abstract boolean hasIntensity(T item);
@@ -190,6 +210,14 @@ public abstract class AbstractActivityListingAdapter<T> extends ArrayAdapter<T>
protected abstract boolean hasSteps(T item); protected abstract boolean hasSteps(T item);
protected abstract boolean hasTotalSteps(T item);
protected abstract boolean isSummary(T item);
protected abstract boolean isEmptySummary(T item);
protected abstract String getStepTotalLabel(T item);
public void setZebraStripes(boolean enable) { public void setZebraStripes(boolean enable) {
zebraStripes = enable; zebraStripes = enable;
} }

View File

@@ -18,6 +18,8 @@ package nodomain.freeyourgadget.gadgetbridge.adapter;
import android.content.Context; import android.content.Context;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast; import android.widget.Toast;
import java.util.Calendar; import java.util.Calendar;
@@ -134,6 +136,11 @@ public class ActivitySummariesAdapter extends AbstractActivityListingAdapter<Bas
this.deviceFilter = device; this.deviceFilter = device;
} }
@Override
protected View fill_dashboard(BaseActivitySummary item, int position, View view, ViewGroup parent, Context context) {
return null;
}
@Override @Override
protected String getDateLabel(BaseActivitySummary item) { protected String getDateLabel(BaseActivitySummary item) {
Date startTime = item.getStartTime(); Date startTime = item.getStartTime();
@@ -219,6 +226,11 @@ public class ActivitySummariesAdapter extends AbstractActivityListingAdapter<Bas
return DateTimeUtils.formatDurationHoursMinutes(duration, TimeUnit.MILLISECONDS); return DateTimeUtils.formatDurationHoursMinutes(duration, TimeUnit.MILLISECONDS);
} }
@Override
protected String getSessionCountLabel(BaseActivitySummary item) {
return "";
}
@Override @Override
protected boolean hasHR(BaseActivitySummary item) { protected boolean hasHR(BaseActivitySummary item) {
return false; return false;
@@ -239,6 +251,26 @@ public class ActivitySummariesAdapter extends AbstractActivityListingAdapter<Bas
return false; return false;
} }
@Override
protected boolean hasTotalSteps(BaseActivitySummary item) {
return false;
}
@Override
protected boolean isSummary(BaseActivitySummary item) {
return false;
}
@Override
protected boolean isEmptySummary(BaseActivitySummary item) {
return false;
}
@Override
protected String getStepTotalLabel(BaseActivitySummary item) {
return null;
}
@Override @Override
protected int getIcon(BaseActivitySummary item) { protected int getIcon(BaseActivitySummary item) {
return ActivityKind.getIconId(item.getActivityKind()); return ActivityKind.getIconId(item.getActivityKind());

View File

@@ -0,0 +1,98 @@
package nodomain.freeyourgadget.gadgetbridge.model;
import java.util.Date;
// ActivitySession holds activities detected by the steps/hr/intensity
// and is used in the Activity List
public class ActivitySession {
public static int SESSION_NORMAL = 1;
public static int SESSION_SUMMARY = 2;
private final Date startTime;
private final Date endTime;
private final int activeSteps;
private final int heartRateAverage;
private final float intensity;
private final float distance;
private final int activityKind;
// following is related to step session, we hold it here for the listview
// it is identified by SESSION_SUMMARY
private int sessionCount = 0;
private int sessionType = SESSION_NORMAL;
private boolean isEmptySummary = false; // in case there is no activity on that day
private int totalDaySteps;
public ActivitySession(Date startTime,
Date endTime,
int steps, int heartRateAverage, float intensity, float distance, int activityKind) {
this.startTime = startTime;
this.endTime = endTime;
this.activeSteps = steps;
this.heartRateAverage = heartRateAverage;
this.intensity = intensity;
this.distance = distance;
this.activityKind = activityKind;
}
public Date getStartTime() {
return startTime;
}
public Date getEndTime() {
return endTime;
}
public int getActiveSteps() {
return activeSteps;
}
public int getHeartRateAverage() {
return heartRateAverage;
}
public int getActivityKind() {
return activityKind;
}
public float getIntensity() {
return intensity;
}
public float getDistance() {
return distance;
}
public int getSessionCount() {
return sessionCount;
}
public void setSessionCount(int sessionCount) {
this.sessionCount = sessionCount;
}
public int getSessionType() {
return sessionType;
}
public void setSessionType(int sessionType) {
this.sessionType = sessionType;
}
public boolean getIsEmptySummary() {
return isEmptySummary;
}
public void setEmptySummary(boolean emptySummary) {
this.isEmptySummary = emptySummary;
}
public int getTotalDaySteps() {
return totalDaySteps;
}
public void setTotalDaySteps(int totalDaySteps) {
this.totalDaySteps = totalDaySteps;
}
}

View File

@@ -0,0 +1,31 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="26dp"
android:height="26dp"
android:tint="#7E7E7E"
android:viewportWidth="26"
android:viewportHeight="26">
<path
android:pathData="m11.711,16.3278a4.8542,7.133 75.8015,0 1,-5.6028 -5.0206,4.8542 7.133,75.8015 0,1 8.1903,-5.0206 4.8542,7.133 75.8015,0 1,5.6028 5.0206,4.8542 7.133,75.8015 0,1 -8.1903,5.0206M21.4865,14.0769 L26.0048,11.3072 22.914,8.5375L23.9253,4.613L18.5345,4.613L15.4436,1.8433 10.9253,4.613L5.5345,4.613L4.5232,8.5375L0.0048,11.3072 3.0957,14.0769L2.0844,18.0013L7.4752,18.0013L10.566,20.771 15.0844,18.0013L20.4752,18.0013Z"
android:strokeWidth="1.01966"
android:fillColor="#000000"/>
<path
android:pathData="m4.273,11.6324l4.094,0l3.4795,-4.2078 1.0371,4.5933 2.6841,-2.2817l7.4587,0l-0.8601,1.1607L16.1168,10.897l-4.3503,3.7731 -0.8612,-3.8037 -1.6109,2.011 -4.0304,-0.0003z"
android:strokeWidth="1.01966"
android:fillColor="#000000"/>
<path
android:pathData="m1.8709,18.7471l-0.3147,1.2211l5.343,0l3.129,2.807 4.5735,-2.807l5.3453,0l0.3147,-1.2211l-5.4373,0l-4.4626,2.734 -3.0558,-2.734z"
android:strokeLineJoin="miter"
android:strokeWidth="0.591009"
android:fillColor="#000000"
android:strokeColor="#00000000"
android:fillType="evenOdd"
android:strokeLineCap="butt"/>
<path
android:pathData="m1.367,20.7367l-0.3147,1.2211l5.3453,0l3.1268,2.807 4.5735,-2.807l5.3453,0l0.3147,-1.2211l-5.4373,0l-4.4626,2.734 -3.0535,-2.734z"
android:strokeLineJoin="miter"
android:strokeWidth="0.591009"
android:fillColor="#000000"
android:strokeColor="#00000000"
android:fillType="evenOdd"
android:strokeLineCap="butt"/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M3,5L1,5v16c0,1.1 0.9,2 2,2h16v-2L3,21L3,5zM21,1L7,1c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L23,3c0,-1.1 -0.9,-2 -2,-2zM21,17L7,17L7,3h14v14z"/>
</vector>

View File

@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#7E7E7E"
>
<path
android:fillColor="@android:color/white"
android:pathData="M18,4H6v2l6.5,6L6,18v2h12v-3h-7l5,-5 -5,-5h7V4z"/>
</vector>

View File

@@ -1,15 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="21.367056dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:tint="#7E7E7E" android:tint="#7E7E7E"
android:viewportWidth="21.367056" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path <path
android:fillColor="#FF000000" android:fillColor="@android:color/white"
android:pathData="m2.5,15.5784h4.1775L8.9012,9.8743 11.3875,16.1187 13.8885,6.0045 18.8671,15.5784 18.7123,18.896 14.4568,10.4989 11.965,21.5 8.9404,14.1173 7.9512,17.3235 3.8385,17.323Z" android:pathData="M11.57,13.16c-1.36,0.28 -2.17,1.16 -2.17,2.41 0,1.34 1.11,2.42 2.49,2.42 2.05,0 3.71,-1.66 3.71,-3.71 0,-1.07 -0.15,-2.12 -0.46,-3.12 -0.79,1.07 -2.2,1.72 -3.57,2zM13.5,0.67s0.74,2.65 0.74,4.8c0,2.06 -1.35,3.73 -3.41,3.73 -2.07,0 -3.63,-1.67 -3.63,-3.73l0.03,-0.36C5.21,7.51 4,10.62 4,14c0,4.42 3.58,8 8,8s8,-3.58 8,-8C20,8.61 17.41,3.8 13.5,0.67zM12,20c-3.31,0 -6,-2.69 -6,-6 0,-1.53 0.3,-3.04 0.86,-4.43 1.01,1.01 2.41,1.63 3.97,1.63 2.66,0 4.75,-1.83 5.28,-4.43C17.34,8.97 18,11.44 18,14c0,3.31 -2.69,6 -6,6z" />
android:strokeWidth="0.999994" />
<path
android:fillColor="#FF000000"
android:pathData="M8.9696,4.2276C9.4586,4.1648 9.801,3.7264 9.7306,3.2534 9.6601,2.7804 9.2023,2.4448 8.7133,2.5076 8.2243,2.5704 7.8819,3.0088 7.9524,3.4818 8.0229,3.9548 8.4806,4.2904 8.9696,4.2276ZM8.4469,10.4135 L8.5536,8.4877 10.1225,8.8668 10.2231,10.2646 11.2606,10.2284 11.0342,8.158 9.2155,7.7021 9.29,6.3777C9.964,6.9486 10.9171,7.2644 11.8951,7.1388L11.767,6.2788C10.9224,6.3872 10.147,6.0486 9.7017,5.4922L9.1546,4.8612C8.9384,4.6261 8.646,4.4883 8.3348,4.5283 8.2015,4.5454 8.119,4.5998 7.9856,4.617L5.8149,5.8599 6.1161,7.881 7.0052,7.7668 6.7873,6.3047 7.5427,5.9009 7.3579,9.9383l-1.3898,1.6275 0.4224,0.9079z"
android:strokeWidth="1" />
</vector> </vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:tint="#7E7E7E"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="m13.5,0.67c0,0 0.74,2.65 0.74,4.8 0,2.06 -1.35,3.73 -3.41,3.73C8.76,9.2 7.2,7.53 7.2,5.47L7.23,5.11C5.21,7.51 4,10.62 4,14c0,4.42 3.58,8 8,8 4.42,0 8,-3.58 8,-8C20,8.61 17.41,3.8 13.5,0.67ZM12,20C8.69,20 6,17.31 6,14 6,12.47 6.3,10.96 6.86,9.57c1.01,1.01 2.41,1.63 3.97,1.63 2.66,0 4.75,-1.83 5.28,-4.43 1.23,2.2 1.89,4.67 1.89,7.23 0,3.31 -2.69,6 -6,6z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:tint="#7E7E7E"
android:width="24dp">
<path
android:fillColor="#000"
android:pathData="M10.74,11.72C11.21,12.95 11.16,14.23 9.75,14.74C6.85,15.81 6.2,13 6.16,12.86L10.74,11.72M5.71,10.91L10.03,9.84C9.84,8.79 10.13,7.74 10.13,6.5C10.13,4.82 8.8,1.53 6.68,2.06C4.26,2.66 3.91,5.35 4,6.65C4.12,7.95 5.64,10.73 5.71,10.91M17.85,19.85C17.82,20 17.16,22.8 14.26,21.74C12.86,21.22 12.8,19.94 13.27,18.71L17.85,19.85M20,13.65C20.1,12.35 19.76,9.65 17.33,9.05C15.22,8.5 13.89,11.81 13.89,13.5C13.89,14.73 14.17,15.78 14,16.83L18.3,17.9C18.38,17.72 19.89,14.94 20,13.65Z" />
</vector>

View File

@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:tint="#7E7E7E"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="m6.4801,14.3793c0.3823,1.0311 0.3416,2.104 -0.8053,2.5316C3.3159,17.8078 2.7872,15.4522 2.7547,15.3349l3.7255,-0.9556M2.3886,13.7003 L5.9026,12.8033c-0.1546,-0.8802 0.0813,-1.7604 0.0813,-2.7998 0,-1.4083 -1.0819,-4.1662 -2.8063,-3.7219 -1.9685,0.503 -2.2532,2.7579 -2.18,3.8476 0.0976,1.0897 1.334,3.4201 1.391,3.571m9.8749,7.4941C12.2392,21.3201 11.7023,23.6672 9.3434,22.7787 8.2046,22.3428 8.1558,21.2698 8.5381,20.2387l3.7255,0.9556m1.7489,-5.1972c0.0813,-1.0897 -0.1952,-3.3531 -2.1718,-3.856 -1.7163,-0.461 -2.7982,2.3136 -2.7982,3.7303 0,1.0311 0.2278,1.9112 0.0895,2.7914l3.4977,0.8969c0.0651,-0.1509 1.2933,-2.4813 1.3828,-3.5626z"
android:strokeWidth="0.999999"/>
<path
android:fillColor="#FF000000"
android:pathData="M14.7308,7.4903C14.986,8.2348 14.9589,9.0096 14.1934,9.3183 12.6189,9.9659 12.266,8.2651 12.2443,8.1803L14.7308,7.4903M12,7 L14.3454,6.3523c-0.1032,-0.6356 0.0543,-1.2711 0.0543,-2.0217 0,-1.0169 -0.7221,-3.0083 -1.873,-2.6875 -1.3138,0.3632 -1.5039,1.9914 -1.455,2.7783C11.1368,5.2083 11.962,6.891 12,7m6.5909,5.4113c-0.0162,0.0908 -0.3746,1.7856 -1.949,1.144 -0.7601,-0.3148 -0.7926,-1.0895 -0.5375,-1.834l2.4865,0.69m1.1673,-3.7528c0.0543,-0.7869 -0.1303,-2.4212 -1.4496,-2.7843 -1.1455,-0.3329 -1.8676,1.6706 -1.8676,2.6935 0,0.7445 0.152,1.3801 0.0597,2.0156l2.3345,0.6477c0.0435,-0.109 0.8632,-1.7917 0.9229,-2.5725z"
android:strokeWidth="0.999998"/>
</vector>

View File

@@ -0,0 +1,379 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/list_item_parent_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--
android:background="?android:attr/activatedBackgroundIndicator"
-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<com.github.mikephil.charting.charts.PieChart
android:id="@+id/activity_dashboard_piechart1"
android:layout_width="110dp"
android:layout_height="110dp"
android:layout_gravity="bottom|center"
android:layout_marginBottom="0dp"
android:layout_weight="1" />
<com.github.mikephil.charting.charts.PieChart
android:id="@+id/activity_dashboard_piechart2"
android:layout_width="110dp"
android:layout_height="110dp"
android:layout_gravity="bottom|center"
android:layout_marginBottom="0dp"
android:layout_weight="1" />
<com.github.mikephil.charting.charts.PieChart
android:id="@+id/activity_dashboard_piechart3"
android:layout_width="110dp"
android:layout_height="110dp"
android:layout_gravity="bottom|center"
android:layout_marginBottom="0dp"
android:layout_weight="1" />
<!--
<com.github.mikephil.charting.charts.PieChart
android:id="@+id/activity_dashboard_piechart4"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_gravity="bottom|center"
android:layout_marginBottom="0dp" />
-->
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_marginBottom="5dp"
android:gravity="center"
android:orientation="horizontal">
<View
android:layout_width="25dp"
android:layout_height="0dp"
android:layout_weight="0.5" />
<include
layout="@layout/heartrate_average_widget"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="bottom|center"
android:layout_weight="1" />
<include
layout="@layout/intensity_total_widget"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="bottom|center"
android:layout_marginTop="0dp"
android:layout_marginEnd="0dp"
android:layout_weight="1" />
<View
android:layout_width="25dp"
android:layout_height="0dp"
android:layout_weight="0.5" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:baselineAligned="false"
android:gravity="bottom|center"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/line_layout_step"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center|top"
android:orientation="vertical">
<ImageView
android:id="@+id/line_layout_step_icon"
android:layout_width="19dp"
android:layout_height="19dp"
android:layout_gravity="center"
android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_shoe_print" />
<TextView
android:id="@+id/line_layout_step_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="@string/activity_list_summary_active_steps" />
<TextView
android:id="@+id/line_layout_step_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="15000" />
</LinearLayout>
<LinearLayout
android:id="@+id/line_layout_distance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center|top"
android:orientation="vertical">
<ImageView
android:id="@+id/line_layout_distance_icon"
android:layout_width="19dp"
android:layout_height="19dp"
android:layout_gravity="center"
android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_distance" />
<TextView
android:id="@+id/line_layout_distance_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="@string/distance" />
<TextView
android:id="@+id/line_layout_distance_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="15.1km" />
</LinearLayout>
<LinearLayout
android:id="@+id/line_layout_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center|top"
android:orientation="vertical">
<ImageView
android:id="@+id/line_layout_duration_icon"
android:layout_width="19dp"
android:layout_height="19dp"
android:layout_gravity="center"
android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_access_time" />
<TextView
android:id="@+id/line_layout_duration_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="@string/activity_list_summary_active_time" />
<TextView
android:id="@+id/line_layout_duration_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="122" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:baselineAligned="false"
android:gravity="center"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/line_layout_total_step"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/line_layout_total_step_icon"
android:layout_width="19dp"
android:layout_height="19dp"
android:layout_gravity="center"
android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_shoe_prints_many" />
<TextView
android:id="@+id/line_layout_total_step_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="@string/live_activity_total_steps" />
<TextView
android:id="@+id/line_layout_total_step_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="15000" />
</LinearLayout>
<LinearLayout
android:id="@+id/line_layout_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/line_layout_count_icon"
android:layout_width="19dp"
android:layout_height="19dp"
android:layout_gravity="center"
android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_activity_stacked" />
<TextView
android:id="@+id/line_layout_count_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="@string/activity_list_summary_activities" />
<TextView
android:id="@+id/line_layout_count_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="15" />
</LinearLayout>
<LinearLayout
android:id="@+id/line_layout_intensity2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="bottom|center"
android:orientation="vertical">
<ImageView
android:id="@+id/line_layout_intensity2_icon"
android:layout_width="19dp"
android:layout_height="19dp"
android:layout_gravity="center"
android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_intensity" />
<TextView
android:id="@+id/line_layout_intensity2_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="@string/activity_list_summary_intensity" />
<TextView
android:id="@+id/line_layout_intensity2_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="15" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View File

@@ -134,7 +134,7 @@
android:layout_height="19dp" android:layout_height="19dp"
android:layout_gravity="bottom|start" android:layout_gravity="bottom|start"
android:contentDescription="@string/candidate_item_device_image" android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_shoe" /> app:srcCompat="@drawable/ic_shoe_print" />
<TextView <TextView
android:id="@+id/line_layout_step_label" android:id="@+id/line_layout_step_label"

View File

@@ -4,7 +4,6 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity$PlaceholderFragment"> tools:context="nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity$PlaceholderFragment">
<TextView <TextView
android:id="@+id/stepsDateView" android:id="@+id/stepsDateView"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -14,8 +13,12 @@
android:textAppearance="@style/TextAppearance.AppCompat.Medium" android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold" /> android:textStyle="bold" />
<ListView <ListView
android:id="@+id/itemListView" android:id="@+id/itemListView"
android:layout_marginTop="0dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
</LinearLayout> </LinearLayout>

View File

@@ -14,14 +14,13 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_activity_unknown" /> app:srcCompat="@drawable/ic_intensity_hollow" />
<TextView <TextView
android:id="@+id/intensity_widget_label" android:id="@+id/intensity_widget_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingBottom="3dp" android:paddingTop="10dp"
android:paddingEnd="3dp"
android:text="" android:text=""
android:textAlignment="center" android:textAlignment="center"
android:textSize="12sp" android:textSize="12sp"

View File

@@ -443,6 +443,11 @@
<string name="weekstepschart_steps_a_week">Steps per week</string> <string name="weekstepschart_steps_a_week">Steps per week</string>
<string name="activity_sleepchart_activity_and_sleep">Activity</string> <string name="activity_sleepchart_activity_and_sleep">Activity</string>
<string name="charts_activity_list">Activity list</string> <string name="charts_activity_list">Activity list</string>
<string name="activity_list_summary_active_steps">Active steps</string>
<string name="activity_list_summary_distance">Distance</string>
<string name="activity_list_summary_active_time">Active time</string>
<string name="activity_list_summary_intensity">Movement\nIntensity</string>
<string name="activity_list_summary_activities">Activities</string>
<string name="lack_of_sleep">Lack of sleep: %1$s</string> <string name="lack_of_sleep">Lack of sleep: %1$s</string>
<string name="overslept">Overslept: %1$s</string> <string name="overslept">Overslept: %1$s</string>
<!-- Firmware updating --> <!-- Firmware updating -->