From c1182f23834e5a6640808118d38a41017146ffd4 Mon Sep 17 00:00:00 2001 From: OliE Date: Sun, 21 Jun 2015 18:29:43 +0200 Subject: [PATCH] redesign the overview fragment weight goal can be set data entries are now editable calculates the current BMI of a person --- android_app/app/src/main/AndroidManifest.xml | 1 + .../com/health/openscale/core/OpenScale.java | 30 +- .../health/openscale/core/ScaleDatabase.java | 62 ++ .../com/health/openscale/core/ScaleUser.java | 19 +- .../openscale/core/ScaleUserDatabase.java | 45 +- .../openscale/gui/EditDataActivity.java | 101 +++ .../openscale/gui/OverviewFragment.java | 416 ++++++++++-- .../health/openscale/gui/TableFragment.java | 16 + .../openscale/gui/UserSettingsActivity.java | 66 +- android_app/app/src/main/res/drawable/bmi.png | Bin 0 -> 1633 bytes .../app/src/main/res/drawable/lastmonth.png | Bin 0 -> 1431 bytes .../app/src/main/res/drawable/lastweek.png | Bin 0 -> 1033 bytes .../app/src/main/res/drawable/muscle.png | Bin 0 -> 1631 bytes .../app/src/main/res/drawable/water.png | Bin 0 -> 1224 bytes .../main/res/layout/activity_usersettings.xml | 86 ++- .../src/main/res/layout/fragment_overview.xml | 624 +++++++++++++++--- .../app/src/main/res/values/strings.xml | 30 +- 17 files changed, 1298 insertions(+), 198 deletions(-) create mode 100644 android_app/app/src/main/java/com/health/openscale/gui/EditDataActivity.java create mode 100644 android_app/app/src/main/res/drawable/bmi.png create mode 100644 android_app/app/src/main/res/drawable/lastmonth.png create mode 100644 android_app/app/src/main/res/drawable/lastweek.png create mode 100644 android_app/app/src/main/res/drawable/muscle.png create mode 100644 android_app/app/src/main/res/drawable/water.png diff --git a/android_app/app/src/main/AndroidManifest.xml b/android_app/app/src/main/AndroidManifest.xml index d0903303..4ea566eb 100644 --- a/android_app/app/src/main/AndroidManifest.xml +++ b/android_app/app/src/main/AndroidManifest.xml @@ -24,6 +24,7 @@ + diff --git a/android_app/app/src/main/java/com/health/openscale/core/OpenScale.java b/android_app/app/src/main/java/com/health/openscale/core/OpenScale.java index b237d1b5..7ae871c5 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/OpenScale.java +++ b/android_app/app/src/main/java/com/health/openscale/core/OpenScale.java @@ -66,7 +66,7 @@ public class OpenScale { return instance; } - public void addScaleUser(String name, String birthday, int body_height, int scale_unit) + public void addScaleUser(String name, String birthday, int body_height, int scale_unit, int gender, double goal_weight, String goal_date) { ScaleUser scaleUser = new ScaleUser(); @@ -75,6 +75,9 @@ public class OpenScale { scaleUser.birthday = new SimpleDateFormat("dd.MM.yyyy").parse(birthday); scaleUser.body_height = body_height; scaleUser.scale_unit = scale_unit; + scaleUser.gender = gender; + scaleUser.goal_weight = goal_weight; + scaleUser.goal_date = new SimpleDateFormat("dd.MM.yyyy").parse(goal_date); } catch (ParseException e) { Log.e("OpenScale", "Can't parse date time string while adding to the database"); @@ -120,7 +123,7 @@ public class OpenScale { scaleUserDB.deleteEntry(id); } - public void updateScaleUser(int id, String name, String birthday, int body_height, int scale_unit) + public void updateScaleUser(int id, String name, String birthday, int body_height, int scale_unit, int gender, double goal_weight, String goal_date) { ScaleUser scaleUser = new ScaleUser(); @@ -130,6 +133,9 @@ public class OpenScale { scaleUser.birthday = new SimpleDateFormat("dd.MM.yyyy").parse(birthday); scaleUser.body_height = body_height; scaleUser.scale_unit = scale_unit; + scaleUser.gender = gender; + scaleUser.goal_weight = goal_weight; + scaleUser.goal_date = new SimpleDateFormat("dd.MM.yyyy").parse(goal_date); } catch (ParseException e) { Log.e("OpenScale", "Can't parse date time string while adding to the database"); } @@ -137,10 +143,17 @@ public class OpenScale { scaleUserDB.updateScaleUser(scaleUser); } + public ArrayList getScaleDataList() { return scaleDataList; } + + public ScaleData getScaleData(long id) + { + return scaleDB.getDataEntry(id); + } + public void addScaleData(int user_id, String date_time, float weight, float fat, float water, float muscle) { ScaleData scaleData = new ScaleData(); @@ -161,6 +174,19 @@ public class OpenScale { updateScaleData(); } + public void updateScaleData(long id, float weight, float fat, float water, float muscle) { + ScaleData scaleData = new ScaleData(); + + scaleData.weight = weight; + scaleData.fat = fat; + scaleData.water = water; + scaleData.muscle = muscle; + + scaleDB.updateEntry(id, scaleData); + + updateScaleData(); + } + public void deleteScaleData(long id) { scaleDB.deleteEntry(id); diff --git a/android_app/app/src/main/java/com/health/openscale/core/ScaleDatabase.java b/android_app/app/src/main/java/com/health/openscale/core/ScaleDatabase.java index 6de798a3..e1d4b4ff 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/ScaleDatabase.java +++ b/android_app/app/src/main/java/com/health/openscale/core/ScaleDatabase.java @@ -112,6 +112,68 @@ public class ScaleDatabase extends SQLiteOpenHelper { return true; } + public void updateEntry(long id, ScaleData scaleData) { + SQLiteDatabase db = getWritableDatabase(); + + ContentValues values = new ContentValues(); + values.put(COLUMN_NAME_WEIGHT, scaleData.weight); + values.put(COLUMN_NAME_FAT, scaleData.fat); + values.put(COLUMN_NAME_WATER, scaleData.water); + values.put(COLUMN_NAME_MUSCLE, scaleData.muscle); + + db.update(TABLE_NAME, values, COLUMN_NAME_ID + "=" + id, null); + } + + public ScaleData getDataEntry(long id) + { + SQLiteDatabase db = getReadableDatabase(); + ScaleData scaleData = new ScaleData(); + + String[] projection = { + COLUMN_NAME_ID, + COLUMN_NAME_USER_ID, + COLUMN_NAME_DATE_TIME, + COLUMN_NAME_WEIGHT, + COLUMN_NAME_FAT, + COLUMN_NAME_WATER, + COLUMN_NAME_MUSCLE + }; + + Cursor cursorScaleDB = db.query( + TABLE_NAME, // The table to query + projection, // The columns to return + COLUMN_NAME_ID + "=?", // The columns for the WHERE clause + new String[] {Long.toString(id)}, // The values for the WHERE clause + null, // don't group the rows + null, // don't filter by row groups + null // The sort order + ); + + try { + cursorScaleDB.moveToFirst(); + + scaleData.id = cursorScaleDB.getLong(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_ID)); + scaleData.user_id = cursorScaleDB.getInt(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_USER_ID)); + String date_time = cursorScaleDB.getString(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_DATE_TIME)); + scaleData.weight = cursorScaleDB.getFloat(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_WEIGHT)); + scaleData.fat = cursorScaleDB.getFloat(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_FAT)); + scaleData.water = cursorScaleDB.getFloat(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_WATER)); + scaleData.muscle = cursorScaleDB.getFloat(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_MUSCLE)); + + scaleData.date_time = formatDateTime.parse(date_time); + + cursorScaleDB.moveToNext(); + + } catch (ParseException ex) { + Log.e("ScaleDatabase", "Can't parse the date time string: " + ex.getMessage()); + } + catch ( IllegalArgumentException ex) { + Log.e("ScaleDatabase", "Illegal argument while reading from scale database: " + ex.getMessage()); + } + + return scaleData; + } + public void deleteEntry(long id) { SQLiteDatabase db = getWritableDatabase(); diff --git a/android_app/app/src/main/java/com/health/openscale/core/ScaleUser.java b/android_app/app/src/main/java/com/health/openscale/core/ScaleUser.java index 41f5dc4b..e6662c60 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/ScaleUser.java +++ b/android_app/app/src/main/java/com/health/openscale/core/ScaleUser.java @@ -26,10 +26,25 @@ public class ScaleUser { public Date birthday; public int body_height; public int scale_unit; - + public int gender; + public double goal_weight; + public Date goal_date; + + public boolean isMale() + { + if (gender == 0) + return true; + + return false; + } + + public double getBMI(double weight) { + return weight / ((body_height / 100.0)*(body_height / 100.0)); + } + @Override public String toString() { - return "ID : " + id + " NAME: " + user_name + " BIRTHDAY: " + birthday.toString() + " BODY_HEIGHT: " + body_height + " SCALE_UNIT: " + UNIT_STRING[scale_unit]; + return "ID : " + id + " NAME: " + user_name + " BIRTHDAY: " + birthday.toString() + " BODY_HEIGHT: " + body_height + " SCALE_UNIT: " + UNIT_STRING[scale_unit] + " GENDER " + gender + " GOAL WEIGHT " + goal_weight + " GOAL DATE " + goal_date.toString(); } } diff --git a/android_app/app/src/main/java/com/health/openscale/core/ScaleUserDatabase.java b/android_app/app/src/main/java/com/health/openscale/core/ScaleUserDatabase.java index 41b11d5e..ca063b7e 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/ScaleUserDatabase.java +++ b/android_app/app/src/main/java/com/health/openscale/core/ScaleUserDatabase.java @@ -30,7 +30,7 @@ import java.util.ArrayList; import java.util.Locale; public class ScaleUserDatabase extends SQLiteOpenHelper { - private static final int DATABASE_VERSION = 1; + private static final int DATABASE_VERSION = 2; private static final String DATABASE_NAME = "openScaleUserDatabase.db"; private static final String TABLE_NAME = "scaleuserdata"; @@ -39,6 +39,9 @@ public class ScaleUserDatabase extends SQLiteOpenHelper { private static final String COLUMN_NAME_BIRTHDAY = "birthday"; private static final String COLUMN_NAME_BODY_HEIGHT = "body_height"; private static final String COLUMN_NAME_SCALE_UNIT = "scale_unit"; + private static final String COLUMN_NAME_GENDER = "gender"; + private static final String COLUMN_NAME_GOAL_WEIGHT = "goal_weight"; + private static final String COLUMN_NAME_GOAL_DATE = "goal_date"; private static final String SQL_CREATE_ENTRIES = "CREATE TABLE " + TABLE_NAME + " (" + @@ -46,7 +49,10 @@ public class ScaleUserDatabase extends SQLiteOpenHelper { COLUMN_NAME_USER_NAME + " TEXT," + COLUMN_NAME_BIRTHDAY + " TEXT," + COLUMN_NAME_BODY_HEIGHT + " INTEGER," + - COLUMN_NAME_SCALE_UNIT + " INTEGER" + + COLUMN_NAME_SCALE_UNIT + " INTEGER," + + COLUMN_NAME_GENDER + " INTEGER," + + COLUMN_NAME_GOAL_WEIGHT + " REAL," + + COLUMN_NAME_GOAL_DATE + " TEXT" + ")"; private static final String SQL_DELETE_ENTRIES = @@ -65,8 +71,11 @@ public class ScaleUserDatabase extends SQLiteOpenHelper { @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - db.execSQL(SQL_DELETE_ENTRIES); - onCreate(db); + if (oldVersion == 1 && newVersion == 2) { + db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + COLUMN_NAME_GENDER + " INTEGER DEFAULT 0"); + db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + COLUMN_NAME_GOAL_WEIGHT + " REAL DEFAULT 0"); + db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + COLUMN_NAME_GOAL_DATE + " TEXT DEFAULT '2014-01-01 00:00'"); + } } public void clearDatabase() { @@ -83,6 +92,9 @@ public class ScaleUserDatabase extends SQLiteOpenHelper { values.put(COLUMN_NAME_BIRTHDAY, formatDateTime.format(scaleUser.birthday)); values.put(COLUMN_NAME_BODY_HEIGHT, scaleUser.body_height); values.put(COLUMN_NAME_SCALE_UNIT, scaleUser.scale_unit); + values.put(COLUMN_NAME_GENDER, scaleUser.gender); + values.put(COLUMN_NAME_GOAL_WEIGHT, scaleUser.goal_weight); + values.put(COLUMN_NAME_GOAL_DATE, formatDateTime.format(scaleUser.goal_date)); try { @@ -112,6 +124,9 @@ public class ScaleUserDatabase extends SQLiteOpenHelper { values.put(COLUMN_NAME_BIRTHDAY, formatDateTime.format(scaleUser.birthday)); values.put(COLUMN_NAME_BODY_HEIGHT, scaleUser.body_height); values.put(COLUMN_NAME_SCALE_UNIT, scaleUser.scale_unit); + values.put(COLUMN_NAME_GENDER, scaleUser.gender); + values.put(COLUMN_NAME_GOAL_WEIGHT, scaleUser.goal_weight); + values.put(COLUMN_NAME_GOAL_DATE, formatDateTime.format(scaleUser.goal_date)); db.update(TABLE_NAME, values, COLUMN_NAME_ID + "=" + scaleUser.id, null); } @@ -126,7 +141,10 @@ public class ScaleUserDatabase extends SQLiteOpenHelper { COLUMN_NAME_USER_NAME, COLUMN_NAME_BIRTHDAY, COLUMN_NAME_BODY_HEIGHT, - COLUMN_NAME_SCALE_UNIT + COLUMN_NAME_SCALE_UNIT, + COLUMN_NAME_GENDER, + COLUMN_NAME_GOAL_WEIGHT, + COLUMN_NAME_GOAL_DATE }; Cursor cursorScaleDB = db.query( @@ -147,8 +165,12 @@ public class ScaleUserDatabase extends SQLiteOpenHelper { String birthday = cursorScaleDB.getString(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_BIRTHDAY)); scaleUser.body_height = cursorScaleDB.getInt(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_BODY_HEIGHT)); scaleUser.scale_unit = cursorScaleDB.getInt(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_SCALE_UNIT)); + scaleUser.gender = cursorScaleDB.getInt(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_GENDER)); + scaleUser.goal_weight = cursorScaleDB.getFloat(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_GOAL_WEIGHT)); + String goal_date = cursorScaleDB.getString(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_GOAL_DATE)); scaleUser.birthday = formatDateTime.parse(birthday); + scaleUser.goal_date = formatDateTime.parse(goal_date); cursorScaleDB.moveToNext(); @@ -171,7 +193,10 @@ public class ScaleUserDatabase extends SQLiteOpenHelper { COLUMN_NAME_USER_NAME, COLUMN_NAME_BIRTHDAY, COLUMN_NAME_BODY_HEIGHT, - COLUMN_NAME_SCALE_UNIT + COLUMN_NAME_SCALE_UNIT, + COLUMN_NAME_GENDER, + COLUMN_NAME_GOAL_WEIGHT, + COLUMN_NAME_GOAL_DATE }; String sortOrder = COLUMN_NAME_ID + " DESC"; @@ -197,8 +222,12 @@ public class ScaleUserDatabase extends SQLiteOpenHelper { String birthday = cursorScaleDB.getString(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_BIRTHDAY)); scaleUser.body_height = cursorScaleDB.getInt(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_BODY_HEIGHT)); scaleUser.scale_unit = cursorScaleDB.getInt(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_SCALE_UNIT)); - - scaleUser.birthday = formatDateTime.parse(birthday); + scaleUser.gender = cursorScaleDB.getInt(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_GENDER)); + scaleUser.goal_weight = cursorScaleDB.getFloat(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_GOAL_WEIGHT)); + String goal_date = cursorScaleDB.getString(cursorScaleDB.getColumnIndexOrThrow(COLUMN_NAME_GOAL_DATE)); + + scaleUser.birthday = formatDateTime.parse(birthday); + scaleUser.goal_date = formatDateTime.parse(goal_date); scaleUserDBEntries.add(scaleUser); diff --git a/android_app/app/src/main/java/com/health/openscale/gui/EditDataActivity.java b/android_app/app/src/main/java/com/health/openscale/gui/EditDataActivity.java new file mode 100644 index 00000000..86ffa533 --- /dev/null +++ b/android_app/app/src/main/java/com/health/openscale/gui/EditDataActivity.java @@ -0,0 +1,101 @@ +/* Copyright (C) 2014 olie.xdev +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see +*/ +package com.health.openscale.gui; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; + +import com.health.openscale.R; +import com.health.openscale.core.OpenScale; +import com.health.openscale.core.ScaleData; + +import java.text.SimpleDateFormat; + +public class EditDataActivity extends Activity { + + private EditText txtWeight; + private EditText txtFat; + private EditText txtWater; + private EditText txtMuscle; + + private Button btnOk; + private Button btnCancel; + + private long id; + + private Context context; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_editdata); + + context = this; + + txtWeight = (EditText) findViewById(R.id.txtWeight); + txtFat = (EditText) findViewById(R.id.txtFat); + txtWater = (EditText) findViewById(R.id.txtWater); + txtMuscle = (EditText) findViewById(R.id.txtMuscle); + + btnOk = (Button)findViewById(R.id.btnOk); + btnCancel = (Button)findViewById(R.id.btnCancel); + + btnOk.setOnClickListener(new onClickListenerOk()); + btnCancel.setOnClickListener(new onClickListenerCancel()); + + id = getIntent().getExtras().getLong("id"); + + OpenScale openScale = OpenScale.getInstance(context); + + ScaleData editScaleData = openScale.getScaleData(id); + + txtWeight.setText(editScaleData.weight+""); + txtFat.setText(editScaleData.fat+""); + txtWater.setText(editScaleData.water+""); + txtMuscle.setText(editScaleData.muscle+""); + + setTitle(getResources().getString(R.string.title_edit_data_entry) + ": " + new SimpleDateFormat("dd. MMM yyyy (EE) HH:mm").format(editScaleData.date_time)); + + } + + + private class onClickListenerOk implements View.OnClickListener { + @Override + public void onClick(View v) { + float weight = Float.valueOf(txtWeight.getText().toString()); + float fat = Float.valueOf(txtFat.getText().toString()); + float water = Float.valueOf(txtWater.getText().toString()); + float muscle = Float.valueOf(txtMuscle.getText().toString()); + + OpenScale openScale = OpenScale.getInstance(context); + + openScale.updateScaleData(id, weight, fat, water, muscle); + + finish(); + } + } + + private class onClickListenerCancel implements View.OnClickListener { + @Override + public void onClick(View v) { + finish(); + } + } +} diff --git a/android_app/app/src/main/java/com/health/openscale/gui/OverviewFragment.java b/android_app/app/src/main/java/com/health/openscale/gui/OverviewFragment.java index 95c6aff0..da1d9f59 100644 --- a/android_app/app/src/main/java/com/health/openscale/gui/OverviewFragment.java +++ b/android_app/app/src/main/java/com/health/openscale/gui/OverviewFragment.java @@ -17,10 +17,14 @@ package com.health.openscale.gui; import android.app.Activity; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.res.Configuration; +import android.graphics.Color; import android.os.Bundle; +import android.preference.PreferenceManager; import android.support.v4.app.Fragment; +import android.text.Html; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -34,47 +38,114 @@ import com.health.openscale.core.ScaleUser; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Calendar; import java.util.List; +import java.util.concurrent.TimeUnit; import lecho.lib.hellocharts.model.ArcValue; +import lecho.lib.hellocharts.model.Axis; +import lecho.lib.hellocharts.model.AxisValue; +import lecho.lib.hellocharts.model.Line; +import lecho.lib.hellocharts.model.LineChartData; import lecho.lib.hellocharts.model.PieChartData; +import lecho.lib.hellocharts.model.PointValue; import lecho.lib.hellocharts.model.SimpleValueFormatter; import lecho.lib.hellocharts.util.Utils; +import lecho.lib.hellocharts.view.LineChartView; import lecho.lib.hellocharts.view.PieChartView; public class OverviewFragment extends Fragment implements FragmentUpdateListener { private View overviewView; - private TextView txtOverviewTitle; - private PieChartView pieChart; - private TextView txtAvgWeight; - private TextView txtAvgFat; - private TextView txtAvgWater; - private TextView txtAvgMuscle; + private TextView txtTitleUser; + private TextView txtTitleLastMeasurement; + private TextView txtTitleGoal; + private TextView txtTitleStatistics; + + private TextView txtWeightLast; + private TextView txtBMILast; + private TextView txtWaterLast; + private TextView txtMuscleLast; + private TextView txtFatLast; + + private TextView txtGoalWeight; + private TextView txtGoalDiff; + private TextView txtGoalDayLeft; + + private TextView txtAvgWeek; + private TextView txtAvgMonth; + + private TextView txtLabelWeight; + private TextView txtLabelBMI; + private TextView txtLabelFat; + private TextView txtLabelMuscle; + private TextView txtLabelWater; + + private TextView txtLabelGoalWeight; + private TextView txtLabelGoalDiff; + private TextView txtLabelDayLeft; + + private TextView txtLabelAvgWeek; + private TextView txtLabelAvgMonth; + + private PieChartView pieChartLast; + private LineChartView lineChartLast; + + private SharedPreferences prefs; private ScaleData lastScaleData; + private ScaleUser currentScaleUser; - @Override + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { overviewView = inflater.inflate(R.layout.fragment_overview, container, false); - txtOverviewTitle = (TextView) overviewView.findViewById(R.id.txtOverviewTitle); - pieChart = (PieChartView) overviewView.findViewById(R.id.pieChart); - txtAvgWeight = (TextView) overviewView.findViewById(R.id.txtAvgWeight); - txtAvgFat = (TextView) overviewView.findViewById(R.id.txtAvgFat); - txtAvgWater = (TextView) overviewView.findViewById(R.id.txtAvgWater); - txtAvgMuscle = (TextView) overviewView.findViewById(R.id.txtAvgMuscle); + txtTitleUser = (TextView) overviewView.findViewById(R.id.txtTitleUser); + txtTitleLastMeasurement = (TextView) overviewView.findViewById(R.id.txtTitleLastMeasurment); + txtTitleGoal = (TextView) overviewView.findViewById(R.id.txtTitleGoal); + txtTitleStatistics = (TextView) overviewView.findViewById(R.id.txtTitleStatistics); - pieChart.setOnValueTouchListener(new PieChartTouchListener()); - pieChart.setChartRotationEnabled(false); + txtWeightLast = (TextView) overviewView.findViewById(R.id.txtWeightLast); + txtBMILast = (TextView) overviewView.findViewById(R.id.txtBMILast); + txtWaterLast = (TextView) overviewView.findViewById(R.id.txtWaterLast); + txtMuscleLast = (TextView) overviewView.findViewById(R.id.txtMuscleLast); + txtFatLast = (TextView) overviewView.findViewById(R.id.txtFatLast); + + txtGoalWeight = (TextView) overviewView.findViewById(R.id.txtGoalWeight); + txtGoalDiff = (TextView) overviewView.findViewById(R.id.txtGoalDiff); + txtGoalDayLeft = (TextView) overviewView.findViewById(R.id.txtGoalDayLeft); + + txtAvgWeek = (TextView) overviewView.findViewById(R.id.txtAvgWeek); + txtAvgMonth = (TextView) overviewView.findViewById(R.id.txtAvgMonth); + + txtLabelWeight = (TextView) overviewView.findViewById(R.id.txtLabelWeight); + txtLabelBMI = (TextView) overviewView.findViewById(R.id.txtLabelBMI); + txtLabelFat = (TextView) overviewView.findViewById(R.id.txtLabelFat); + txtLabelMuscle = (TextView) overviewView.findViewById(R.id.txtLabelMuscle); + txtLabelWater = (TextView) overviewView.findViewById(R.id.txtLabelWater); + + txtLabelGoalWeight = (TextView) overviewView.findViewById(R.id.txtLabelGoalWeight); + txtLabelGoalDiff = (TextView) overviewView.findViewById(R.id.txtLabelGoalDiff); + txtLabelDayLeft = (TextView) overviewView.findViewById(R.id.txtLabelDayLeft); + + txtLabelAvgWeek = (TextView) overviewView.findViewById(R.id.txtLabelAvgWeek); + txtLabelAvgMonth = (TextView) overviewView.findViewById(R.id.txtLabelAvgMonth); + + pieChartLast = (PieChartView) overviewView.findViewById(R.id.pieChartLast); + lineChartLast = (LineChartView) overviewView.findViewById(R.id.lineChartLast); + + pieChartLast.setOnValueTouchListener(new PieChartLastTouchListener()); + pieChartLast.setChartRotationEnabled(false); overviewView.findViewById(R.id.btnInsertData).setOnClickListener(new View.OnClickListener() { public void onClick(View view) { btnOnClickInsertData(); } }); - + + prefs = PreferenceManager.getDefaultSharedPreferences(overviewView.getContext()); + updateOnView(OpenScale.getInstance(overviewView.getContext()).getScaleDataList()); return overviewView; @@ -83,66 +154,287 @@ public class OverviewFragment extends Fragment implements FragmentUpdateListener @Override public void updateOnView(ArrayList scaleDataList) { - ScaleUser scaleUser = OpenScale.getInstance(overviewView.getContext()).getSelectedScaleUser(); + currentScaleUser = OpenScale.getInstance(overviewView.getContext()).getSelectedScaleUser(); - txtOverviewTitle.setText(getResources().getString(R.string.label_overview_title_start) + " " + scaleUser.user_name + " " + getResources().getString(R.string.label_overview_title_end)); - - List arcValues = new ArrayList(); - - if (scaleDataList.isEmpty()) { + if (scaleDataList.isEmpty()) { lastScaleData = null; return; } lastScaleData = scaleDataList.get(0); - - arcValues.add(new ArcValue(lastScaleData.fat, Utils.COLOR_ORANGE)); - arcValues.add(new ArcValue(lastScaleData.water, Utils.COLOR_BLUE)); - arcValues.add(new ArcValue(lastScaleData.muscle, Utils.COLOR_GREEN)); - - PieChartData pieChartData = new PieChartData(arcValues); - pieChartData.setHasLabels(true); + + txtTitleUser.setText(getResources().getString(R.string.label_title_user).toUpperCase() + " " + currentScaleUser.user_name); + txtTitleLastMeasurement.setText(getResources().getString(R.string.label_title_last_measurement).toUpperCase()); + txtTitleGoal.setText(getResources().getString(R.string.label_title_goal).toUpperCase()); + txtTitleStatistics.setText(getResources().getString(R.string.label_title_statistics).toUpperCase()); + + updateLastPieChart(); + updateLastLineChart(scaleDataList); + updateLastMeasurement(); + updateGoal(scaleDataList); + updateStatistics(scaleDataList); + } + + private void updateLastMeasurement() { + txtWeightLast.setText(lastScaleData.weight + " " + ScaleUser.UNIT_STRING[currentScaleUser.scale_unit]); + txtBMILast.setText(String.format("%.1f", currentScaleUser.getBMI(lastScaleData.weight))); + txtFatLast.setText(lastScaleData.fat + " %"); + txtWaterLast.setText(lastScaleData.water + " %"); + txtMuscleLast.setText(lastScaleData.muscle + " %"); + } + + private void updateGoal(ArrayList scaleDataList) { + txtGoalWeight.setText(currentScaleUser.goal_weight + " " + ScaleUser.UNIT_STRING[currentScaleUser.scale_unit]); + + double weight_diff = currentScaleUser.goal_weight - lastScaleData.weight; + txtGoalDiff.setText(weight_diff + " " + ScaleUser.UNIT_STRING[currentScaleUser.scale_unit]); + + Calendar goalDate = Calendar.getInstance(); + Calendar curDate = Calendar.getInstance(); + goalDate.setTime(currentScaleUser.goal_date); + + long days = daysBetween(curDate, goalDate); + txtGoalDayLeft.setText(days + " " + getResources().getString(R.string.label_days)); + + txtLabelGoalWeight.setText(Html.fromHtml(getResources().getString(R.string.label_weight_goal) + "
BMI " + String.format("%.1f", currentScaleUser.getBMI(currentScaleUser.goal_weight)) + " ")); + txtLabelGoalDiff.setText(Html.fromHtml(getResources().getString(R.string.label_weight_difference) + "
BMI " + String.format("%.1f", currentScaleUser.getBMI(lastScaleData.weight) - currentScaleUser.getBMI(currentScaleUser.goal_weight)) + " ")); + txtLabelDayLeft.setText(Html.fromHtml(getResources().getString(R.string.label_days_left) + "
" + getResources().getString(R.string.label_goal_date_is) + " " + new SimpleDateFormat("dd. MMM yyyy (EE)").format(currentScaleUser.goal_date) + " ")); + + if (scaleDataList.size() > 2) { + ScaleData diffScaleData = scaleDataList.get(1); + + double diffWeight = lastScaleData.weight - diffScaleData.weight; + double diffBMI = currentScaleUser.getBMI(lastScaleData.weight) - currentScaleUser.getBMI(diffScaleData.weight); + double diffFat = lastScaleData.fat - diffScaleData.fat; + double diffMuscle = lastScaleData.muscle - diffScaleData.muscle; + double diffWater = lastScaleData.water - diffScaleData.water; + + if (diffWeight > 0.0) + txtLabelWeight.setText(Html.fromHtml(getResources().getString(R.string.label_weight) + "
" + String.format("%.1f ", diffWeight) + ScaleUser.UNIT_STRING[currentScaleUser.scale_unit] + "")); + else + txtLabelWeight.setText(Html.fromHtml(getResources().getString(R.string.label_weight) + "
" + String.format("%.1f ", diffWeight) + ScaleUser.UNIT_STRING[currentScaleUser.scale_unit] + "")); + + + if (diffBMI > 0.0) + txtLabelBMI.setText(Html.fromHtml(getResources().getString(R.string.label_bmi) + "
" + String.format("%.1f", diffBMI) + "")); + else + txtLabelBMI.setText(Html.fromHtml(getResources().getString(R.string.label_bmi) + "
" + String.format("%.1f", diffBMI) + "")); + + if (diffFat > 0.0) + txtLabelFat.setText(Html.fromHtml(getResources().getString(R.string.label_fat) + "
" + String.format("%.1f", diffFat) + "%")); + else + txtLabelFat.setText(Html.fromHtml(getResources().getString(R.string.label_fat) + "
" + String.format("%.1f", diffFat) + "%")); + + if (diffMuscle > 0.0) + txtLabelMuscle.setText(Html.fromHtml(getResources().getString(R.string.label_muscle) + "
" + String.format("%.1f", diffMuscle) + "%")); + else + txtLabelMuscle.setText(Html.fromHtml(getResources().getString(R.string.label_muscle) + "
" + String.format("%.1f", diffMuscle) + "%")); + + if (diffWater > 0.0) + txtLabelWater.setText(Html.fromHtml(getResources().getString(R.string.label_water) + "
" + String.format("%.1f", diffWater) + "%")); + else + txtLabelWater.setText(Html.fromHtml(getResources().getString(R.string.label_water) + "
" + String.format("%.1f", diffWater) + "%")); + } + } + + private void updateStatistics(ArrayList scaleDataList) { + Calendar histDate = Calendar.getInstance(); + Calendar weekPastDate = Calendar.getInstance(); + Calendar monthPastDate = Calendar.getInstance(); + + weekPastDate.setTime(lastScaleData.date_time); + weekPastDate.add(Calendar.DATE, -7); + + monthPastDate.setTime(lastScaleData.date_time); + monthPastDate.add(Calendar.DATE, -30); + + int weekSize = 0; + float weekAvgWeight = 0; + float weekAvgBMI = 0; + float weekAvgFat = 0; + float weekAvgWater = 0; + float weekAvgMuscle = 0; + + int monthSize = 0; + float monthAvgWeight = 0; + float monthAvgBMI = 0; + float monthAvgFat = 0; + float monthAvgWater = 0; + float monthAvgMuscle = 0; + + for (ScaleData scaleData : scaleDataList) + { + histDate.setTime(scaleData.date_time); + + if (weekPastDate.before(histDate)) { + weekSize++; + + weekAvgWeight += scaleData.weight; + weekAvgBMI += currentScaleUser.getBMI(scaleData.weight); + weekAvgFat += scaleData.fat; + weekAvgWater += scaleData.water; + weekAvgMuscle += scaleData.muscle; + } + + if (monthPastDate.before(histDate)) { + monthSize++; + + monthAvgWeight += scaleData.weight; + monthAvgBMI += currentScaleUser.getBMI(scaleData.weight); + monthAvgFat += scaleData.fat; + monthAvgWater += scaleData.water; + monthAvgMuscle += scaleData.muscle; + } else { + break; + } + } + + weekAvgWeight /= weekSize; + weekAvgBMI /= weekSize; + weekAvgFat /= weekSize; + weekAvgWater /= weekSize; + weekAvgMuscle /= weekSize; + + monthAvgWeight /= monthSize; + monthAvgBMI /= monthSize; + monthAvgFat /= monthSize; + monthAvgWater /= monthSize; + monthAvgMuscle /= monthSize; + + txtLabelAvgWeek.setText(Html.fromHtml(getResources().getString(R.string.label_last_week) + "
" + String.format("[Ø-"+getResources().getString(R.string.label_weight)+": %.1f" + ScaleUser.UNIT_STRING[currentScaleUser.scale_unit] + "] [Ø-"+getResources().getString(R.string.label_bmi)+": %.1f] [Ø-"+getResources().getString(R.string.label_fat)+": %.1f%%] [Ø-"+getResources().getString(R.string.label_muscle)+": %.1f%%] [Ø-"+getResources().getString(R.string.label_water)+": %.1f%%]", weekAvgWeight, weekAvgBMI, weekAvgFat, weekAvgMuscle, weekAvgWater) + "")); + txtLabelAvgMonth.setText(Html.fromHtml(getResources().getString(R.string.label_last_month) + "
" + String.format("[Ø-"+getResources().getString(R.string.label_weight)+": %.1f" + ScaleUser.UNIT_STRING[currentScaleUser.scale_unit] + "] [Ø-"+getResources().getString(R.string.label_bmi)+": %.1f] [Ø-"+getResources().getString(R.string.label_fat)+": %.1f%%] [Ø-"+getResources().getString(R.string.label_muscle)+": %.1f%%] [Ø-"+getResources().getString(R.string.label_water)+": %.1f%%]", monthAvgWeight, monthAvgBMI, monthAvgFat, monthAvgMuscle, monthAvgWater) + "")); + + txtAvgWeek.setText(weekSize + " " + getResources().getString(R.string.label_measures)); + txtAvgMonth.setText(monthSize + " " + getResources().getString(R.string.label_measures)); + } + + private void updateLastLineChart(ArrayList scaleDataList) { + List axisValues = new ArrayList(); + + List valuesWeight = new ArrayList(); + List valuesFat = new ArrayList(); + List valuesWater = new ArrayList(); + List valuesMuscle = new ArrayList(); + List lines = new ArrayList(); + + int max_i = 7; + + if (scaleDataList.size() < 7) { + max_i = scaleDataList.size(); + } + + Calendar histDate = Calendar.getInstance(); + Calendar lastDate = Calendar.getInstance(); + + lastDate.setTime(scaleDataList.get(0).date_time); + + for (int i=0; i arcValuesLast = new ArrayList(); + + arcValuesLast.add(new ArcValue(lastScaleData.fat, Utils.COLOR_ORANGE)); + arcValuesLast.add(new ArcValue(lastScaleData.water, Utils.COLOR_BLUE)); + arcValuesLast.add(new ArcValue(lastScaleData.muscle, Utils.COLOR_GREEN)); + + PieChartData pieChartData = new PieChartData(arcValuesLast); + pieChartData.setHasLabels(false); pieChartData.setFormatter(new SimpleValueFormatter(1, false, null, " %".toCharArray())); - pieChartData.setHasCenterCircle(true); - pieChartData.setCenterText1(Float.toString(lastScaleData.weight) + " " + ScaleUser.UNIT_STRING[scaleUser.scale_unit]); - pieChartData.setCenterText2(new SimpleDateFormat("dd. MMM yyyy (EE)").format(lastScaleData.date_time)); + pieChartData.setHasCenterCircle(true); + pieChartData.setCenterText1(Float.toString(lastScaleData.weight) + " " + ScaleUser.UNIT_STRING[currentScaleUser.scale_unit]); + pieChartData.setCenterText2(new SimpleDateFormat("dd. MMM yyyy").format(lastScaleData.date_time)); + if ((getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE || - (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) { - pieChartData.setCenterText1FontSize(33); + (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) { + pieChartData.setCenterText1FontSize(25); pieChartData.setCenterText2FontSize(14); } else { - pieChartData.setCenterText1FontSize(12); + pieChartData.setCenterText1FontSize(10); pieChartData.setCenterText2FontSize(8); pieChartData.setValueLabelTextSize(8); } - - pieChart.setPieChartData(pieChartData); - - double avgWeight = 0; - double avgFat = 0; - double avgWater = 0; - double avgMuscle = 0; - - for (ScaleData scaleData : scaleDataList) - { - avgWeight += scaleData.weight; - avgFat += scaleData.fat; - avgWater += scaleData.water; - avgMuscle += scaleData.muscle; - } - - avgWeight = avgWeight / scaleDataList.size(); - avgFat = avgFat / scaleDataList.size(); - avgWater = avgWater / scaleDataList.size(); - avgMuscle = avgMuscle / scaleDataList.size(); - - txtAvgWeight.setText(String.format( "%.1f " + ScaleUser.UNIT_STRING[scaleUser.scale_unit], avgWeight)); - txtAvgFat.setText(String.format( "%.1f %%", avgFat)); - txtAvgWater.setText(String.format( "%.1f %%", avgWater)); - txtAvgMuscle.setText(String.format( "%.1f %%", avgMuscle)); - } + + pieChartLast.setPieChartData(pieChartData); + } + + private long daysBetween(Calendar startDate, Calendar endDate) { + long end = endDate.getTimeInMillis(); + long start = startDate.getTimeInMillis(); + return TimeUnit.MILLISECONDS.toDays(Math.abs(end - start)); + } public void btnOnClickInsertData() { @@ -150,7 +442,7 @@ public class OverviewFragment extends Fragment implements FragmentUpdateListener startActivityForResult(intent, 1); } - private class PieChartTouchListener implements PieChartView.PieChartOnValueTouchListener + private class PieChartLastTouchListener implements PieChartView.PieChartOnValueTouchListener { @Override public void onValueTouched(int i, ArcValue arcValue) diff --git a/android_app/app/src/main/java/com/health/openscale/gui/TableFragment.java b/android_app/app/src/main/java/com/health/openscale/gui/TableFragment.java index 738237ad..a879e819 100644 --- a/android_app/app/src/main/java/com/health/openscale/gui/TableFragment.java +++ b/android_app/app/src/main/java/com/health/openscale/gui/TableFragment.java @@ -18,6 +18,7 @@ package com.health.openscale.gui; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; +import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.res.Configuration; @@ -154,6 +155,7 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { deleteButton.setOnClickListener(new onClickListenerDelete()); dataRow.addView(deleteButton); + dataRow.setOnClickListener(new onClickListenerRow()); if ((getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) != Configuration.SCREENLAYOUT_SIZE_XLARGE && (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) != Configuration.SCREENLAYOUT_SIZE_LARGE) @@ -170,6 +172,20 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { } } + private class onClickListenerRow implements View.OnClickListener { + + @Override + public void onClick(View v) { + TableRow dataRow = (TableRow)v; + TextView idTextView = (TextView) dataRow.getChildAt(0); + long id = Long.parseLong(idTextView.getText().toString()); + + Intent intent = new Intent(tableView.getContext(), EditDataActivity.class); + intent.putExtra("id", id); + startActivityForResult(intent, 1); + } + } + private class onClickListenerImport implements View.OnClickListener { @Override public void onClick(View v) { diff --git a/android_app/app/src/main/java/com/health/openscale/gui/UserSettingsActivity.java b/android_app/app/src/main/java/com/health/openscale/gui/UserSettingsActivity.java index 7671257c..9a3468cb 100644 --- a/android_app/app/src/main/java/com/health/openscale/gui/UserSettingsActivity.java +++ b/android_app/app/src/main/java/com/health/openscale/gui/UserSettingsActivity.java @@ -47,14 +47,18 @@ public class UserSettingsActivity extends Activity { private EditText txtUserName; private EditText txtBodyHeight; private EditText txtBirthday; + private EditText txtGoalWeight; + private EditText txtGoalDate; private RadioGroup radioScaleUnit; + private RadioGroup radioGender; private Button btnBirthdaySet; + private Button btnGoalDateSet; private Button btnOk; private Button btnCancel; private Button btnDelete; - private SimpleDateFormat birthdayFormat = new SimpleDateFormat("dd.MM.yyyy"); + private SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy"); private Context context; @@ -67,10 +71,14 @@ public class UserSettingsActivity extends Activity { txtUserName = (EditText) findViewById(R.id.txtUserName); txtBodyHeight = (EditText) findViewById(R.id.txtBodyHeight); radioScaleUnit = (RadioGroup) findViewById(R.id.groupScaleUnit); + radioGender = (RadioGroup) findViewById(R.id.groupGender); + txtGoalWeight = (EditText) findViewById(R.id.txtGoalWeight); txtBirthday = (EditText) findViewById(R.id.txtBirthday); + txtGoalDate = (EditText) findViewById(R.id.txtGoalDate); btnBirthdaySet = (Button) findViewById(R.id.btnDateSet); + btnGoalDateSet = (Button) findViewById(R.id.btnGoalDateSet); btnDelete = (Button) findViewById(R.id.btnDelete); btnOk = (Button)findViewById(R.id.btnOk); btnCancel = (Button)findViewById(R.id.btnCancel); @@ -79,8 +87,11 @@ public class UserSettingsActivity extends Activity { btnCancel.setOnClickListener(new onClickListenerCancel()); btnDelete.setOnClickListener(new onClickListenerDelete()); btnBirthdaySet.setOnClickListener(new onClickListenerBirthdaySet()); + btnGoalDateSet.setOnClickListener(new onClickListenerGoalDateSet()); - txtBirthday.setText(birthdayFormat.format(new Date())); + txtBirthday.setText(dateFormat.format(new Date())); + + txtGoalDate.setText(dateFormat.format(new Date())); if (getIntent().getExtras().getInt("mode") == EDIT_USER_REQUEST) { @@ -102,9 +113,11 @@ public class UserSettingsActivity extends Activity { txtUserName.setText(scaleUser.user_name); txtBodyHeight.setText(Integer.toString(scaleUser.body_height)); - txtBirthday.setText(birthdayFormat.format(scaleUser.birthday)); + txtBirthday.setText(dateFormat.format(scaleUser.birthday)); + txtGoalDate.setText(dateFormat.format(scaleUser.goal_date)); + txtGoalWeight.setText(scaleUser.goal_weight+""); - switch (scaleUser.scale_unit) + switch (scaleUser.scale_unit) { case 0: radioScaleUnit.check(R.id.btnRadioKG); @@ -116,6 +129,16 @@ public class UserSettingsActivity extends Activity { radioScaleUnit.check(R.id.btnRadioST); break; } + + switch (scaleUser.gender) + { + case 0: + radioGender.check(R.id.btnRadioMale); + break; + case 1: + radioGender.check(R.id.btnRadioWoman); + break; + } } private boolean validateInput() @@ -144,6 +167,13 @@ public class UserSettingsActivity extends Activity { } }; + private DatePickerDialog.OnDateSetListener goalDatePickerListener = new DatePickerDialog.OnDateSetListener() { + @Override + public void onDateSet(DatePicker view, int selectedYear, int selectedMonth, int selectedDay) { + txtGoalDate.setText(String.format("%02d.%02d.%04d", selectedDay, selectedMonth + 1, selectedYear)); + } + }; + private class onClickListenerDelete implements View.OnClickListener { @Override public void onClick(View v) { @@ -197,6 +227,8 @@ public class UserSettingsActivity extends Activity { String name = txtUserName.getText().toString(); int body_height = Integer.valueOf(txtBodyHeight.getText().toString()); int checkedRadioButtonId = radioScaleUnit.getCheckedRadioButtonId(); + int checkedGenderId = radioGender.getCheckedRadioButtonId(); + double goal_weight = Double.valueOf(txtGoalWeight.getText().toString()); int scale_unit = -1; @@ -212,17 +244,29 @@ public class UserSettingsActivity extends Activity { break; } + int gender = -1; + + switch (checkedGenderId) { + case R.id.btnRadioMale: + gender = 0; + break; + case R.id.btnRadioWoman: + gender = 1; + break; + } + String date = txtBirthday.getText().toString(); + String goal_date = txtGoalDate.getText().toString(); int id = -1; if (getIntent().getExtras().getInt("mode") == EDIT_USER_REQUEST) { id = getIntent().getExtras().getInt("id"); - openScale.updateScaleUser(id, name, date, body_height, scale_unit); + openScale.updateScaleUser(id, name, date, body_height, scale_unit, gender, goal_weight, goal_date); } else { - openScale.addScaleUser(name, date, body_height, scale_unit); + openScale.addScaleUser(name, date, body_height, scale_unit, gender, goal_weight, goal_date); id = openScale.getScaleUserList().get(0).id; } @@ -247,6 +291,16 @@ public class UserSettingsActivity extends Activity { } } + + private class onClickListenerGoalDateSet implements View.OnClickListener { + @Override + public void onClick(View v) { + Calendar cal = Calendar.getInstance(); + DatePickerDialog datePicker = new DatePickerDialog(context, goalDatePickerListener, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH)); + datePicker.show(); + } + } + private class onClickListenerCancel implements View.OnClickListener { @Override public void onClick(View v) { diff --git a/android_app/app/src/main/res/drawable/bmi.png b/android_app/app/src/main/res/drawable/bmi.png new file mode 100644 index 0000000000000000000000000000000000000000..484ab7c30e934443a9881634f65d26ffeb87b8bc GIT binary patch literal 1633 zcmV-n2A=teP)@dG5ti_w^9e9=UMF;QcT z=#xGfLt-o-qA>vz4f>#bR1HBTia|h9R1}n=gj%2l+T%mdmC4QB-FxqL+q<-rOy=%< zp83z2ne#C#s>(nPDF%2L1Yi(=96?0JiO3ugkz$yTh)fZY>7g5_YSsv}017;pt8RZs z;1;0E;+RlvLUg*$05}cINbuxqfxnE_gTT<<0-y#sWF7wjR3{XG&CWv24Bakd=eGmh zHo&R`PX1n_O@U>R+C~`URU4oin3kZ)mjb(uw%tHkp#Vq&`)!~v69m8`&g##P+&{d-b~;n;Jg9}eU-o^_Pq~ii`c#kXbM7hB#_F1{62JUesKW3R&I~U`J>JcG%Bp#SB1@rAKV#OMzBZJ&~dP@6MfE)BvQM z=uLbG(4nfQva~;GX?X;b)!ia;r7tfnB1=SMv@d^zh%6P6$^bLnLJ=wTUw&Oc{gJ>q_I+_c-Qm75GaiC} zs%mG*2}RxliN6I@wIhlZ+S0Ot>KK`9>F#0$pfnE$#83x-Z?aUa5s~@!eU+1chlm`r z@3EGqox0w>1*rAqdkZ(w$**jeFkbbi2tT7r6 zVl^Kij#^-i{zO_I6n7U9-S~KH~t+I7YgGu`yR~DzF;(9JnuLA0@y}qh${f zeS&daW3!w)v?(UxLxID-`*>>1zFa5GV|@X@CdVI888&IFnH$pEui?paW0azJuXf>N%t*RdPmrM%~Rw8(P?7oQzjgh6nN5ArhqkZ=H*(ZxH#7P0H4(N z4zScFUT-KbHu-x}K$AA(j;&@T`We`xs_hXZ%@Uv*xX6ihz^%YFCII=v4ik;vqsJ{j z0r&~HLRGV>I{=~ zLpSg}umN~iReyBodIEUeelAqi_hX5|z%qxOX60bb3Sc&{+Mg{9kz7yy^{%D4cu6)^xuobU7F0?<{&0CdFy zKt#&uc^yI#cy@A0i?KPtW1p5H2H>!>g^xti1w>>rFiKT76fppZ$RzU|eHK|68Yp4# fpQD2S4Dj$Dxxp%=C;u>R00000NkvXXu0mjf$rkQ} literal 0 HcmV?d00001 diff --git a/android_app/app/src/main/res/drawable/lastmonth.png b/android_app/app/src/main/res/drawable/lastmonth.png new file mode 100644 index 0000000000000000000000000000000000000000..2a8eb7a18711f0c4c2a25259c85947d65765ed99 GIT binary patch literal 1431 zcmV;I1!($-P)- zkcy}tst1XP$n+s4#SBU@G%~$?Krv-LL|!dzs+q<+_x5ns!P9QQ|$XnF|?`wH`5+`XGG^gc_799*H!8J_qYmMV#=Rq zA#;9;2B@aH9hjA-0VX6QoA4d*XPo|R4REnsM}V~va=U@eN}D7Q=z1ME7$NthrcD$)TLUbV7z^;6_>ECT zW(RO*s6NTuAkg&(aH}}wFou9ffeoScz(QN){g#esz0z(za4)b@B8eBew@AL0q@3W0 z=nTjDYh}>Oftkv)t+&+scpL*%fE5-7oh)ytl5p8?nenZNp)b!gr|s& z{uJL>qn9%8~s$3C++-ExPqL} zSy5B(8sG;Doddv9PI8qt7*=$wt(Om&i+_k>o_qnO)!z~!Jmy>IoCmxsEL8qfaDsW@ z2~JXLD&_!h1EqSG{hjv?M>aDd$!*&PwOKi1S;>M{+IUI?|} zQ`0vAPigMIWN4?`#)>+Rpu2a$Sgr)CEo@EztAK3=*=d@(UnBG#Ht6sgX$pjmvkG`Q zf)$!#a9Ab`Y3kY=)c_vwf-GUXu;&Ur$9oOC5Ly82LVs}KxTbDmgf88^V-AK%j1dYx z>j@I47vmpkRTGt|vKrKdM-`nB{ps!7X-rtWi1-PKhxMiqNQiB{@UU@LZKaC!`LRmFS!|H#e#K!--Q1GrDA8wK8XFo1I| z5XkPrKO(b8!ca~^+GUa`4QcX$j|@6L(8v~m8zkY$i$Mz-xebAhH{4c_Xg5z&0t}_-6wb3ysw-v40Ss2P}xg+zk9>se3zcE&g4$PADfpz)BM4`?;i^)}0Rbq2^0{iBF% l3S>@jocn zfCY>Jiz1Z0K`7cw{?({EKc|dvr|gSR{<#XWzxicY=aYW922D$Z3aG?;1~5NL1xyKv zCMZIeUq{Aa0_%WPKmjOvJcoeS0r+nVshzh2)LE*rWM2UEY8bXIQDL(N?Io80E2QG! zp$4tvg}QY5<#!1TheQ(;m3Wtc&r#TbX7PLu{H{PdAk_&2%@S`fyaGo3$k$cCYVjNg zPL-j10^E`6gaL=wW#B^@x|51JTZ!xeNI3zrY;rg#t%$Bf>;JD!F_VpV@r`v&fQrr49`JV8j z01N2QQ0O!@WIo!0!qL|pwUD4Cg5WPop;J7;fhsg6m2W{;MZ;XT#E*< zAJ{JP@j+k&SP85VOCd@u0PYH7I{-WdW((Qt#Xf~^^hP*hNiW@5&jpOkCquacas@;O zIg?AI4N$qkf)rEx>9CWLA$8txJq-`{8V62`J&*|-A~K4?HKq|ga-VZIm>a=d0l5M) zZ3E02YOE;+%oH0U2Jk%$rcvX6gCQq&D7oU4`mowwD>J~oA!7(77+G5avNA%69+Pea z2O?Zru_?gND6JlK&t%079#_13!@qt0RENR~u@6*a^tmj5s%Jo_!W#_(*Rv1_&II-< z-d~{dA#5s^zyT&7vW#LMaHK95ko|T8>U)J(2yol079v48c-aFqNi+rQt8l5!2HjCy zr{ez`*k_Be&B|)ofE~b+Y6Lz>@dC#b@9qK5vY>!AU~LjczgkN`74{BdU$G(WGoS_7 zl917_iUL%l{}#Ae%L=H&`^d|UW?)yfk{&M`5Jn)>0Q_O%-5gZ_bePFExks=+y`h$8 zz!>%>hFW4Qvd zjr@Lq>G7^7EB#d|pq}y{MdV8$H-ag*0cl6cRSJIrr&XltJStpY00000NkvXXu0mjf Dr)oc5!lIL8@MUQTpt6Hc|`>OfmsJ zA+G=b{|BlcOn`-f0T}^(PB~%%dY2f)#K1%q#K^!%9Aai3WLar2g~+jj2Wv+uycLx+zXJ$B;csnci9UATDp>b2`P zZr#3f_ul;n4<9{w`t143SFhi^d;j6n=PzHsegE<6_n*K2CbPKo0wevKr;B5VgyhnL z-<{7S%CLX@`4lPH&z+Qxh7lLq%=`@ovnJ&P1{`R{n-${*!bSNj@V^KGGt)4h{! zS?)itvnE_)XuaPp`uD4($H}@jPU{BO#I7>)IUZ-P9#GlJ5XKuM)7G|TwolP{UT;=c z$)Mu<$&;cZJFFeNOO%78fA)Av#RT|GI=IwB_q*!kIa?p=-~OmxJn>dbxla+#vSnWk zPS(wsb@hD9!M6rmKd1{UWiLp+cR9ICXb&=;ZGAe@3LMfnxV9f@c`$)$KM^>h2NERy)ZgZI{Q@j#S0Sx@9&q1vv3T@RX@}&`(eoZq2xkQxrWIO`3s-2<<#mIztCnVvY!xcyx_6X<9+@| z-!OK)`*@(mJCrXYbMcQ!{gVt_r;GpMViu7=;XJzE~l zl)f60w|hZ;Y|kP~;nEPPHy6SkpSE4Dn|LZyV#T7M{9@A}OD5*6A%05Br=F6Nuy9{0 zHIJ|BhT4nbn1!3TcfQwjTD&0NL)kTl`BSyz^YcxObHsoi@!`Jk=^DH8;rYQWVhb!> z%AOsZu)X`yai1w)%_oc5!lIL8@MUQTpt6Hc|`>jLiW) zA+G=b{|Blc1p^oYb>G`=0j+N+3GxeOU}R!uWn<^y;^yJw7Z4H^laP{;l~Yhs(bU$_ zGcYzav#_+Xwy||~_44x%2nq?0jE;#-NK8r3$S)~xZ13pm?wL4w%G4Qi=gnWVWZCi+ zD_5=EuxZQo9lQ7J-FM*Np~EN6oV#%G(zWY1?mv3`_$+cVlng6yNSj%ryl3Wf`)3bNGQ_eyaGdNazMAvdBoU88 zHxydg5?5F{FZ3}!vqWQJ(?mrt-h&PXzAH-vsyMY&7Kq+jeyEPaYIDe}R=4VTUO&rL z=msWpdf8ri)p&|)YuEyTg^i~tRC_U>S1kQDfvxDdg0Y{n@C1v@izoV{I=)`Mpxa@) zaA71zXzg;v)m%!kCS{^Zk4tR!Ok8}sdW`V`m4DS5O_|5a6q|d6h;Ps-n7x*8TmhO6R z&Bf)fUIrGkjOw=_{E9noL^X6Ti-kF}#Uy7gEg}7&gy?yQU6O@BIUHx3vIVCg!04+Cf&;S4c literal 0 HcmV?d00001 diff --git a/android_app/app/src/main/res/layout/activity_usersettings.xml b/android_app/app/src/main/res/layout/activity_usersettings.xml index 96b97391..7eefe335 100644 --- a/android_app/app/src/main/res/layout/activity_usersettings.xml +++ b/android_app/app/src/main/res/layout/activity_usersettings.xml @@ -64,6 +64,41 @@ android:id="@+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:text="@string/label_gender" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + +