1
0
mirror of https://github.com/oliexdev/openScale.git synced 2025-08-18 22:41:44 +02:00

add an expandable recycler view

This commit is contained in:
oliexdev
2023-01-21 18:20:48 +01:00
parent a6c85d7548
commit 6a3bc7ba8e
7 changed files with 89 additions and 240 deletions

View File

@@ -15,6 +15,11 @@
*/ */
package com.health.openscale.gui.measurement; package com.health.openscale.gui.measurement;
import static com.health.openscale.gui.measurement.MeasurementView.MeasurementViewMode.ADD;
import static com.health.openscale.gui.measurement.MeasurementView.MeasurementViewMode.EDIT;
import static com.health.openscale.gui.measurement.MeasurementView.MeasurementViewMode.STATISTIC;
import static com.health.openscale.gui.measurement.MeasurementView.MeasurementViewMode.VIEW;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
@@ -53,11 +58,6 @@ import com.health.openscale.gui.utils.ColorUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static com.health.openscale.gui.measurement.MeasurementView.MeasurementViewMode.ADD;
import static com.health.openscale.gui.measurement.MeasurementView.MeasurementViewMode.EDIT;
import static com.health.openscale.gui.measurement.MeasurementView.MeasurementViewMode.STATISTIC;
import static com.health.openscale.gui.measurement.MeasurementView.MeasurementViewMode.VIEW;
public abstract class MeasurementView extends TableLayout { public abstract class MeasurementView extends TableLayout {
public enum MeasurementViewMode {VIEW, EDIT, ADD, STATISTIC} public enum MeasurementViewMode {VIEW, EDIT, ADD, STATISTIC}
@@ -207,7 +207,7 @@ public abstract class MeasurementView extends TableLayout {
iconView.setImageResource(iconId); iconView.setImageResource(iconId);
iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
iconView.setPadding(25,25,25,25); iconView.setPadding(15,15,15,15);
iconView.setColorFilter(ColorUtil.COLOR_BLACK); iconView.setColorFilter(ColorUtil.COLOR_BLACK);
iconView.setBackground(iconViewBackground); iconView.setBackground(iconViewBackground);

View File

@@ -1,104 +0,0 @@
package com.health.openscale.gui.overview;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
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 com.health.openscale.gui.measurement.WeightMeasurementView;
import com.health.openscale.gui.utils.ColorUtil;
import java.util.ArrayList;
import java.util.List;
class MeasurementAdapter extends RecyclerView.Adapter<MeasurementAdapter.ViewHolder> {
private Context context;
private ScaleMeasurement scaleMeasurement;
private ScaleMeasurement prevScaleMeasurement;
private List<FloatMeasurementView> measurementViewList;
public MeasurementAdapter(Context aContext, ScaleMeasurement scaleMeasurement, ScaleMeasurement prevScaleMeasurement) {
context = aContext;
this.scaleMeasurement = scaleMeasurement;
this.prevScaleMeasurement = prevScaleMeasurement;
measurementViewList = new ArrayList<>();
List<MeasurementView> measurementDefaultViewList = MeasurementView.getMeasurementList(context, MeasurementView.DateTimeOrder.LAST);
for (MeasurementView measurementView : measurementDefaultViewList) {
if (measurementView instanceof FloatMeasurementView && measurementView.isVisible() && !(measurementView instanceof WeightMeasurementView)) {
measurementViewList.add((FloatMeasurementView)measurementView);
}
}
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_measurement, parent, false);
MeasurementAdapter.ViewHolder viewHolder = new MeasurementAdapter.ViewHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
FloatMeasurementView measurementView = measurementViewList.get(position);
measurementView.loadFrom(scaleMeasurement, prevScaleMeasurement);
GradientDrawable iconViewBackground = new GradientDrawable();
iconViewBackground.setColor(((FloatMeasurementView) measurementView).getColor());
iconViewBackground.setShape(GradientDrawable.OVAL);
iconViewBackground.setGradientRadius(holder.iconView.getWidth());
holder.iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
holder.iconView.setColorFilter(ColorUtil.COLOR_BLACK);
holder.iconView.setBackground(iconViewBackground);
holder.iconView.setImageDrawable(measurementView.getIcon());
SpannableStringBuilder value = new SpannableStringBuilder();
value.append("");
value.setSpan(new ForegroundColorSpan(measurementView.getIndicatorColor()), 0, 1,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
value.append(measurementView.getValueAsString(true));
measurementView.appendDiffValue(value, true);
holder.valueView.setText(value);
}
@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 valueView;
ImageView iconView;
public ViewHolder(@NonNull View itemView) {
super(itemView);
valueView = itemView.findViewById(R.id.valueView);
iconView = itemView.findViewById(R.id.iconView);
}
}
}

View File

@@ -1,28 +1,27 @@
package com.health.openscale.gui.overview; package com.health.openscale.gui.overview;
import android.app.Activity; import android.app.Activity;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TableLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.navigation.Navigation; import androidx.navigation.Navigation;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.transition.AutoTransition;
import androidx.transition.TransitionManager;
import com.google.android.flexbox.AlignItems;
import com.google.android.flexbox.FlexDirection;
import com.google.android.flexbox.FlexboxLayoutManager;
import com.google.android.flexbox.JustifyContent;
import com.health.openscale.R; import com.health.openscale.R;
import com.health.openscale.core.datatypes.ScaleMeasurement; import com.health.openscale.core.datatypes.ScaleMeasurement;
import com.health.openscale.gui.measurement.DateMeasurementView;
import com.health.openscale.gui.measurement.MeasurementEntryFragment; import com.health.openscale.gui.measurement.MeasurementEntryFragment;
import com.health.openscale.gui.measurement.WeightMeasurementView; import com.health.openscale.gui.measurement.MeasurementView;
import com.health.openscale.gui.measurement.TimeMeasurementView;
import com.health.openscale.gui.measurement.UserMeasurementView;
import java.text.DateFormat; import java.text.DateFormat;
import java.util.List; import java.util.List;
@@ -30,10 +29,13 @@ import java.util.List;
class OverviewAdapter extends RecyclerView.Adapter<OverviewAdapter.ViewHolder> { class OverviewAdapter extends RecyclerView.Adapter<OverviewAdapter.ViewHolder> {
private Activity activity; private Activity activity;
private List<ScaleMeasurement> scaleMeasurementList; private List<ScaleMeasurement> scaleMeasurementList;
private int maxMeasurementView;
public OverviewAdapter(Activity activity, List<ScaleMeasurement> scaleMeasurementList) { public OverviewAdapter(Activity activity, List<ScaleMeasurement> scaleMeasurementList) {
this.activity = activity; this.activity = activity;
this.scaleMeasurementList = scaleMeasurementList; this.scaleMeasurementList = scaleMeasurementList;
this.maxMeasurementView = 3;
} }
@Override @Override
@@ -48,18 +50,11 @@ class OverviewAdapter extends RecyclerView.Adapter<OverviewAdapter.ViewHolder> {
@Override @Override
public void onBindViewHolder(@NonNull OverviewAdapter.ViewHolder holder, int position) { public void onBindViewHolder(@NonNull OverviewAdapter.ViewHolder holder, int position) {
ScaleMeasurement scaleMeasurement = scaleMeasurementList.get(position); ScaleMeasurement scaleMeasurement = scaleMeasurementList.get(position);
ScaleMeasurement prevScaleMeasurement = scaleMeasurementList.get(position-1); ScaleMeasurement prevScaleMeasurement = new ScaleMeasurement();
holder.expandMoreView.setOnClickListener(new View.OnClickListener() { if (scaleMeasurementList.size() > 2) {
@Override prevScaleMeasurement = scaleMeasurementList.get(position - 1);
public void onClick(View v) {
if (holder.measurementRecyclerView.getVisibility() == View.GONE) {
holder.measurementRecyclerView.setVisibility(View.VISIBLE);
} else {
holder.measurementRecyclerView.setVisibility(View.GONE);
} }
}
});
holder.itemView.setOnClickListener(new View.OnClickListener() { holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override @Override
@@ -71,38 +66,41 @@ class OverviewAdapter extends RecyclerView.Adapter<OverviewAdapter.ViewHolder> {
} }
}); });
if (!scaleMeasurement.getComment().isEmpty()) { holder.expandMeasurementView.setOnClickListener(new View.OnClickListener() {
holder.commentTextView.setVisibility(View.VISIBLE); @Override
holder.commentIconView.setVisibility(View.VISIBLE); public void onClick(View v) {
holder.commentTextView.setText(scaleMeasurement.getComment()); TransitionManager.beginDelayedTransition(holder.measurementViews, new AutoTransition());
if (holder.measurementViews.getVisibility() == View.VISIBLE) {
holder.measurementViews.setVisibility(View.GONE);
holder.expandMeasurementView.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.ic_expand_more));
} else { } else {
holder.commentTextView.setVisibility(View.GONE); holder.measurementViews.setVisibility(View.VISIBLE);
holder.commentIconView.setVisibility(View.GONE); holder.expandMeasurementView.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.ic_expand_less));
} }
}
});
FlexboxLayoutManager layoutManager = new FlexboxLayoutManager(activity);
layoutManager.setFlexDirection(FlexDirection.ROW);
layoutManager.setJustifyContent(JustifyContent.SPACE_AROUND);
layoutManager.setAlignItems(AlignItems.CENTER);
holder.measurementRecyclerView.setLayoutManager(layoutManager);
holder.measurementRecyclerView.setHasFixedSize(true);
holder.measurementRecyclerView.setNestedScrollingEnabled(false);
holder.measurementRecyclerView.setAdapter(new MeasurementAdapter(activity, scaleMeasurement, prevScaleMeasurement));
WeightMeasurementView weightMeasurementView = new WeightMeasurementView(activity);
weightMeasurementView.loadFrom(scaleMeasurement, prevScaleMeasurement);
SpannableStringBuilder weightValue = new SpannableStringBuilder();
weightValue.append("");
weightValue.setSpan(new ForegroundColorSpan(weightMeasurementView.getIndicatorColor()), 0, 1,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
weightValue.append(weightMeasurementView.getValueAsString(true));
int start = weightValue.length();
weightMeasurementView.appendDiffValue(weightValue, true);
weightValue.setSpan(new RelativeSizeSpan(0.9f), start, weightValue.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
holder.weightView.setText(weightValue);
holder.dateView.setText(DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT).format(scaleMeasurement.getDateTime())); holder.dateView.setText(DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT).format(scaleMeasurement.getDateTime()));
List<MeasurementView> measurementViewList = MeasurementView.getMeasurementList(activity, MeasurementView.DateTimeOrder.LAST);
int i = 0;
for (MeasurementView measurementView : measurementViewList) {
i++;
if (measurementView instanceof DateMeasurementView || measurementView instanceof TimeMeasurementView || measurementView instanceof UserMeasurementView) {
measurementView.setVisible(false);
}
else {
measurementView.loadFrom(scaleMeasurement, prevScaleMeasurement);
if (i <= maxMeasurementView) {
holder.measurementHighlightViews.addView(measurementView);
} else {
holder.measurementViews.addView(measurementView);
}
}
}
} }
@Override @Override
@@ -117,21 +115,18 @@ class OverviewAdapter extends RecyclerView.Adapter<OverviewAdapter.ViewHolder> {
static class ViewHolder extends RecyclerView.ViewHolder { static class ViewHolder extends RecyclerView.ViewHolder {
TextView dateView; TextView dateView;
TextView weightView; TableLayout measurementHighlightViews;
ImageView expandMoreView; ImageView expandMeasurementView;
RecyclerView measurementRecyclerView; TableLayout measurementViews;
ImageView commentIconView;
TextView commentTextView;
public ViewHolder(@NonNull View itemView) { public ViewHolder(@NonNull View itemView) {
super(itemView); super(itemView);
dateView = itemView.findViewById(R.id.dateView); dateView = itemView.findViewById(R.id.dateView);
weightView = itemView.findViewById(R.id.weightView); measurementHighlightViews = itemView.findViewById(R.id.measurementHighlightViews);
expandMoreView = itemView.findViewById(R.id.expandMoreView); expandMeasurementView = itemView.findViewById(R.id.expandMoreView);
measurementRecyclerView = itemView.findViewById(R.id.measurementRecyclerView); measurementViews = itemView.findViewById(R.id.measurementViews);
commentIconView = itemView.findViewById(R.id.commentIconView); measurementViews.setVisibility(View.GONE);
commentTextView = itemView.findViewById(R.id.commentTextView);
} }
} }
} }

