mirror of
https://github.com/oliexdev/openScale.git
synced 2025-08-13 20:24:14 +02:00
- redesign statistic fragment to show the differences between a range of measurements
This commit is contained in:
@@ -576,6 +576,19 @@ public class OpenScale {
|
||||
return measurementDAO.getAllInRange(startCalender.getTime(), endCalender.getTime(), selectedUserId);
|
||||
}
|
||||
|
||||
public List<ScaleMeasurement> getScaleMeasurementOfRangeDates(int startYear, int startMonth, int startDay, int endYear, int endMonth, int endDay) {
|
||||
int selectedUserId = getSelectedScaleUserId();
|
||||
|
||||
Calendar startCalender = Calendar.getInstance();
|
||||
Calendar endCalender = Calendar.getInstance();
|
||||
|
||||
startCalender.set(startYear, startMonth, startDay, 0, 0, 0);
|
||||
endCalender.set(endYear, endMonth, endDay, 0, 0, 0);
|
||||
endCalender.add(Calendar.DAY_OF_MONTH, 1);
|
||||
|
||||
return measurementDAO.getAllInRange(startCalender.getTime(), endCalender.getTime(), selectedUserId);
|
||||
}
|
||||
|
||||
public List<ScaleMeasurement> getScaleMeasurementOfDay(int year, int month, int day) {
|
||||
int selectedUserId = getSelectedScaleUserId();
|
||||
|
||||
|
@@ -228,7 +228,7 @@ public abstract class FloatMeasurementView extends MeasurementView {
|
||||
setValue(clampValue(value - INC_DEC_DELTA), previousValue, true);
|
||||
}
|
||||
|
||||
private String formatValue(float value, boolean withUnit) {
|
||||
public String formatValue(float value, boolean withUnit) {
|
||||
final String format = String.format(Locale.getDefault(), "%%.%df%s",
|
||||
getDecimalPlaces(), withUnit && !getUnit().isEmpty() ? " %s" : "");
|
||||
return String.format(Locale.getDefault(), format, value, getUnit());
|
||||
|
@@ -103,8 +103,10 @@ public class OverviewFragment extends Fragment {
|
||||
chartView.getLegend().setEnabled(false);
|
||||
chartView.getAxisRight().setDrawLabels(false);
|
||||
chartView.getAxisRight().setDrawGridLines(false);
|
||||
chartView.getAxisRight().setDrawAxisLine(false);
|
||||
chartView.getAxisLeft().setDrawGridLines(false);
|
||||
chartView.getAxisLeft().setDrawLabels(false);
|
||||
chartView.getAxisLeft().setDrawAxisLine(false);
|
||||
chartView.getXAxis().setDrawGridLines(false);
|
||||
|
||||
chartActionBarView = overviewView.findViewById(R.id.chartActionBar);
|
||||
|
@@ -0,0 +1,173 @@
|
||||
package com.health.openscale.gui.statistic;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.RelativeSizeSpan;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.github.mikephil.charting.charts.LineChart;
|
||||
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.interfaces.datasets.ILineDataSet;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.health.openscale.R;
|
||||
import com.health.openscale.core.datatypes.ScaleMeasurement;
|
||||
import com.health.openscale.gui.measurement.FloatMeasurementView;
|
||||
import com.health.openscale.gui.measurement.MeasurementView;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
class StatisticAdapter extends RecyclerView.Adapter<StatisticAdapter.ViewHolder> {
|
||||
private Activity activity;
|
||||
private List<ScaleMeasurement> scaleMeasurementList;
|
||||
private ScaleMeasurement firstMeasurement;
|
||||
private ScaleMeasurement lastMeasurement;
|
||||
private List<FloatMeasurementView> measurementViewList;
|
||||
|
||||
public StatisticAdapter(Activity activity, List<ScaleMeasurement> scaleMeasurementList) {
|
||||
this.activity = activity;
|
||||
this.scaleMeasurementList = scaleMeasurementList;
|
||||
|
||||
if (scaleMeasurementList.isEmpty()) {
|
||||
this.firstMeasurement = new ScaleMeasurement();
|
||||
this.lastMeasurement = new ScaleMeasurement();
|
||||
} else if (scaleMeasurementList.size() == 1) {
|
||||
this.firstMeasurement = scaleMeasurementList.get(0);
|
||||
this.lastMeasurement = scaleMeasurementList.get(0);
|
||||
} else {
|
||||
this.firstMeasurement = scaleMeasurementList.get(scaleMeasurementList.size()-1);
|
||||
this.lastMeasurement = scaleMeasurementList.get(0);
|
||||
}
|
||||
|
||||
List<MeasurementView> fullMeasurementViewList = MeasurementView.getMeasurementList(activity, MeasurementView.DateTimeOrder.LAST);
|
||||
measurementViewList = new ArrayList<>();
|
||||
|
||||
for (MeasurementView measurementView : fullMeasurementViewList) {
|
||||
if (measurementView instanceof FloatMeasurementView && measurementView.isVisible()) {
|
||||
measurementViewList.add((FloatMeasurementView)measurementView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatisticAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_statistic, parent, false);
|
||||
|
||||
ViewHolder viewHolder = new ViewHolder(view);
|
||||
|
||||
return viewHolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull StatisticAdapter.ViewHolder holder, int position) {
|
||||
FloatMeasurementView measurementView = measurementViewList.get(position);
|
||||
List<Entry> lineEntries = new ArrayList<>();
|
||||
|
||||
Collections.reverse(scaleMeasurementList);
|
||||
|
||||
int i=0;
|
||||
float sumValue = 0;
|
||||
for (ScaleMeasurement scaleMeasurement : scaleMeasurementList) {
|
||||
measurementView.loadFrom(scaleMeasurement, null);
|
||||
sumValue += measurementView.getValue();
|
||||
lineEntries.add(new Entry(i, measurementView.getValue()));
|
||||
i++;
|
||||
}
|
||||
|
||||
Collections.reverse(scaleMeasurementList);
|
||||
|
||||
LineDataSet lineDataSet = new LineDataSet(lineEntries, holder.measurementName.getText().toString());
|
||||
lineDataSet.setColor(measurementView.getColor());
|
||||
lineDataSet.setDrawCircles(false);
|
||||
lineDataSet.setFillColor(measurementView.getColor());
|
||||
lineDataSet.setDrawFilled(true);
|
||||
lineDataSet.setDrawValues(false);
|
||||
lineDataSet.setHighlightEnabled(false);
|
||||
|
||||
List<ILineDataSet> dataSets = new ArrayList<>();
|
||||
dataSets.add(lineDataSet);
|
||||
|
||||
LineData data = new LineData(dataSets);
|
||||
holder.diffChartView.setData(data);
|
||||
holder.diffChartView.invalidate();
|
||||
|
||||
measurementView.loadFrom(lastMeasurement, firstMeasurement);
|
||||
|
||||
holder.measurementName.setText(measurementView.getName());
|
||||
SpannableStringBuilder diffValueText = new SpannableStringBuilder();
|
||||
float avgValue = sumValue / scaleMeasurementList.size();
|
||||
diffValueText.append("(\u00d8 " + measurementView.formatValue(avgValue, true) + ") ");
|
||||
diffValueText.setSpan(new RelativeSizeSpan(0.8f), 0, diffValueText.length(),
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
measurementView.appendDiffValue(diffValueText, false);
|
||||
holder.diffValueView.setText(diffValueText);
|
||||
holder.endValueView.setText(measurementView.getValueAsString(true));
|
||||
holder.iconView.setImageDrawable(measurementView.getIcon());
|
||||
holder.iconView.setBackgroundTintList(ColorStateList.valueOf(measurementView.getColor()));
|
||||
|
||||
measurementView.loadFrom(firstMeasurement, null);
|
||||
holder.startValueView.setText(measurementView.getValueAsString(true));
|
||||
}
|
||||
|
||||
private int convertDateToInt(Date date) {
|
||||
LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
return (int)localDate.toEpochDay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return measurementViewList.get(position).getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return measurementViewList.size();
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView measurementName;
|
||||
TextView diffValueView;
|
||||
TextView startValueView;
|
||||
FloatingActionButton iconView;
|
||||
LineChart diffChartView;
|
||||
TextView endValueView;
|
||||
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
|
||||
measurementName = itemView.findViewById(R.id.measurementName);
|
||||
diffValueView = itemView.findViewById(R.id.diffValueView);
|
||||
startValueView = itemView.findViewById(R.id.startValueView);
|
||||
iconView = itemView.findViewById(R.id.iconView);
|
||||
diffChartView = itemView.findViewById(R.id.diffChartView);
|
||||
endValueView = itemView.findViewById(R.id.endValueView);
|
||||
|
||||
diffChartView.getLegend().setEnabled(false);
|
||||
diffChartView.getDescription().setEnabled(false);
|
||||
diffChartView.getAxisRight().setDrawLabels(false);
|
||||
diffChartView.getAxisRight().setDrawGridLines(false);
|
||||
diffChartView.getAxisRight().setDrawAxisLine(false);
|
||||
diffChartView.getAxisLeft().setDrawGridLines(false);
|
||||
diffChartView.getAxisLeft().setDrawLabels(false);
|
||||
diffChartView.getAxisLeft().setDrawAxisLine(false);
|
||||
diffChartView.getXAxis().setDrawGridLines(false);
|
||||
diffChartView.getXAxis().setDrawLabels(false);
|
||||
diffChartView.getXAxis().setDrawAxisLine(false);
|
||||
diffChartView.setMinOffset(0);
|
||||
}
|
||||
}
|
||||
}
|
@@ -16,141 +16,120 @@
|
||||
|
||||
package com.health.openscale.gui.statistic;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.Html;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.util.Pair;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.github.mikephil.charting.charts.RadarChart;
|
||||
import com.github.mikephil.charting.components.Legend;
|
||||
import com.github.mikephil.charting.components.LegendEntry;
|
||||
import com.github.mikephil.charting.components.MarkerView;
|
||||
import com.github.mikephil.charting.data.RadarData;
|
||||
import com.github.mikephil.charting.data.RadarDataSet;
|
||||
import com.github.mikephil.charting.data.RadarEntry;
|
||||
import com.github.mikephil.charting.formatter.ValueFormatter;
|
||||
import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet;
|
||||
import com.google.android.material.datepicker.CalendarConstraints;
|
||||
import com.google.android.material.datepicker.CompositeDateValidator;
|
||||
import com.google.android.material.datepicker.DateValidatorPointBackward;
|
||||
import com.google.android.material.datepicker.DateValidatorPointForward;
|
||||
import com.google.android.material.datepicker.MaterialDatePicker;
|
||||
import com.google.android.material.datepicker.MaterialPickerOnPositiveButtonClickListener;
|
||||
import com.health.openscale.R;
|
||||
import com.health.openscale.core.OpenScale;
|
||||
import com.health.openscale.core.datatypes.ScaleMeasurement;
|
||||
import com.health.openscale.core.datatypes.ScaleUser;
|
||||
import com.health.openscale.core.utils.Converters;
|
||||
import com.health.openscale.core.utils.DateTimeHelpers;
|
||||
import com.health.openscale.gui.measurement.BMIMeasurementView;
|
||||
import com.health.openscale.gui.measurement.BoneMeasurementView;
|
||||
import com.health.openscale.gui.measurement.ChartMarkerView;
|
||||
import com.health.openscale.gui.measurement.FatMeasurementView;
|
||||
import com.health.openscale.gui.measurement.FloatMeasurementView;
|
||||
import com.health.openscale.gui.measurement.MeasurementView;
|
||||
import com.health.openscale.gui.measurement.MeasurementViewSettings;
|
||||
import com.health.openscale.gui.measurement.MuscleMeasurementView;
|
||||
import com.health.openscale.gui.measurement.WaterMeasurementView;
|
||||
import com.health.openscale.gui.measurement.WeightMeasurementView;
|
||||
import com.health.openscale.gui.utils.ColorUtil;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class StatisticsFragment extends Fragment {
|
||||
|
||||
private View statisticsView;
|
||||
|
||||
private TextView txtGoalWeight;
|
||||
private TextView txtGoalDiff;
|
||||
private TextView txtGoalDayLeft;
|
||||
private TextView txtTotalWeightLost;
|
||||
|
||||
private TextView txtLabelGoalWeight;
|
||||
private TextView txtLabelGoalDiff;
|
||||
private TextView txtLabelDayLeft;
|
||||
private TextView txtLabelTotalWeightLost;
|
||||
|
||||
private RadarChart radarChartWeek;
|
||||
private RadarChart radarChartMonth;
|
||||
|
||||
private ScaleUser currentScaleUser;
|
||||
private ScaleMeasurement firstScaleMeasurement;
|
||||
private ScaleMeasurement lastScaleMeasurement;
|
||||
|
||||
private ArrayList <MeasurementView> viewMeasurementsStatistics;
|
||||
private RecyclerView compareRecyclerView;
|
||||
private TextView diffDateTextView;
|
||||
private TextView countMeasurementTextView;
|
||||
private ImageView datePickerView;
|
||||
private StatisticAdapter statisticAdapter;
|
||||
private List<ScaleMeasurement> scaleMeasurementList;
|
||||
private SharedPreferences prefs;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
statisticsView = inflater.inflate(R.layout.fragment_statistics, container, false);
|
||||
View statisticsView = inflater.inflate(R.layout.fragment_statistics, container, false);
|
||||
|
||||
txtGoalWeight = statisticsView.findViewById(R.id.txtGoalWeight);
|
||||
txtGoalWeight.setTextColor(ColorUtil.getTintColor(statisticsView.getContext()));
|
||||
txtGoalDiff = statisticsView.findViewById(R.id.txtGoalDiff);
|
||||
txtGoalDiff.setTextColor(ColorUtil.getTintColor(statisticsView.getContext()));
|
||||
txtGoalDayLeft = statisticsView.findViewById(R.id.txtGoalDayLeft);
|
||||
txtGoalDayLeft.setTextColor(ColorUtil.getTintColor(statisticsView.getContext()));
|
||||
txtTotalWeightLost = statisticsView.findViewById(R.id.txtTotalWeightLost);
|
||||
txtTotalWeightLost.setTextColor(ColorUtil.getTintColor(statisticsView.getContext()));
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
compareRecyclerView = statisticsView.findViewById(R.id.compareRecyclerView);
|
||||
diffDateTextView = statisticsView.findViewById(R.id.diffDateTextView);
|
||||
countMeasurementTextView = statisticsView.findViewById(R.id.countMeasurementTextView);
|
||||
datePickerView = statisticsView.findViewById(R.id.datePickerView);
|
||||
|
||||
txtLabelGoalWeight = statisticsView.findViewById(R.id.txtLabelGoalWeight);
|
||||
txtLabelGoalWeight.setTextColor(ColorUtil.getTintColor(statisticsView.getContext()));
|
||||
txtLabelGoalDiff = statisticsView.findViewById(R.id.txtLabelGoalDiff);
|
||||
txtLabelGoalDiff.setTextColor(ColorUtil.getTintColor(statisticsView.getContext()));
|
||||
txtLabelDayLeft = statisticsView.findViewById(R.id.txtLabelDayLeft);
|
||||
txtLabelDayLeft.setTextColor(ColorUtil.getTintColor(statisticsView.getContext()));
|
||||
txtLabelTotalWeightLost = statisticsView.findViewById(R.id.txtLabelTotalWeightLost);
|
||||
txtLabelTotalWeightLost.setTextColor(ColorUtil.getTintColor(statisticsView.getContext()));
|
||||
datePickerView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
List<CalendarConstraints.DateValidator> dateValidatorList = new ArrayList<>();
|
||||
|
||||
viewMeasurementsStatistics = new ArrayList<>();
|
||||
CalendarConstraints.DateValidator selectedDateValidator = new CalendarConstraints.DateValidator() {
|
||||
@Override
|
||||
public boolean isValid(long date) {
|
||||
Calendar dateCalendar = Calendar.getInstance();
|
||||
dateCalendar.setTime(new Date(date));
|
||||
|
||||
viewMeasurementsStatistics.add(new WeightMeasurementView(statisticsView.getContext()));
|
||||
viewMeasurementsStatistics.add(new WaterMeasurementView(statisticsView.getContext()));
|
||||
viewMeasurementsStatistics.add(new MuscleMeasurementView(statisticsView.getContext()));
|
||||
viewMeasurementsStatistics.add(new FatMeasurementView(statisticsView.getContext()));
|
||||
viewMeasurementsStatistics.add(new BoneMeasurementView(statisticsView.getContext()));
|
||||
viewMeasurementsStatistics.add(new BMIMeasurementView(statisticsView.getContext()));
|
||||
List<ScaleMeasurement> dateScaleMeasurementList = OpenScale.getInstance().getScaleMeasurementOfDay(dateCalendar.get(Calendar.YEAR), dateCalendar.get(Calendar.MONTH), dateCalendar.get(Calendar.DAY_OF_MONTH));
|
||||
|
||||
ArrayList<LegendEntry> legendEntriesWeek = new ArrayList<>();
|
||||
if (!dateScaleMeasurementList.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i< viewMeasurementsStatistics.size(); i++) {
|
||||
LegendEntry legendEntry = new LegendEntry();
|
||||
legendEntry.label = i + " - " + viewMeasurementsStatistics.get(i).getName().toString();
|
||||
legendEntriesWeek.add(legendEntry);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
MarkerView mv = new ChartMarkerView(statisticsView.getContext(), R.layout.chart_markerview);
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
radarChartWeek = statisticsView.findViewById(R.id.radarPastWeek);
|
||||
radarChartWeek.getXAxis().setTextColor(ColorUtil.getTintColor(statisticsView.getContext()));
|
||||
radarChartWeek.getDescription().setEnabled(false);
|
||||
radarChartWeek.getYAxis().setEnabled(false);
|
||||
radarChartWeek.setExtraTopOffset(10);
|
||||
radarChartWeek.setRotationEnabled(false);
|
||||
Legend weekLegend = radarChartWeek.getLegend();
|
||||
weekLegend.setTextColor(ColorUtil.getTintColor(statisticsView.getContext()));
|
||||
weekLegend.setWordWrapEnabled(true);
|
||||
weekLegend.setExtra(legendEntriesWeek);
|
||||
weekLegend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER);
|
||||
mv.setChartView(radarChartWeek);
|
||||
radarChartWeek.setMarker(mv);
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel parcel, int i) {
|
||||
|
||||
radarChartMonth = statisticsView.findViewById(R.id.radarPastMonth);
|
||||
radarChartMonth.getXAxis().setTextColor(ColorUtil.getTintColor(statisticsView.getContext()));
|
||||
radarChartMonth.getDescription().setEnabled(false);
|
||||
radarChartMonth.getYAxis().setEnabled(false);
|
||||
radarChartMonth.setExtraTopOffset(10);
|
||||
radarChartMonth.setRotationEnabled(false);
|
||||
Legend monthLegend = radarChartMonth.getLegend();
|
||||
monthLegend.setTextColor(ColorUtil.getTintColor(statisticsView.getContext()));
|
||||
monthLegend.setWordWrapEnabled(true);
|
||||
monthLegend.setExtra(legendEntriesWeek);
|
||||
monthLegend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER);
|
||||
mv.setChartView(radarChartMonth);
|
||||
radarChartMonth.setMarker(mv);
|
||||
}
|
||||
};
|
||||
dateValidatorList.add(DateValidatorPointForward.from(scaleMeasurementList.get(scaleMeasurementList.size()-1).getDateTime().getTime()));
|
||||
dateValidatorList.add(DateValidatorPointBackward.before(scaleMeasurementList.get(0).getDateTime().getTime()));
|
||||
dateValidatorList.add(selectedDateValidator);
|
||||
|
||||
CalendarConstraints constraintsBuilderRange = new CalendarConstraints.Builder().setValidator(CompositeDateValidator.allOf(dateValidatorList)).build();
|
||||
|
||||
MaterialDatePicker<Pair<Long, Long>> materialDate = MaterialDatePicker.Builder.dateRangePicker().setCalendarConstraints(constraintsBuilderRange).build();
|
||||
materialDate.show(getActivity().getSupportFragmentManager(), "MATERIAL_DATE_PICKER");
|
||||
|
||||
materialDate.addOnPositiveButtonClickListener(new MaterialPickerOnPositiveButtonClickListener<Pair<Long, Long>>() {
|
||||
@Override public void onPositiveButtonClick(Pair<Long,Long> selection) {
|
||||
Calendar startCalendar = Calendar.getInstance();
|
||||
startCalendar.setTime(new Date(selection.first));
|
||||
Calendar endCalendar = Calendar.getInstance();
|
||||
endCalendar.setTime(new Date(selection.second));
|
||||
|
||||
setDiffDateText(startCalendar.getTime(), endCalendar.getTime());
|
||||
|
||||
List<ScaleMeasurement> rangeScaleMeasurementList = OpenScale.getInstance().getScaleMeasurementOfRangeDates(startCalendar.get(Calendar.YEAR), startCalendar.get(Calendar.MONTH), startCalendar.get(Calendar.DAY_OF_MONTH),
|
||||
endCalendar.get(Calendar.YEAR), endCalendar.get(Calendar.MONTH), endCalendar.get(Calendar.DAY_OF_MONTH));
|
||||
|
||||
prefs.edit().putLong("statistic_range_start_date", startCalendar.getTime().getTime()).commit();
|
||||
|
||||
updateStatistic(rangeScaleMeasurementList);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
|
||||
compareRecyclerView.setLayoutManager(layoutManager);
|
||||
|
||||
OpenScale.getInstance().getScaleMeasurementsLiveData().observe(getViewLifecycleOwner(), new Observer<List<ScaleMeasurement>>() {
|
||||
@Override
|
||||
@@ -171,206 +150,57 @@ public class StatisticsFragment extends Fragment {
|
||||
return statisticsView;
|
||||
}
|
||||
|
||||
public void updateOnView(List<ScaleMeasurement> scaleMeasurementList) {
|
||||
currentScaleUser = OpenScale.getInstance().getSelectedScaleUser();
|
||||
public void updateStatistic(List<ScaleMeasurement> rangeScaleMeasurementList) {
|
||||
compareRecyclerView.setVisibility(View.VISIBLE);
|
||||
statisticAdapter = new StatisticAdapter(getActivity(), rangeScaleMeasurementList);
|
||||
compareRecyclerView.setAdapter(statisticAdapter);
|
||||
|
||||
if (scaleMeasurementList.isEmpty()) {
|
||||
lastScaleMeasurement = new ScaleMeasurement();
|
||||
lastScaleMeasurement.setUserId(currentScaleUser.getId());
|
||||
lastScaleMeasurement.setWeight(currentScaleUser.getInitialWeight());
|
||||
firstScaleMeasurement = lastScaleMeasurement;
|
||||
countMeasurementTextView.setText(rangeScaleMeasurementList.size() + " " + getResources().getString(R.string.label_measurements));
|
||||
|
||||
ScaleMeasurement firstMeasurement;
|
||||
ScaleMeasurement lastMeasurement;
|
||||
|
||||
if (rangeScaleMeasurementList.isEmpty()) {
|
||||
firstMeasurement = new ScaleMeasurement();
|
||||
lastMeasurement = new ScaleMeasurement();
|
||||
} else if (rangeScaleMeasurementList.size() == 1) {
|
||||
firstMeasurement = rangeScaleMeasurementList.get(0);
|
||||
lastMeasurement = rangeScaleMeasurementList.get(0);
|
||||
} else {
|
||||
lastScaleMeasurement = scaleMeasurementList.get(0);
|
||||
firstScaleMeasurement = scaleMeasurementList.get(scaleMeasurementList.size() - 1);
|
||||
firstMeasurement = rangeScaleMeasurementList.get(rangeScaleMeasurementList.size() - 1);
|
||||
lastMeasurement = rangeScaleMeasurementList.get(0);
|
||||
}
|
||||
|
||||
updateStatistics(scaleMeasurementList);
|
||||
updateGoal();
|
||||
setDiffDateText(firstMeasurement.getDateTime(), lastMeasurement.getDateTime());
|
||||
}
|
||||
|
||||
private void updateGoal() {
|
||||
final Converters.WeightUnit unit = currentScaleUser.getScaleUnit();
|
||||
public void setDiffDateText(Date firstDate, Date secondDate) {
|
||||
String diffDateText = DateFormat.getDateInstance(DateFormat.MEDIUM).format(firstDate) + " - " +
|
||||
DateFormat.getDateInstance(DateFormat.MEDIUM).format(secondDate);
|
||||
|
||||
ScaleMeasurement goalScaleMeasurement = new ScaleMeasurement();
|
||||
goalScaleMeasurement.setUserId(currentScaleUser.getId());
|
||||
goalScaleMeasurement.setWeight(currentScaleUser.getGoalWeight());
|
||||
|
||||
txtGoalWeight.setText(String.format("%.1f %s",
|
||||
Converters.fromKilogram(goalScaleMeasurement.getWeight(), unit),
|
||||
unit.toString()));
|
||||
|
||||
txtGoalDiff.setText(String.format("%.1f %s",
|
||||
Converters.fromKilogram(goalScaleMeasurement.getWeight() - lastScaleMeasurement.getWeight(), unit),
|
||||
unit.toString()));
|
||||
|
||||
txtTotalWeightLost.setText(String.format("%.1f %s",
|
||||
Converters.fromKilogram(firstScaleMeasurement.getWeight() - lastScaleMeasurement.getWeight(), unit),
|
||||
unit.toString()));
|
||||
|
||||
Calendar goalCalendar = Calendar.getInstance();
|
||||
goalCalendar.setTime(currentScaleUser.getGoalDate());
|
||||
int days = Math.max(0, DateTimeHelpers.daysBetween(Calendar.getInstance(), goalCalendar));
|
||||
txtGoalDayLeft.setText(getResources().getQuantityString(R.plurals.label_days, days, days));
|
||||
|
||||
boolean isBmiEnabled = new MeasurementViewSettings(
|
||||
PreferenceManager.getDefaultSharedPreferences(getActivity()), BMIMeasurementView.KEY)
|
||||
.isEnabled();
|
||||
final float goalBmi = goalScaleMeasurement.getBMI(currentScaleUser.getBodyHeight());
|
||||
|
||||
txtLabelGoalWeight.setText(
|
||||
isBmiEnabled
|
||||
? Html.fromHtml(String.format(
|
||||
"%s<br><font color='grey'><small>%s: %.1f</small></font>",
|
||||
getResources().getString(R.string.label_goal_weight),
|
||||
getResources().getString(R.string.label_bmi),
|
||||
goalBmi))
|
||||
: getResources().getString(R.string.label_goal_weight));
|
||||
|
||||
txtLabelGoalDiff.setText(
|
||||
isBmiEnabled
|
||||
? Html.fromHtml(String.format(
|
||||
"%s<br><font color='grey'><small>%s: %.1f</small></font>",
|
||||
getResources().getString(R.string.label_weight_difference),
|
||||
getResources().getString(R.string.label_bmi),
|
||||
lastScaleMeasurement.getBMI(currentScaleUser.getBodyHeight()) - goalBmi))
|
||||
: getResources().getString(R.string.label_weight_difference));
|
||||
|
||||
txtLabelDayLeft.setText(
|
||||
Html.fromHtml(String.format(
|
||||
"%s<br><font color='grey'><small>%s %s</small></font>",
|
||||
getResources().getString(R.string.label_days_left),
|
||||
getResources().getString(R.string.label_goal_date_is),
|
||||
DateFormat.getDateInstance(DateFormat.LONG).format(currentScaleUser.getGoalDate()))));
|
||||
|
||||
txtLabelTotalWeightLost.setText(
|
||||
Html.fromHtml(String.format(
|
||||
"%s<br><font color='grey'><small>%s %.1f %s</small></font>",
|
||||
getResources().getString(R.string.label_total_weight_lost),
|
||||
getResources().getString(R.string.label_total_weight_lost_weight_reference),
|
||||
Converters.fromKilogram(firstScaleMeasurement.getWeight(), unit),
|
||||
unit.toString())));
|
||||
diffDateTextView.setText(diffDateText);
|
||||
}
|
||||
|
||||
private void updateStatistics(List<ScaleMeasurement> scaleMeasurementList) {
|
||||
radarChartWeek.clear();
|
||||
radarChartMonth.clear();
|
||||
public void updateOnView(List<ScaleMeasurement> scaleMeasurementList) {
|
||||
this.scaleMeasurementList = scaleMeasurementList;
|
||||
|
||||
Calendar histDate = Calendar.getInstance();
|
||||
Calendar weekPastDate = Calendar.getInstance();
|
||||
Calendar monthPastDate = Calendar.getInstance();
|
||||
Long prefDate = prefs.getLong("statistic_range_start_date", 0);
|
||||
|
||||
weekPastDate.setTime(lastScaleMeasurement.getDateTime());
|
||||
weekPastDate.add(Calendar.DATE, -7);
|
||||
if (prefDate != 0) {
|
||||
Calendar startCalendar = Calendar.getInstance();
|
||||
startCalendar.setTime(new Date(prefDate));
|
||||
Calendar endCalendar = Calendar.getInstance();
|
||||
endCalendar.setTime(new Date());
|
||||
|
||||
monthPastDate.setTime(lastScaleMeasurement.getDateTime());
|
||||
monthPastDate.add(Calendar.DATE, -30);
|
||||
setDiffDateText(startCalendar.getTime(), endCalendar.getTime());
|
||||
|
||||
ScaleMeasurement averageWeek = new ScaleMeasurement();
|
||||
ScaleMeasurement averageMonth = new ScaleMeasurement();
|
||||
List<ScaleMeasurement> rangeScaleMeasurementList = OpenScale.getInstance().getScaleMeasurementOfRangeDates(startCalendar.get(Calendar.YEAR), startCalendar.get(Calendar.MONTH), startCalendar.get(Calendar.DAY_OF_MONTH),
|
||||
endCalendar.get(Calendar.YEAR), endCalendar.get(Calendar.MONTH), endCalendar.get(Calendar.DAY_OF_MONTH));
|
||||
|
||||
ArrayList<RadarEntry> entriesLastMeasurement = new ArrayList<>();
|
||||
ArrayList<RadarEntry> entriesAvgWeek = new ArrayList<>();
|
||||
ArrayList<RadarEntry> entriesAvgMonth = new ArrayList<>();
|
||||
|
||||
for (ScaleMeasurement measurement : scaleMeasurementList) {
|
||||
histDate.setTime(measurement.getDateTime());
|
||||
|
||||
if (weekPastDate.before(histDate)) {
|
||||
averageWeek.add(measurement);
|
||||
}
|
||||
|
||||
if (monthPastDate.before(histDate)) {
|
||||
averageMonth.add(measurement);
|
||||
}
|
||||
updateStatistic(rangeScaleMeasurementList);
|
||||
} else {
|
||||
updateStatistic(scaleMeasurementList);
|
||||
}
|
||||
|
||||
averageWeek.divide(averageWeek.count());
|
||||
averageMonth.divide(averageMonth.count());
|
||||
|
||||
for (MeasurementView view : viewMeasurementsStatistics) {
|
||||
final FloatMeasurementView measurementView = (FloatMeasurementView) view;
|
||||
|
||||
Object[] extraData = new Object[3];
|
||||
extraData[0] = null; // not needed
|
||||
extraData[1] = null; // not needed
|
||||
extraData[2] = measurementView;
|
||||
|
||||
measurementView.loadFrom(averageMonth, null);
|
||||
entriesAvgMonth.add(new RadarEntry(measurementView.getValue(), extraData));
|
||||
|
||||
measurementView.loadFrom(averageWeek, null);
|
||||
entriesAvgWeek.add(new RadarEntry(measurementView.getValue(), extraData));
|
||||
|
||||
measurementView.loadFrom(lastScaleMeasurement, null);
|
||||
entriesLastMeasurement.add(new RadarEntry(measurementView.getValue(), extraData));
|
||||
}
|
||||
|
||||
RadarDataSet setLastMeasurement = new RadarDataSet(entriesLastMeasurement, getString(R.string.label_title_last_measurement));
|
||||
setLastMeasurement.setColor(ColorUtil.COLOR_BLUE);
|
||||
setLastMeasurement.setFillColor(ColorUtil.COLOR_BLUE);
|
||||
setLastMeasurement.setDrawFilled(true);
|
||||
setLastMeasurement.setFillAlpha(180);
|
||||
setLastMeasurement.setLineWidth(2f);
|
||||
setLastMeasurement.setDrawHighlightCircleEnabled(true);
|
||||
setLastMeasurement.setDrawHighlightIndicators(false);
|
||||
|
||||
RadarDataSet setAvgWeek = new RadarDataSet(entriesAvgWeek, getString(R.string.label_last_week));
|
||||
setAvgWeek.setColor(ColorUtil.COLOR_GREEN);
|
||||
setAvgWeek.setFillColor(ColorUtil.COLOR_GREEN);
|
||||
setAvgWeek.setDrawFilled(true);
|
||||
setAvgWeek.setFillAlpha(180);
|
||||
setAvgWeek.setLineWidth(2f);
|
||||
setAvgWeek.setDrawHighlightCircleEnabled(true);
|
||||
setAvgWeek.setDrawHighlightIndicators(false);
|
||||
|
||||
RadarDataSet setAvgMonth = new RadarDataSet(entriesAvgMonth, getString(R.string.label_last_month));
|
||||
setAvgMonth.setColor(ColorUtil.COLOR_GREEN);
|
||||
setAvgMonth.setFillColor(ColorUtil.COLOR_GREEN);
|
||||
setAvgMonth.setDrawFilled(true);
|
||||
setAvgMonth.setFillAlpha(180);
|
||||
setAvgMonth.setLineWidth(2f);
|
||||
setAvgMonth.setDrawHighlightCircleEnabled(true);
|
||||
setAvgMonth.setDrawHighlightIndicators(false);
|
||||
|
||||
ArrayList<IRadarDataSet> setsAvgWeek = new ArrayList<>();
|
||||
setsAvgWeek.add(setAvgWeek);
|
||||
setsAvgWeek.add(setLastMeasurement);
|
||||
|
||||
ArrayList<IRadarDataSet> setsAvgMonth = new ArrayList<>();
|
||||
setsAvgMonth.add(setAvgMonth);
|
||||
setsAvgMonth.add(setLastMeasurement);
|
||||
|
||||
RadarData dataAvgWeek = new RadarData(setsAvgWeek);
|
||||
dataAvgWeek.setValueTextSize(8f);
|
||||
dataAvgWeek.setDrawValues(false);
|
||||
dataAvgWeek.setValueFormatter(new ValueFormatter() {
|
||||
@Override
|
||||
public String getRadarLabel(RadarEntry radarEntry) {
|
||||
FloatMeasurementView measurementView = (FloatMeasurementView) radarEntry.getData();
|
||||
|
||||
return measurementView.getValueAsString(true);
|
||||
}
|
||||
});
|
||||
|
||||
RadarData dataAvgMonth = new RadarData(setsAvgMonth);
|
||||
dataAvgMonth.setValueTextSize(8f);
|
||||
dataAvgMonth.setDrawValues(false);
|
||||
dataAvgMonth.setValueFormatter(new ValueFormatter() {
|
||||
@Override
|
||||
public String getRadarLabel(RadarEntry radarEntry) {
|
||||
FloatMeasurementView measurementView = (FloatMeasurementView) radarEntry.getData();
|
||||
|
||||
return measurementView.getValueAsString(true);
|
||||
}
|
||||
});
|
||||
|
||||
radarChartWeek.setData(dataAvgWeek);
|
||||
radarChartMonth.setData(dataAvgMonth);
|
||||
|
||||
radarChartWeek.animateXY(1000, 1000);
|
||||
radarChartMonth.animateXY(1000, 1000);
|
||||
|
||||
radarChartWeek.invalidate();
|
||||
radarChartMonth.invalidate();
|
||||
}
|
||||
}
|
||||
|
5
android_app/app/src/main/res/drawable/ic_calendar.xml
Normal file
5
android_app/app/src/main/res/drawable/ic_calendar.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#000000"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M20,3h-1L19,1h-2v2L7,3L7,1L5,1v2L4,3c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,5c0,-1.1 -0.9,-2 -2,-2zM20,21L4,21L4,8h16v13z"/>
|
||||
</vector>
|
@@ -18,14 +18,14 @@
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/AppTheme.AppBarOverlay">
|
||||
android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay" />
|
||||
app:popupTheme="@style/ThemeOverlay.MaterialComponents.Dark" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
|
@@ -12,7 +12,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar"
|
||||
android:background="?attr/colorPrimaryDark">
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
|
@@ -6,7 +6,7 @@
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_inc"
|
||||
style="@style/Widget.AppCompat.Button.Borderless"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_dec"
|
||||
style="@style/Widget.AppCompat.Button.Borderless"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
|
@@ -115,6 +115,7 @@
|
||||
app:fabSize="mini"
|
||||
app:srcCompat="@drawable/ic_show"
|
||||
android:layout_below="@id/deleteMenu"
|
||||
app:backgroundTint="#33B5E5"
|
||||
app:layout_anchor="@id/editMenu"
|
||||
android:clickable="true"
|
||||
android:visibility="gone"
|
||||
|
@@ -1,248 +1,65 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="5dp">
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/scrollView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<TextView
|
||||
android:id="@+id/timePeriodView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="@string/label_time_period"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/datePickerView"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
android:id="@+id/diffDateTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="01.01.1900 - 01.01.2000"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/datePickerView"
|
||||
app:layout_constraintStart_toEndOf="@+id/timePeriodView"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoText="false"
|
||||
android:text="@string/label_title_goal"
|
||||
android:textSize="20dp"
|
||||
android:typeface="monospace" />
|
||||
<TextView
|
||||
android:id="@+id/withTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/label_with"
|
||||
app:layout_constraintEnd_toEndOf="@+id/timePeriodView"
|
||||
app:layout_constraintTop_toBottomOf="@+id/timePeriodView" />
|
||||
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@android:color/darker_gray" />
|
||||
<TextView
|
||||
android:id="@+id/countMeasurementTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="0 measurements"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toEndOf="@+id/diffDateTextView"
|
||||
app:layout_constraintStart_toStartOf="@+id/diffDateTextView"
|
||||
app:layout_constraintTop_toBottomOf="@+id/diffDateTextView" />
|
||||
|
||||
<TableLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_weight="90"
|
||||
android:stretchColumns="1">
|
||||
<ImageView
|
||||
android:id="@+id/datePickerView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/compareRecyclerView"
|
||||
app:layout_constraintStart_toEndOf="@+id/diffDateTextView"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_calendar" />
|
||||
|
||||
<TableRow
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:orientation="horizontal">
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/compareRecyclerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/countMeasurementTextView" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageGoalWeight"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/ic_target"
|
||||
android:tint="?attr/colorControlNormal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtLabelGoalWeight"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_column="1"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_weight="80"
|
||||
android:lines="2"
|
||||
android:password="false"
|
||||
android:phoneNumber="false"
|
||||
android:singleLine="false"
|
||||
android:text="Target weight"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="15dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtGoalWeight"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_column="2"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="20"
|
||||
android:gravity="right"
|
||||
android:text="-1 kg"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="15dp" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:id="@+id/tableRow9"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageGoalDiff"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/ic_difference"
|
||||
android:tint="?attr/colorControlNormal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtLabelGoalDiff"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_column="1"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_weight="80"
|
||||
android:lines="2"
|
||||
android:password="false"
|
||||
android:phoneNumber="false"
|
||||
android:singleLine="false"
|
||||
android:text="Weight difference"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="15dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtGoalDiff"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_column="2"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="20"
|
||||
android:gravity="right"
|
||||
android:text="-1 kg"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="15dp" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageTotalWeightLoss"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/ic_weight_loss"
|
||||
android:tint="?attr/colorControlNormal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtLabelTotalWeightLost"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_column="1"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_weight="80"
|
||||
android:lines="2"
|
||||
android:password="false"
|
||||
android:phoneNumber="false"
|
||||
android:singleLine="false"
|
||||
android:text="Target weight"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="15dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtTotalWeightLost"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_column="2"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="20"
|
||||
android:gravity="right"
|
||||
android:text="0 kg"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="15dp" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:id="@+id/tableRow10"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageDayLeft"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/ic_daysleft"
|
||||
android:tint="?attr/colorControlNormal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtLabelDayLeft"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_column="1"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_weight="80"
|
||||
android:lines="2"
|
||||
android:password="false"
|
||||
android:phoneNumber="false"
|
||||
android:singleLine="false"
|
||||
android:text="Days left"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="15dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtGoalDayLeft"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_column="2"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="20"
|
||||
android:gravity="right"
|
||||
android:text="-1 days"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="15dp" />
|
||||
</TableRow>
|
||||
|
||||
</TableLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/label_last_week"
|
||||
android:textSize="20dp"
|
||||
android:typeface="monospace" />
|
||||
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@android:color/darker_gray" />
|
||||
|
||||
<com.github.mikephil.charting.charts.RadarChart
|
||||
android:id="@+id/radarPastWeek"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/label_last_month"
|
||||
android:textSize="20dp"
|
||||
android:typeface="monospace" />
|
||||
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@android:color/darker_gray" />
|
||||
|
||||
<com.github.mikephil.charting.charts.RadarChart
|
||||
android:id="@+id/radarPastMonth"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
87
android_app/app/src/main/res/layout/item_statistic.xml
Normal file
87
android_app/app/src/main/res/layout/item_statistic.xml
Normal file
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10dp"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
app:cardCornerRadius="10dp"
|
||||
app:contentPadding="10dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/measurementName"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="TextView"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toStartOf="@+id/diffValueView"
|
||||
app:layout_constraintStart_toEndOf="@+id/iconView"
|
||||
app:layout_constraintTop_toTopOf="@+id/iconView" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/diffValueView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TextView"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/measurementName" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/startValueView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:text="TextView"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/iconView" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/iconView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="false"
|
||||
app:fabSize="mini"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_weight" />
|
||||
|
||||
<com.github.mikephil.charting.charts.LineChart
|
||||
android:id="@+id/diffChartView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/endValueView"
|
||||
app:layout_constraintStart_toEndOf="@+id/startValueView"
|
||||
app:layout_constraintTop_toBottomOf="@+id/measurementName" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/endValueView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TextView"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/startValueView" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</LinearLayout>
|
@@ -2,11 +2,11 @@
|
||||
<resources>
|
||||
<color name="blue_pressed">@android:color/holo_blue_dark</color>
|
||||
<color name="blue_normal">@android:color/holo_blue_light</color>
|
||||
<color name="gray_disabled">#ccc</color>
|
||||
<color name="gray_disabled">#cccccc</color>
|
||||
|
||||
<color name="primaryColor">#000000</color>
|
||||
<color name="primaryLightColor">@android:color/holo_blue_light</color>
|
||||
<color name="primaryDarkColor">#000000</color>
|
||||
|
||||
<color name="widgetTextColor">#555</color>
|
||||
<color name="widgetTextColor">#555555</color>
|
||||
</resources>
|
||||
|
@@ -53,6 +53,8 @@
|
||||
<string name="label_days_left">Days left</string>
|
||||
<string name="label_date">Date</string>
|
||||
<string name="label_time">Time</string>
|
||||
<string name="label_time_period">Time period</string>
|
||||
<string name="label_with">with</string>
|
||||
<string name="label_birthday">Birthday</string>
|
||||
<string name="label_user_name">Name</string>
|
||||
<string name="label_height">Height</string>
|
||||
@@ -69,6 +71,7 @@
|
||||
<string name="label_title_user">user</string>
|
||||
<string name="label_title_last_measurement">last measurement</string>
|
||||
<string name="label_title_goal">Goal</string>
|
||||
<string name="label_measurements">measurements</string>
|
||||
<string name="label_import">Import</string>
|
||||
<string name="label_export">Export</string>
|
||||
<string name="label_delete_all">Delete all</string>
|
||||
|
@@ -1,14 +1,16 @@
|
||||
<resources>
|
||||
<!-- Application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.DayNight">
|
||||
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
|
||||
<item name="colorPrimary">@color/primaryColor</item>
|
||||
<item name="colorOnPrimary">@color/primaryLightColor</item>
|
||||
<item name="colorPrimaryDark">@color/primaryDarkColor</item>
|
||||
<item name="colorAccent">@color/primaryLightColor</item>
|
||||
<item name="android:datePickerStyle">@style/DatePickerStyle</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme_Dark" parent="Theme.AppCompat.NoActionBar">
|
||||
<style name="AppTheme_Dark" parent="Theme.MaterialComponents.NoActionBar">
|
||||
<item name="colorPrimary">@color/primaryColor</item>
|
||||
<item name="colorOnPrimary">@color/primaryLightColor</item>
|
||||
<item name="colorPrimaryDark">@color/primaryDarkColor</item>
|
||||
<item name="colorAccent">@color/primaryLightColor</item>
|
||||
<item name="android:datePickerStyle">@style/DatePickerStyle</item>
|
||||
@@ -19,10 +21,6 @@
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
|
||||
<style name="DatePickerStyle" parent="@android:style/Widget.Material.Light.DatePicker">
|
||||
<item name="android:datePickerMode">spinner</item>
|
||||
</style>
|
||||
|
Reference in New Issue
Block a user