TrackList: swipe to delete.

This commit is contained in:
Dennis Guse
2025-03-26 21:48:53 +01:00
parent c34e9bd7b6
commit 5bea48096c
6 changed files with 39 additions and 5 deletions
@@ -43,6 +43,7 @@ public abstract class AbstractTrackDeleteActivity extends AbstractActivity imple
ConfirmDeleteDialogFragment.showDialog(getSupportFragmentManager(), trackIds);
}
//TODO A callback is better.
@Override
public void onConfirmDeleteDone(Track.Id... trackIds) {
ArrayList<Track.Id> trackIdList = Arrays.stream(trackIds)
@@ -34,7 +34,9 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.button.MaterialButton;
@@ -60,6 +62,7 @@ import de.dennisguse.opentracks.ui.aggregatedStatistics.AggregatedStatisticsActi
import de.dennisguse.opentracks.ui.aggregatedStatistics.ConfirmDeleteDialogFragment;
import de.dennisguse.opentracks.ui.markers.MarkerListActivity;
import de.dennisguse.opentracks.ui.util.ActivityUtils;
import de.dennisguse.opentracks.ui.util.RecyclerViewSwipeDeleteCallback;
import de.dennisguse.opentracks.util.IntentDashboardUtils;
import de.dennisguse.opentracks.util.IntentUtils;
import de.dennisguse.opentracks.util.PermissionRequester;
@@ -168,6 +171,13 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
viewBinding.trackList.setLayoutManager(layoutManager);
viewBinding.trackList.setAdapter(adapter);
ItemTouchHelper itemTouchhelper = new ItemTouchHelper(new RecyclerViewSwipeDeleteCallback(this) {
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
TrackListActivity.this.deleteTracks(new Track.Id(viewHolder.getItemId()));
}
});
itemTouchhelper.attachToRecyclerView(viewBinding.trackList);
viewBinding.trackListFabAction.setOnClickListener((view) -> {
if (recordingStatus.isRecording()) {
Toast.makeText(TrackListActivity.this, getString(R.string.hold_to_stop), Toast.LENGTH_LONG).show();
@@ -306,6 +316,12 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
adapter.swapData(tracks);
}
@Override
public void onConfirmDeleteAbort(Track.Id... trackIds) {
// This is not nice, but it will happen rarely (as deletion is not a standard case).
adapter.notifyItemRangeChanged(0, adapter.getItemCount());
}
@Override
protected void onDeleteConfirmed() {
// Do nothing
@@ -55,6 +55,7 @@ public class TrackListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
this.recyclerView = recyclerView;
this.recordingStatus = recordingStatus;
this.unitSystem = unitSystem;
setHasStableIds(true);
}
public void setActionModeCallback(ActivityUtils.ContextualActionModeCallback actionModeCallback) {
@@ -76,6 +77,12 @@ public class TrackListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
viewHolder.bind(cursor);
}
@Override
public long getItemId(int position) {
cursor.moveToPosition(position);
return cursor.getLong(cursor.getColumnIndexOrThrow(TracksColumns._ID));
}
@Override
public int getItemCount() {
if (cursor == null) {
@@ -234,6 +241,7 @@ public class TrackListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
viewBinding.getRoot().setActivated(isSelected);
}
//TODO Check if this still required.
public long getId() {
return trackId.id();
}
@@ -75,7 +75,8 @@ public class ConfirmDeleteDialogFragment extends DialogFragment {
getActivity(),
titleId,
getString(messageId),
(dialog, which) -> caller.onConfirmDeleteDone(trackIds)
(dialog, which) -> caller.onConfirmDeleteDone(trackIds),
(dialog, which) -> caller.onConfirmDeleteAbort(trackIds)
);
}
@@ -86,6 +87,9 @@ public class ConfirmDeleteDialogFragment extends DialogFragment {
*/
public interface ConfirmDeleteCaller {
default void onConfirmDeleteAbort(Track.Id... trackIds) {
}
void onConfirmDeleteDone(Track.Id... trackIds);
}
}
@@ -71,13 +71,18 @@ public class DeleteMarkerDialogFragment extends DialogFragment {
int titleId = markerIds.length > 1 ? R.string.generic_delete_selected_confirm_title : R.string.marker_delete_one_confirm_title;
int messageId = markerIds.length > 1 ? R.string.marker_delete_multiple_confirm_message : R.string.marker_delete_one_confirm_message;
return DialogUtils.createConfirmationDialog(
fragmentActivity, titleId, getString(messageId), (dialog, which) -> new Thread(() -> {
fragmentActivity, titleId, getString(messageId),
(dialog, which) -> new Thread(() -> {
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(fragmentActivity);
for (Marker.Id markerId : markerIds) {
contentProviderUtils.deleteMarker(context, markerId);
}
caller.onMarkerDeleted();
}).start());
}
).start(),
(dialog, which) -> {
// None
});
}
/**
@@ -42,12 +42,12 @@ public class DialogUtils {
* @param message the message
* @param okListener the listener when OK is clicked
*/
public static Dialog createConfirmationDialog(final Context context, int titleId, String message, DialogInterface.OnClickListener okListener) {
public static Dialog createConfirmationDialog(final Context context, int titleId, String message, DialogInterface.OnClickListener okListener, DialogInterface.OnClickListener cancelListener) {
return new AlertDialog.Builder(context)
.setCancelable(true)
.setIcon(R.drawable.ic_delete_forever_24dp)
.setMessage(message)
.setNegativeButton(android.R.string.cancel, null)
.setNegativeButton(android.R.string.cancel, cancelListener)
.setPositiveButton(android.R.string.ok, okListener)
.setTitle(titleId).create();
}