1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-28 04:46:51 +01:00

Animate card movement on device list

This commit is contained in:
José Rebelo 2022-06-28 20:31:58 +01:00 committed by Gitea
parent e1840baa32
commit 1755b4e093
2 changed files with 60 additions and 4 deletions

View File

@ -188,6 +188,7 @@ public class ControlCenterv2 extends AppCompatActivity
deviceList = deviceManager.getDevices(); deviceList = deviceManager.getDevices();
mGBDeviceAdapter = new GBDeviceAdapterv2(this, deviceList, deviceActivityHashMap); mGBDeviceAdapter = new GBDeviceAdapterv2(this, deviceList, deviceActivityHashMap);
mGBDeviceAdapter.setHasStableIds(true);
// get activity data asynchronously, this fills the deviceActivityHashMap // get activity data asynchronously, this fills the deviceActivityHashMap
// and calls refreshPairedDevices() notifyDataSetChanged // and calls refreshPairedDevices() notifyDataSetChanged

View File

@ -30,7 +30,6 @@ import android.text.Editable;
import android.text.InputType; import android.text.InputType;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.transition.TransitionManager;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.Pair; import android.util.Pair;
import android.util.TypedValue; import android.util.TypedValue;
@ -58,6 +57,8 @@ import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView; import androidx.cardview.widget.CardView;
import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.charts.PieChart;
@ -70,6 +71,7 @@ import com.google.android.material.snackbar.Snackbar;
import com.jaredrummler.android.colorpicker.ColorPickerDialog; import com.jaredrummler.android.colorpicker.ColorPickerDialog;
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener; import com.jaredrummler.android.colorpicker.ColorPickerDialogListener;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -116,7 +118,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
/** /**
* Adapter for displaying GBDevice instances. * Adapter for displaying GBDevice instances.
*/ */
public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.ViewHolder> { public class GBDeviceAdapterv2 extends ListAdapter<GBDevice, GBDeviceAdapterv2.ViewHolder> {
private static final Logger LOG = LoggerFactory.getLogger(GBDeviceAdapterv2.class); private static final Logger LOG = LoggerFactory.getLogger(GBDeviceAdapterv2.class);
private final Context context; private final Context context;
@ -126,8 +128,10 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
private String expandedFolderName = ""; private String expandedFolderName = "";
private ViewGroup parent; private ViewGroup parent;
private HashMap<String, long[]> deviceActivityMap = new HashMap(); private HashMap<String, long[]> deviceActivityMap = new HashMap();
private StableIdGenerator idGenerator = new StableIdGenerator();
public GBDeviceAdapterv2(Context context, List<GBDevice> deviceList, HashMap<String,long[]> deviceMap) { public GBDeviceAdapterv2(Context context, List<GBDevice> deviceList, HashMap<String,long[]> deviceMap) {
super(new GBDeviceDiffUtil());
this.context = context; this.context = context;
this.deviceList = deviceList; this.deviceList = deviceList;
rebuildFolders(); rebuildFolders();
@ -842,9 +846,22 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
showRemoveDeviceDialog(device); showRemoveDeviceDialog(device);
return true; return true;
case R.id.controlcenter_device_submenu_show_details: case R.id.controlcenter_device_submenu_show_details:
final String previouslyExpandedDeviceAddress = expandedDeviceAddress;
expandedDeviceAddress = detailsShown ? "" : device.getAddress(); expandedDeviceAddress = detailsShown ? "" : device.getAddress();
TransitionManager.beginDelayedTransition(parent);
notifyDataSetChanged(); if (!previouslyExpandedDeviceAddress.isEmpty()) {
// Notify the previously expanded device for a change (collapsing it)
for (int i = 0; i < devicesListWithFolders.size(); i++) {
final GBDevice gbDevice = devicesListWithFolders.get(i);
if (gbDevice.getAddress().equals(previouslyExpandedDeviceAddress)) {
notifyItemChanged(devicesListWithFolders.indexOf(gbDevice));
break;
}
}
}
// Update the current one
notifyItemChanged(devicesListWithFolders.indexOf(device));
return true; return true;
case R.id.controlcenter_device_submenu_set_parent_folder: case R.id.controlcenter_device_submenu_set_parent_folder:
showSetParentFolderDialog(device); showSetParentFolderDialog(device);
@ -1067,6 +1084,11 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
return devicesListWithFolders.size(); return devicesListWithFolders.size();
} }
@Override
public long getItemId(int position) {
return idGenerator.getId(devicesListWithFolders.get(position));
}
static class ViewHolder extends RecyclerView.ViewHolder { static class ViewHolder extends RecyclerView.ViewHolder {
View root; View root;
@ -1358,4 +1380,37 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
return Color.HSVToColor(hsvb); return Color.HSVToColor(hsvb);
} }
private static class GBDeviceDiffUtil extends DiffUtil.ItemCallback<GBDevice> {
@Override
public boolean areItemsTheSame(@NonNull GBDevice oldItem, @NonNull GBDevice newItem) {
return new EqualsBuilder()
.append(oldItem.getAddress(), newItem.getAddress())
.append(oldItem.getName(), newItem.getName())
.isEquals();
}
@Override
public boolean areContentsTheSame(@NonNull GBDevice oldItem, @NonNull GBDevice newItem) {
return EqualsBuilder.reflectionEquals(oldItem, newItem);
}
}
/**
* A generator of stable IDs, given a string, since hashCode can easily have collisions.
*/
private static class StableIdGenerator {
private final Map<String, Long> idMapping = new HashMap<String, Long>();
private long nextId = 0;
public long getId(final GBDevice device) {
final String str = String.format("%s_%s", device.getAddress(), device.getName());
if (!idMapping.containsKey(str)) {
idMapping.put(str, nextId++);
}
return idMapping.get(str);
}
}
} }