mirror of
https://github.com/oliexdev/openScale.git
synced 2025-08-29 11:10:35 +02:00
Make it possible to change order of measurment views
By long pressing a view in the data entry activity, the view can be dragged up or down to change the order. The order is then saved and reflected in overview, table and data entry fragments/activity. This fixes part of #81 (and #164).
This commit is contained in:
@@ -59,6 +59,7 @@ 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;
|
||||
|
||||
@@ -78,6 +79,8 @@ public class MainActivity extends AppCompatActivity
|
||||
private BottomNavigationView navBottomDrawer;
|
||||
private ActionBarDrawerToggle drawerToggle;
|
||||
|
||||
private boolean settingsActivityRunning = false;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
@@ -90,6 +93,9 @@ public class MainActivity extends AppCompatActivity
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
CaocConfig.Builder.create()
|
||||
.trackActivities(true)
|
||||
.apply();
|
||||
@@ -183,33 +189,24 @@ public class MainActivity extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
|
||||
private void registerOnSharedPreferenceChangeListener() {
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
private void unregisterOnSharedPreferenceChangeListener() {
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.unregisterOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
// Stop listening when returning from settings
|
||||
unregisterOnSharedPreferenceChangeListener();
|
||||
settingsActivityRunning = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
// Clean up when shutting down
|
||||
unregisterOnSharedPreferenceChangeListener();
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.unregisterOnSharedPreferenceChangeListener(this);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||
recreate();
|
||||
if (settingsActivityRunning || key == MeasurementView.PREF_MEASUREMENT_ORDER) {
|
||||
recreate();
|
||||
}
|
||||
}
|
||||
|
||||
private void positiveFeedbackDialog() {
|
||||
@@ -307,10 +304,10 @@ public class MainActivity extends AppCompatActivity
|
||||
prefs.edit().putInt("lastFragmentId", menuItemId).commit();
|
||||
break;
|
||||
case R.id.nav_settings:
|
||||
registerOnSharedPreferenceChangeListener();
|
||||
Intent settingsIntent = new Intent(this, SettingsActivity.class);
|
||||
settingsIntent.putExtra(SettingsActivity.EXTRA_TINT_COLOR, navDrawer.getItemTextColor().getDefaultColor());
|
||||
startActivity(settingsIntent);
|
||||
settingsActivityRunning = true;
|
||||
drawerLayout.closeDrawers();
|
||||
return;
|
||||
case R.id.nav_help:
|
||||
|
@@ -20,15 +20,18 @@ 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;
|
||||
@@ -127,6 +130,16 @@ 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();
|
||||
@@ -456,4 +469,95 @@ 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:
|
||||
View draggedView = (View) 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);
|
||||
MeasurementView.saveMeasurementViewsOrder(table);
|
||||
}
|
||||
break;
|
||||
case DragEvent.ACTION_DRAG_ENDED:
|
||||
if (hasBackground) {
|
||||
// Restore background
|
||||
view.setBackground(background);
|
||||
background = null;
|
||||
hasBackground = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@ import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
@@ -58,6 +59,8 @@ import static com.health.openscale.gui.views.MeasurementView.MeasurementViewMode
|
||||
public abstract class MeasurementView extends TableLayout {
|
||||
public enum MeasurementViewMode {VIEW, EDIT, ADD, STATISTIC}
|
||||
|
||||
public static String PREF_MEASUREMENT_ORDER = "measurementOrder";
|
||||
|
||||
private TableRow measurementRow;
|
||||
private ImageView iconView;
|
||||
private TextView nameView;
|
||||
@@ -84,38 +87,76 @@ public abstract class MeasurementView extends TableLayout {
|
||||
|
||||
public enum DateTimeOrder { FIRST, LAST, NONE }
|
||||
|
||||
public static final List<MeasurementView> getMeasurementList(Context context, DateTimeOrder order) {
|
||||
final List<MeasurementView> measurementViews = new ArrayList<>();
|
||||
|
||||
if (order == DateTimeOrder.FIRST) {
|
||||
measurementViews.add(new DateMeasurementView(context));
|
||||
measurementViews.add(new TimeMeasurementView(context));
|
||||
}
|
||||
measurementViews.add(new WeightMeasurementView(context));
|
||||
measurementViews.add(new BMIMeasurementView(context));
|
||||
measurementViews.add(new WaterMeasurementView(context));
|
||||
measurementViews.add(new MuscleMeasurementView(context));
|
||||
measurementViews.add(new LBWMeasurementView(context));
|
||||
measurementViews.add(new FatMeasurementView(context));
|
||||
measurementViews.add(new BoneMeasurementView(context));
|
||||
measurementViews.add(new WaistMeasurementView(context));
|
||||
measurementViews.add(new WHtRMeasurementView(context));
|
||||
measurementViews.add(new HipMeasurementView(context));
|
||||
measurementViews.add(new WHRMeasurementView(context));
|
||||
measurementViews.add(new BMRMeasurementView(context));
|
||||
measurementViews.add(new CommentMeasurementView(context));
|
||||
if (order == DateTimeOrder.LAST) {
|
||||
measurementViews.add(new DateMeasurementView(context));
|
||||
measurementViews.add(new TimeMeasurementView(context));
|
||||
public static final List<MeasurementView> getMeasurementList(Context context, DateTimeOrder dateTimeOrder) {
|
||||
final List<MeasurementView> sorted = new ArrayList<>();
|
||||
if (dateTimeOrder == DateTimeOrder.FIRST) {
|
||||
sorted.add(new DateMeasurementView(context));
|
||||
sorted.add(new TimeMeasurementView(context));
|
||||
}
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
for (MeasurementView measurement : measurementViews) {
|
||||
{
|
||||
final List<MeasurementView> unsorted = new ArrayList<>();
|
||||
|
||||
unsorted.add(new WeightMeasurementView(context));
|
||||
unsorted.add(new BMIMeasurementView(context));
|
||||
unsorted.add(new WaterMeasurementView(context));
|
||||
unsorted.add(new MuscleMeasurementView(context));
|
||||
unsorted.add(new LBWMeasurementView(context));
|
||||
unsorted.add(new FatMeasurementView(context));
|
||||
unsorted.add(new BoneMeasurementView(context));
|
||||
unsorted.add(new WaistMeasurementView(context));
|
||||
unsorted.add(new WHtRMeasurementView(context));
|
||||
unsorted.add(new HipMeasurementView(context));
|
||||
unsorted.add(new WHRMeasurementView(context));
|
||||
unsorted.add(new BMRMeasurementView(context));
|
||||
unsorted.add(new CommentMeasurementView(context));
|
||||
|
||||
// Get sort order
|
||||
final String[] sortOrder = TextUtils.split(
|
||||
prefs.getString(PREF_MEASUREMENT_ORDER, ""), ",");
|
||||
|
||||
// Move views from unsorted to sorted in the correct order
|
||||
for (String key : sortOrder) {
|
||||
for (MeasurementView measurement : unsorted) {
|
||||
if (key.equals(measurement.getKey())) {
|
||||
sorted.add(measurement);
|
||||
unsorted.remove(measurement);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Any new views end up at the end
|
||||
sorted.addAll(unsorted);
|
||||
}
|
||||
|
||||
if (dateTimeOrder == DateTimeOrder.LAST) {
|
||||
sorted.add(new DateMeasurementView(context));
|
||||
sorted.add(new TimeMeasurementView(context));
|
||||
}
|
||||
|
||||
for (MeasurementView measurement : sorted) {
|
||||
measurement.updatePreferences(prefs);
|
||||
}
|
||||
|
||||
return measurementViews;
|
||||
return sorted;
|
||||
}
|
||||
|
||||
public static void saveMeasurementViewsOrder(TableLayout tableLayout) {
|
||||
ArrayList<String> order = new ArrayList<>();
|
||||
for (int i = 0; i < tableLayout.getChildCount(); ++i) {
|
||||
MeasurementView view = (MeasurementView) tableLayout.getChildAt(i);
|
||||
if (view instanceof DateMeasurementView || view instanceof TimeMeasurementView) {
|
||||
continue;
|
||||
}
|
||||
order.add(view.getKey());
|
||||
}
|
||||
PreferenceManager.getDefaultSharedPreferences(tableLayout.getContext())
|
||||
.edit()
|
||||
.putString(PREF_MEASUREMENT_ORDER, TextUtils.join(",", order))
|
||||
.commit();
|
||||
}
|
||||
|
||||
private void initView(Context context) {
|
||||
@@ -180,9 +221,7 @@ public abstract class MeasurementView extends TableLayout {
|
||||
evaluatorView.setLayoutParams(new TableRow.LayoutParams(0, LayoutParams.WRAP_CONTENT, 0.99f));
|
||||
spaceAfterEvaluatorView.setLayoutParams(new TableRow.LayoutParams(0, LayoutParams.WRAP_CONTENT, 0.01f));
|
||||
|
||||
onClickListenerEvaluation onClickListener = new onClickListenerEvaluation();
|
||||
measurementRow.setOnClickListener(onClickListener);
|
||||
evaluatorRow.setOnClickListener(onClickListener);
|
||||
setOnClickListener(new onClickListenerEvaluation());
|
||||
}
|
||||
|
||||
protected LinearLayout getIncDecLayout() {
|
||||
|
Reference in New Issue
Block a user