From f0940e7dee3dd707647274f6ed2e3666a6e5943b Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Thu, 22 Feb 2018 15:46:28 +0100 Subject: [PATCH] Move setting of measurement order to preferences --- .../health/openscale/gui/MainActivity.java | 3 +- .../gui/activities/DataEntryActivity.java | 106 --------- .../preferences/MeasurementPreferences.java | 203 ++++++++++++++++++ .../app/src/main/res/values/strings.xml | 3 + .../main/res/xml/measurement_preferences.xml | 1 + 5 files changed, 208 insertions(+), 108 deletions(-) diff --git a/android_app/app/src/main/java/com/health/openscale/gui/MainActivity.java b/android_app/app/src/main/java/com/health/openscale/gui/MainActivity.java index 197c5c0e..dcd57915 100644 --- a/android_app/app/src/main/java/com/health/openscale/gui/MainActivity.java +++ b/android_app/app/src/main/java/com/health/openscale/gui/MainActivity.java @@ -59,7 +59,6 @@ import com.health.openscale.gui.fragments.OverviewFragment; import com.health.openscale.gui.fragments.StatisticsFragment; import com.health.openscale.gui.fragments.TableFragment; import com.health.openscale.gui.utils.PermissionHelper; -import com.health.openscale.gui.views.MeasurementView; import java.lang.reflect.Field; @@ -204,7 +203,7 @@ public class MainActivity extends AppCompatActivity @Override public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { - if (settingsActivityRunning || key == MeasurementView.PREF_MEASUREMENT_ORDER) { + if (settingsActivityRunning) { recreate(); } } diff --git a/android_app/app/src/main/java/com/health/openscale/gui/activities/DataEntryActivity.java b/android_app/app/src/main/java/com/health/openscale/gui/activities/DataEntryActivity.java index 0bf3b0a3..521f37b2 100644 --- a/android_app/app/src/main/java/com/health/openscale/gui/activities/DataEntryActivity.java +++ b/android_app/app/src/main/java/com/health/openscale/gui/activities/DataEntryActivity.java @@ -20,18 +20,15 @@ import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.graphics.Color; -import android.graphics.Point; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.graphics.drawable.DrawableCompat; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; -import android.view.DragEvent; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; -import android.view.MotionEvent; import android.view.View; import android.widget.Button; import android.widget.LinearLayout; @@ -130,16 +127,6 @@ public class DataEntryActivity extends AppCompatActivity { : MeasurementView.MeasurementViewMode.VIEW; for (MeasurementView measurement : dataEntryMeasurements) { measurement.setEditMode(mode); - - // Date and time can not be reordered (as they can be both first and last) - if (measurement instanceof DateMeasurementView || measurement instanceof TimeMeasurementView) { - continue; - } - - onLongClickListener longClickListener = new onLongClickListener(); - measurement.setOnTouchListener(longClickListener); - measurement.setOnLongClickListener(longClickListener); - measurement.setOnDragListener(new onDragListener()); } updateOnView(); @@ -469,97 +456,4 @@ public class DataEntryActivity extends AppCompatActivity { } } } - - private class onLongClickListener implements View.OnTouchListener, View.OnLongClickListener { - float x = 0; - float y = 0; - - @Override - public boolean onTouch(View view, MotionEvent event) { - if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { - // Save x and y so that the drag shadow can have the touch point set to where - // the user did the touch (and not in the center of the view). - x = event.getX(); - y = event.getY(); - } - return false; - } - - @Override - public boolean onLongClick(View view) { - return view.startDrag(null, new dragShadowBuilder(view), view, 0); - } - - private class dragShadowBuilder extends View.DragShadowBuilder { - public dragShadowBuilder(View view) { - super(view); - } - - @Override - public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) { - super.onProvideShadowMetrics(outShadowSize, outShadowTouchPoint); - outShadowTouchPoint.set(Math.round(x), Math.round(y)); - } - } - } - - private class onDragListener implements View.OnDragListener { - Drawable background = null; - // background may be set to null, thus the extra boolean - boolean hasBackground = false; - - @Override - public boolean onDrag(View view, DragEvent event) { - switch (event.getAction()) { - case DragEvent.ACTION_DRAG_STARTED: - if (view == event.getLocalState() && !hasBackground) { - background = view.getBackground(); - hasBackground = true; - view.setBackgroundColor(Color.GRAY); - } - break; - case DragEvent.ACTION_DRAG_LOCATION: - // Ignore - break; - case DragEvent.ACTION_DRAG_ENTERED: - if (view != event.getLocalState()) { - background = view.getBackground(); - hasBackground = true; - view.setBackgroundColor(Color.LTGRAY); - } - break; - case DragEvent.ACTION_DRAG_EXITED: - if (view != event.getLocalState() && hasBackground) { - view.setBackground(background); - background = null; - hasBackground = false; - } - break; - case DragEvent.ACTION_DROP: - MeasurementView draggedView = (MeasurementView) event.getLocalState(); - TableLayout table = (TableLayout) draggedView.getParent(); - final int draggedIndex = table.indexOfChild(draggedView); - final int targetIndex = table.indexOfChild(view); - if (draggedIndex != targetIndex) { - // A view that is moved down is placed after the target view, - // and a view that is moved up is placed before the target view. - table.removeView(draggedView); - table.addView(draggedView, targetIndex); - dataEntryMeasurements.remove(draggedView); - dataEntryMeasurements.add(targetIndex, draggedView); - MeasurementView.saveMeasurementViewsOrder(getApplicationContext(), dataEntryMeasurements); - } - break; - case DragEvent.ACTION_DRAG_ENDED: - if (hasBackground) { - // Restore background - view.setBackground(background); - background = null; - hasBackground = false; - } - break; - } - return true; - } - } } diff --git a/android_app/app/src/main/java/com/health/openscale/gui/preferences/MeasurementPreferences.java b/android_app/app/src/main/java/com/health/openscale/gui/preferences/MeasurementPreferences.java index a59e3254..44e65ecd 100644 --- a/android_app/app/src/main/java/com/health/openscale/gui/preferences/MeasurementPreferences.java +++ b/android_app/app/src/main/java/com/health/openscale/gui/preferences/MeasurementPreferences.java @@ -16,17 +16,27 @@ package com.health.openscale.gui.preferences; import android.app.AlertDialog; +import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; +import android.graphics.Color; +import android.graphics.Point; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.EditTextPreference; import android.preference.ListPreference; import android.preference.MultiSelectListPreference; import android.preference.Preference; +import android.preference.PreferenceCategory; import android.preference.PreferenceFragment; import android.preference.PreferenceGroup; +import android.preference.PreferenceManager; +import android.preference.PreferenceScreen; import android.preference.SwitchPreference; +import android.view.DragEvent; +import android.view.MotionEvent; +import android.view.View; import android.widget.Toast; import com.health.openscale.R; @@ -34,6 +44,7 @@ import com.health.openscale.core.OpenScale; import com.health.openscale.core.bodymetric.EstimatedFatMetric; import com.health.openscale.core.bodymetric.EstimatedLBWMetric; import com.health.openscale.core.bodymetric.EstimatedWaterMetric; +import com.health.openscale.gui.views.MeasurementView; import java.util.ArrayList; import java.util.List; @@ -56,6 +67,9 @@ public class MeasurementPreferences extends PreferenceFragment implements Shared private Preference deleteAll; + private PreferenceScreen measurementOrderScreen; + private PreferenceCategory measurementOrderCategory; + private CheckBoxPreference fatEnable; private SwitchPreference fatPercentageEnable; private CheckBoxPreference waterEnable; @@ -79,6 +93,30 @@ public class MeasurementPreferences extends PreferenceFragment implements Shared deleteAll = (Preference) findPreference(PREFERENCE_KEY_DELETE_ALL); deleteAll.setOnPreferenceClickListener(new onClickListenerDeleteAll()); + final Context context = getActivity().getApplicationContext(); + measurementOrderScreen = (PreferenceScreen) findPreference(MeasurementView.PREF_MEASUREMENT_ORDER); + + measurementOrderCategory = new PreferenceCategory(context); + measurementOrderCategory.setTitle(R.string.label_press_hold_reorder); + measurementOrderCategory.setOrderingAsAdded(true); + + Preference resetOrder = new Preference(context); + resetOrder.setTitle(R.string.label_set_default_order); + resetOrder.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + PreferenceManager.getDefaultSharedPreferences(context).edit() + .remove(MeasurementView.PREF_MEASUREMENT_ORDER).commit(); + measurementOrderCategory.removeAll(); + updateMeasurementOrderScreen(context, measurementOrderCategory); + return true; + } + }); + measurementOrderScreen.addPreference(resetOrder); + measurementOrderScreen.addPreference(measurementOrderCategory); + + updateMeasurementOrderScreen(context, measurementOrderCategory); + estimateWaterEnable = (CheckBoxPreference) findPreference(PREFERENCE_KEY_ESTIMATE_WATER); estimateWaterFormula = (ListPreference) findPreference(PREFERENCE_KEY_ESTIMATE_WATER_FORMULA); estimateLBWEnable = (CheckBoxPreference) findPreference(PREFERENCE_KEY_ESTIMATE_LBW); @@ -100,6 +138,17 @@ public class MeasurementPreferences extends PreferenceFragment implements Shared initSummary(getPreferenceScreen()); } + private void updateMeasurementOrderScreen(Context context, PreferenceCategory category) { + List measurementViews = MeasurementView.getMeasurementList( + context, MeasurementView.DateTimeOrder.NONE); + for (MeasurementView measurement : measurementViews) { + Preference preference = new MeasurementOrderPreference(context, category, measurement); + preference.setShouldDisableView(true); + preference.setEnabled(measurement.isVisible()); + category.addPreference(preference); + } + } + public void updateWaterListPreferences() { ArrayList listEntries = new ArrayList(); ArrayList listEntryValues = new ArrayList(); @@ -167,6 +216,10 @@ public class MeasurementPreferences extends PreferenceFragment implements Shared @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { updatePrefSummary(findPreference(key)); + if (!key.equals(MeasurementView.PREF_MEASUREMENT_ORDER)) { + measurementOrderCategory.removeAll(); + updateMeasurementOrderScreen(getContext(), measurementOrderCategory); + } } private void updatePrefSummary(Preference p) { @@ -266,4 +319,154 @@ public class MeasurementPreferences extends PreferenceFragment implements Shared return false; } } + + private class MeasurementOrderPreference extends Preference { + PreferenceGroup parentGroup; + MeasurementView measurement; + View boundView; + + MeasurementOrderPreference(Context context, PreferenceGroup parent, MeasurementView measurementView) { + super(context); + parentGroup = parent; + measurement = measurementView; + setIcon(measurement.getIcon()); + setTitle(measurement.getNameText()); + } + + public PreferenceGroup getParent() { + return parentGroup; + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + boundView = view; + + onTouchClickListener touchClickListener = new onTouchClickListener(this); + view.setOnTouchListener(touchClickListener); + view.setOnLongClickListener(touchClickListener); + view.setOnDragListener(new onDragListener()); + } + + private class onTouchClickListener implements View.OnTouchListener, View.OnLongClickListener { + MeasurementOrderPreference preference; + int x = 0; + int y = 0; + + onTouchClickListener(MeasurementOrderPreference pref) { + preference = pref; + } + + @Override + public boolean onTouch(View view, MotionEvent event) { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + x = Math.round(event.getX()); + y = Math.round(event.getY()); + } + return false; + } + + @Override + public boolean onLongClick(View view) { + return view.startDrag(null, new dragShadowBuilder(view), preference, 0); + } + + private class dragShadowBuilder extends View.DragShadowBuilder { + public dragShadowBuilder(View view) { + super(view); + } + + @Override + public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) { + super.onProvideShadowMetrics(outShadowSize, outShadowTouchPoint); + outShadowTouchPoint.set(x, y); + } + } + } + + private class onDragListener implements View.OnDragListener { + Drawable background = null; + // background may be set to null, thus the extra boolean + boolean hasBackground = false; + + private MeasurementOrderPreference castLocalState(DragEvent event) { + return (MeasurementOrderPreference) event.getLocalState(); + } + + private boolean isDraggedView(View view, DragEvent event) { + return castLocalState(event).boundView == view; + } + + private void setTemporaryBackgroundColor(View view, int color) { + if (!hasBackground) { + background = view.getBackground(); + hasBackground = true; + view.setBackgroundColor(color); + } + } + + private void restoreBackground(View view) { + if (hasBackground) { + view.setBackground(background); + background = null; + hasBackground = false; + } + } + + @Override + public boolean onDrag(View view, DragEvent event) { + switch (event.getAction()) { + case DragEvent.ACTION_DRAG_STARTED: + if (isDraggedView(view, event)) { + setTemporaryBackgroundColor(view, Color.GRAY); + } + break; + case DragEvent.ACTION_DRAG_ENTERED: + if (!isDraggedView(view, event)) { + setTemporaryBackgroundColor(view, Color.LTGRAY); + } + break; + case DragEvent.ACTION_DRAG_EXITED: + if (!isDraggedView(view, event)) { + restoreBackground(view); + } + break; + case DragEvent.ACTION_DROP: + MeasurementOrderPreference draggedPref = castLocalState(event); + PreferenceGroup group = draggedPref.getParent(); + + ArrayList preferences = new ArrayList<>(); + for (int i = 0; i < group.getPreferenceCount(); ++i) { + MeasurementOrderPreference pref = (MeasurementOrderPreference) group.getPreference(i); + // Add all preferences except the dragged one + if (pref != draggedPref) { + preferences.add(pref); + } + // When we find the view that is the drop target use add(index, ...). + // This will add the dragged preference before the drop if dragged upwards, + // and after if dragged downwards. + if (pref.boundView == view) { + preferences.add(i, draggedPref); + } + } + + ArrayList measurementViews = new ArrayList<>(); + // Re-add all preferences in the new order + group.removeAll(); + for (MeasurementOrderPreference p : preferences) { + p.setOrder(DEFAULT_ORDER); + group.addPreference(p); + measurementViews.add(p.measurement); + } + MeasurementView.saveMeasurementViewsOrder(getContext(), measurementViews); + break; + case DragEvent.ACTION_DRAG_ENDED: + restoreBackground(view); + break; + } + return true; + } + } + + } } diff --git a/android_app/app/src/main/res/values/strings.xml b/android_app/app/src/main/res/values/strings.xml index 9e514f8c..34f44fef 100644 --- a/android_app/app/src/main/res/values/strings.xml +++ b/android_app/app/src/main/res/values/strings.xml @@ -222,5 +222,8 @@ openScale requires permission to access the coarse location to search for Bluetooth devices Information Next + Measurement order + Press and hold to reorder + Set default order diff --git a/android_app/app/src/main/res/xml/measurement_preferences.xml b/android_app/app/src/main/res/xml/measurement_preferences.xml index aa23c650..b3e14152 100644 --- a/android_app/app/src/main/res/xml/measurement_preferences.xml +++ b/android_app/app/src/main/res/xml/measurement_preferences.xml @@ -1,6 +1,7 @@ +