View File

@@ -309,7 +309,6 @@ public class OverviewFragment extends Fragment {
} }
private void updateUserSelection() { private void updateUserSelection() {
currentScaleUser = OpenScale.getInstance().getSelectedScaleUser(); currentScaleUser = OpenScale.getInstance().getSelectedScaleUser();
spinUserAdapter.clear(); spinUserAdapter.clear();
@@ -335,6 +334,11 @@ public class OverviewFragment extends Fragment {
WeightMeasurementView weightMeasurementView = new WeightMeasurementView(getContext()); WeightMeasurementView weightMeasurementView = new WeightMeasurementView(getContext());
ScaleMeasurement initialWeightMeasurement = OpenScale.getInstance().getLastScaleMeasurement(); ScaleMeasurement initialWeightMeasurement = OpenScale.getInstance().getLastScaleMeasurement();
if (initialWeightMeasurement == null) {
initialWeightMeasurement = new ScaleMeasurement();
}
initialWeightMeasurement.setWeight(initialWeightMeasurement.getWeight()); initialWeightMeasurement.setWeight(initialWeightMeasurement.getWeight());
weightMeasurementView.loadFrom(initialWeightMeasurement, null); weightMeasurementView.loadFrom(initialWeightMeasurement, null);

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,8l-6,6 1.41,1.41L12,10.83l4.59,4.58L18,14z"/>
</vector>

View File

@@ -1,30 +0,0 @@
<?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="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:orientation="vertical">
<ImageView
android:id="@+id/iconView"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:paddingLeft="5dp"
android:paddingTop="5dp"
android:paddingRight="5dp"
android:paddingBottom="5dp"
android:scaleType="centerInside"
app:srcCompat="@drawable/ic_tdee" />
<TextView
android:id="@+id/valueView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:lineSpacingExtra="-5dp"
android:text="TextView"
android:textSize="12sp" />
</LinearLayout>

View File

@@ -29,57 +29,31 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<TextView <TableLayout
android:id="@+id/weightView" android:id="@+id/measurementHighlightViews"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:lineSpacingExtra="-5dp" android:layout_marginTop="5dp"
android:text="TextView" app:layout_constraintTop_toBottomOf="@id/dateView">
android:textSize="18sp" </TableLayout>
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/dateView" />
<ImageView <ImageView
android:id="@+id/expandMoreView" android:id="@+id/expandMoreView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
app:layout_constraintBottom_toBottomOf="@+id/weightView"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/measurementHighlightViews"
app:srcCompat="@drawable/ic_expand_more" app:srcCompat="@drawable/ic_expand_more"
app:tint="?attr/colorControlNormal" /> app:tint="?attr/colorControlNormal" />
<androidx.recyclerview.widget.RecyclerView <TableLayout
android:id="@+id/measurementRecyclerView" android:id="@+id/measurementViews"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginTop="8dp" android:layout_marginTop="5dp"
android:visibility="gone" app:layout_constraintTop_toBottomOf="@id/expandMoreView">
app:layout_constraintTop_toBottomOf="@+id/weightView" > </TableLayout>
</androidx.recyclerview.widget.RecyclerView>
<ImageView
android:id="@+id/commentIconView"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginTop="8dp"
android:visibility="gone"
app:tint="?attr/colorControlNormal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/measurementRecyclerView"
app:srcCompat="@drawable/ic_comment" />
<TextView
android:id="@+id/commentTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="TextView"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/commentIconView"
app:layout_constraintStart_toEndOf="@+id/commentIconView"
app:layout_constraintTop_toTopOf="@+id/commentIconView" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>