From 4b16829ace7160afba02d7f9bba516bd40f1fcbd Mon Sep 17 00:00:00 2001 From: Damyan Ivanov Date: Tue, 16 Feb 2021 22:15:40 +0200 Subject: [PATCH] implement swipe-remove and drag-move in template details --- .../ui/templates/TemplateDetailsAdapter.java | 104 +++++++++++++++++- .../ui/templates/TemplateDetailsFragment.java | 2 +- .../templates/TemplateDetailsViewModel.java | 12 ++ .../res/layout/template_details_account.xml | 12 +- 4 files changed, 124 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateDetailsAdapter.java b/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateDetailsAdapter.java index 1d79120b..c7e59c3d 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateDetailsAdapter.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateDetailsAdapter.java @@ -20,6 +20,7 @@ package net.ktnx.mobileledger.ui.templates; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; @@ -28,6 +29,7 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.AsyncListDiffer; import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; import net.ktnx.mobileledger.R; @@ -54,8 +56,11 @@ import java.util.regex.Pattern; class TemplateDetailsAdapter extends RecyclerView.Adapter { private static final String D_TEMPLATE_UI = "template-ui"; private final AsyncListDiffer differ; - public TemplateDetailsAdapter() { + private final TemplateDetailsViewModel mModel; + private final ItemTouchHelper itemTouchHelper; + public TemplateDetailsAdapter(TemplateDetailsViewModel model) { super(); + mModel = model; setHasStableIds(true); differ = new AsyncListDiffer<>(this, new DiffUtil.ItemCallback() { @Override @@ -90,6 +95,97 @@ class TemplateDetailsAdapter extends RecyclerView.Adapter dropTargets, int curX, int curY) { + RecyclerView.ViewHolder best = null; + int bestDistance = 0; + for (RecyclerView.ViewHolder v : dropTargets) { + if (v == selected) + continue; + + final int viewTop = v.itemView.getTop(); + int distance = Math.abs(viewTop - curY); + if (best == null) { + best = v; + bestDistance = distance; + } + else { + if (distance < bestDistance) { + bestDistance = distance; + best = v; + } + } + } + + Logger.debug("dnd", "Best target is " + best); + return best; + } + @Override + public boolean canDropOver(@NonNull RecyclerView recyclerView, + @NonNull RecyclerView.ViewHolder current, + @NonNull RecyclerView.ViewHolder target) { + final int adapterPosition = target.getAdapterPosition(); + + // first item is immovable + if (adapterPosition == 0) + return false; + + return super.canDropOver(recyclerView, current, target); + } + @Override + public int getMovementFlags(@NonNull RecyclerView recyclerView, + @NonNull RecyclerView.ViewHolder viewHolder) { + int flags = 0; + // the top item (transaction params) is always there + final int adapterPosition = viewHolder.getAdapterPosition(); + if (adapterPosition > 0) + flags |= makeFlag(ItemTouchHelper.ACTION_STATE_DRAG, + ItemTouchHelper.UP | ItemTouchHelper.DOWN) | + makeFlag(ItemTouchHelper.ACTION_STATE_SWIPE, + ItemTouchHelper.START | ItemTouchHelper.END); + + return flags; + } + @Override + public boolean onMove(@NonNull RecyclerView recyclerView, + @NonNull RecyclerView.ViewHolder viewHolder, + @NonNull RecyclerView.ViewHolder target) { + + final int fromPosition = viewHolder.getAdapterPosition(); + final int toPosition = target.getAdapterPosition(); + mModel.moveItem(fromPosition, toPosition); + + return true; + } + @Override + public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { + int pos = viewHolder.getAdapterPosition(); + mModel.removeItem(pos); + } + }); + } + @Override + public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + + itemTouchHelper.attachToRecyclerView(recyclerView); + } + @Override + public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) { + super.onDetachedFromRecyclerView(recyclerView); + + itemTouchHelper.attachToRecyclerView(null); } @Override public long getItemId(int position) { @@ -560,6 +656,12 @@ class TemplateDetailsAdapter extends RecyclerView.Adapter { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + itemTouchHelper.startDrag(this); + } + return false; + }); } @Override void bind(TemplateDetailsItem item) { diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateDetailsFragment.java b/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateDetailsFragment.java index d8d1bb90..50088be3 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateDetailsFragment.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateDetailsFragment.java @@ -117,7 +117,7 @@ public class TemplateDetailsFragment extends QRScanCapableFragment { } - TemplateDetailsAdapter adapter = new TemplateDetailsAdapter(); + TemplateDetailsAdapter adapter = new TemplateDetailsAdapter(mViewModel); b.patternDetailsRecyclerView.setAdapter(adapter); mViewModel.getItems(mPatternId) .observe(getViewLifecycleOwner(), adapter::setItems); diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateDetailsViewModel.java b/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateDetailsViewModel.java index 40647875..5132af26 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateDetailsViewModel.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateDetailsViewModel.java @@ -184,4 +184,16 @@ public class TemplateDetailsViewModel extends ViewModel { taDAO.finishSave(mPatternId); }); } + public void moveItem(int sourcePos, int targetPos) { + ArrayList newList = new ArrayList<>(items.getValue()); + TemplateDetailsItem item = newList.remove(sourcePos); + newList.add(targetPos, item); + items.setValue(newList); + } + public void removeItem(int position) { + ArrayList newList = new ArrayList<>(items.getValue()); + newList.remove(position); + checkItemConsistency(newList); + items.setValue(newList); + } } \ No newline at end of file diff --git a/app/src/main/res/layout/template_details_account.xml b/app/src/main/res/layout/template_details_account.xml index c8c5285f..a0cae774 100644 --- a/app/src/main/res/layout/template_details_account.xml +++ b/app/src/main/res/layout/template_details_account.xml @@ -21,17 +21,21 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:animateLayoutChanges="true" - android:paddingHorizontal="@dimen/text_margin" + android:padding="@dimen/text_margin" >