Android Arraylist с возможностью Drag and drop
Как сделать Fragment с RecyclerView в котором будет Arraylist с MaterialCardView в котором будут TextView и ImageView но при этом при нажатии на ImageView можно перетаскивать по RecyclerView меняя местами с другими MaterialCardView.То есть Drag and drop. В примере material-components-android используется generateCardNumbers но я не знаю как его заменить на Arraylist так что бы я сам мог выставлять количество проявляемых MaterialCardView и мог менять в них текст. Как это сделать?
Я знаю что кода много, поэтому загрузил исходники в github https://github.com/Buldog18/Drag-and-drop
В Styles
style name="AppTheme"parent="Theme.MaterialComponents.Light.DarkActionBar"
CardAdapter
public class CardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public int[] cardNumbers;
private ItemTouchHelper itemTouchHelper;
CardAdapter(int[] cardNumbers) {
this.cardNumbers = cardNumbers;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.fragment_card, parent, /* attachToRoot= */ false);
return new CardViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
((CardViewHolder) viewHolder).bind(cardNumbers[position], itemTouchHelper);
}
@Override
public int getItemCount() {
return cardNumbers.length;
}
void setItemTouchHelper(ItemTouchHelper itemTouchHelper) {
this.itemTouchHelper = itemTouchHelper;
}
private static class CardViewHolder extends RecyclerView.ViewHolder {
private final TextView titleView;
private final View dragHandleView;
private CardViewHolder(View itemView) {
super(itemView);
titleView = itemView.findViewById(R.id.card_txt);
dragHandleView = itemView.findViewById(R.id.card_img);
}
@SuppressLint("ClickableViewAccessibility")
private void bind(int cardNumber, final ItemTouchHelper itemTouchHelper) {
titleView.setText(String.format(Locale.getDefault(), "Card #%02d", cardNumber));
dragHandleView.setOnTouchListener(
(v, event) -> {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
itemTouchHelper.startDrag(CardViewHolder.this);
return true;
}
return false;
});
}
}
}
CardItemTouchHelperCallback
public class CardItemTouchHelperCallback extends ItemTouchHelper.Callback {
private static final int DRAG_FLAGS = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
private static final int SWIPE_FLAGS = 0;
private final CardAdapter cardAdapter;
@Nullable
private MaterialCardView dragCardView;
CardItemTouchHelperCallback(CardAdapter cardAdapter) {
this.cardAdapter = cardAdapter;
}
@Override
public int getMovementFlags(
@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
return makeMovementFlags(DRAG_FLAGS, SWIPE_FLAGS);
}
@Override
public boolean onMove(
@NonNull RecyclerView recyclerView,
@NonNull RecyclerView.ViewHolder viewHolder,
@NonNull RecyclerView.ViewHolder target) {
int fromPosition = viewHolder.getAdapterPosition();
int toPosition = target.getAdapterPosition();
swapCards(fromPosition, toPosition, cardAdapter);
return true;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
}
@Override
public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG && viewHolder != null) {
dragCardView = (MaterialCardView) viewHolder.itemView;
dragCardView.setDragged(true);
} else if (actionState == ItemTouchHelper.ACTION_STATE_IDLE && dragCardView != null) {
dragCardView.setDragged(false);
dragCardView = null;
}
}
static void swapCards(int fromPosition, int toPosition, CardAdapter cardAdapter) {
int fromNumber = cardAdapter.cardNumbers[fromPosition];
cardAdapter.cardNumbers[fromPosition] = cardAdapter.cardNumbers[toPosition];
cardAdapter.cardNumbers[toPosition] = fromNumber;
cardAdapter.notifyItemMoved(fromPosition, toPosition);
}
}
NotificationsFragment
public class NotificationsFragment extends Fragment {
public static NotificationsFragment newInstance() {
return new NotificationsFragment();
}
private static final int CARD_COUNT = 30;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_notifications, container, false);
}
@Override
public void onViewCreated(@NonNull final View view, @Nullable Bundle savedInstanceState) {
RecyclerView recyclerView = view.findViewById(R.id.card_recy);
CardAdapter cardAdapter = new CardAdapter(generateCardNumbers());
ItemTouchHelper itemTouchHelper =
new ItemTouchHelper(new CardItemTouchHelperCallback(cardAdapter));
// Provide an ItemTouchHelper to the Adapter; can't use constructor due to circular dependency.
cardAdapter.setItemTouchHelper(itemTouchHelper);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(cardAdapter);
recyclerView
.setAccessibilityDelegateCompat(new RecyclerViewAccessibilityDelegate(recyclerView) {
@NonNull
@Override
public AccessibilityDelegateCompat getItemDelegate() {
return new ItemDelegate(this) {
@Override
public void onInitializeAccessibilityNodeInfo(View host,
AccessibilityNodeInfoCompat info) {
super.onInitializeAccessibilityNodeInfo(host, info);
int position = recyclerView.getChildLayoutPosition(host);
if (position != 0) {
info.addAction(new AccessibilityNodeInfoCompat.AccessibilityActionCompat(R.id.move_card_up_action,
host.getResources().getString(R.string.cat_card_action_move_up)));
}
if (position != (CARD_COUNT - 1)) {
info.addAction(new AccessibilityNodeInfoCompat.AccessibilityActionCompat(
R.id.move_card_down_action,
host.getResources().getString(R.string.cat_card_action_move_down)));
}
}
@Override
public boolean performAccessibilityAction(View host, int action, Bundle args) {
int fromPosition = recyclerView.getChildLayoutPosition(host);
if (action == R.id.move_card_down_action) {
swapCards(fromPosition, fromPosition + 1, cardAdapter);
return true;
} else if (action == R.id.move_card_up_action) {
swapCards(fromPosition, fromPosition - 1, cardAdapter);
return true;
}
return super.performAccessibilityAction(host, action, args);
}
};
}
});
itemTouchHelper.attachToRecyclerView(recyclerView);
}
private static int[] generateCardNumbers() {
int[] cardNumbers = new int[CARD_COUNT];
for (int i = 0; i < CARD_COUNT; i++) {
cardNumbers[i] = i + 1;
}
return cardNumbers;
}
}
fragment_card
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cat_card_list_item_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="8dp"
android:clickable="true"
android:focusable="true"
android:minHeight="118dp">
<TextView
android:id="@+id/card_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:layout_marginRight="16dp"
android:textAppearance="?attr/textAppearanceHeadline6"/>
<ImageView
android:id="@+id/card_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:padding="16dp"
android:src="@drawable/ic_quick_menu"
tools:targetApi="jelly_bean"/>
</com.google.android.material.card.MaterialCardView>
fragment_notifications
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/card_recy"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>