Android cardview change position with drag and drop - java

I want to make my cardviews inside a fragment(Navigation Drawler) able to change the position in the list with drag and drop.
my layout file structure:
FrameLayout{
LinearLayout{
cardview_1
card_view_2}}

Use a recyclerView and make the rowItemLayout.xml or columnItemLayout.xml with cardView as root View.
Then use the functions of recyclerView such as:
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(createHelperCallback());
itemTouchHelper.attachToRecyclerView(recyclerView);
private ItemTouchHelper.Callback createHelperCallback() {
ItemTouchHelper.SimpleCallback simpleItemTouchCallback =
new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN,
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
moveItem(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
#Override
public void onSwiped(final RecyclerView.ViewHolder viewHolder, int swipeDir) {
deleteItem(viewHolder.getAdapterPosition());
}
};
return simpleItemTouchCallback;
}
private void moveItem(int oldPos, int newPos) {
ListItem item = (ListItem) listData.get(oldPos);
listData.remove(oldPos);
listData.add(newPos, item);
adapter.notifyItemMoved(oldPos, newPos);
}
private void deleteItem(final int position) {
listData.remove(position);
adapter.notifyItemRemoved(position);
}

Related

How to prohibit deleting a certain type of element in RecyclerView with a swipe(I want the element not to move)?

I have 2 types of items in RecyclerView: Tier = 0 and Row = 1; And I want to delete only "Row"with a swipe. Of course, simply banning is not a problem. And how to remove the possibility of shifting the element on the adapter?
ItemTouchHelper helper = new ItemTouchHelper(
new ItemTouchHandler(0,
ItemTouchHelper.LEFT)
);
helper.attachToRecyclerView(recyclerView);
Class itself
private class ItemTouchHandler extends ItemTouchHelper.SimpleCallback {
public ItemTouchHandler(int dragDirs, int swipeDirs) {
super(dragDirs, swipeDirs);
}
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
int from = viewHolder.getAdapterPosition();
int to = target.getAdapterPosition();
Collections.swap(recyclerAdapter.getMoviesList(), from, to);
recyclerAdapter.notifyItemMoved(from, to);
return true;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
recyclerAdapter.deleteRow(viewHolder.getAdapterPosition());
}
This is deleting an item in the adapter:
public void deleteRow(int position) {
moviesList.remove(position);
notifyDataSetChanged();
}
in my case
#Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = 0;
int swipeFlags = 0;
if(recyclerAdapter.getMoviesList().get(viewHolder.getAdapterPosition()).getType()==Element.TYPE_TIER) {
swipeFlags = 0;
} else {
swipeFlags = ItemTouchHelper.LEFT;
}
return makeMovementFlags(dragFlags, swipeFlags);
}

Disable ItemTouchHelper Swipe for some rows in RecyclerView

I'm simply using following methods to do the Right and Left swipe on my Data list.and it works fine. and I want to know how to disable swipe action for some rows in the data list.
ex: there is some data user should not be able delete. I want to restrict those rows.
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
//Remove swiped item from the list and notify the RecyclerView
}
#Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
}
};
Use getMovementFlags() of your ItemTouchHelper.SimpleCallback. You would need to detect the view holders for which you want to disallow swiping by not returning swipe flags.
Here is a sample of where swiping is disallowed for a grid layout.
#Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
// Set movement flags based on the layout manager
if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
final int swipeFlags = 0;
return makeMovementFlags(dragFlags, swipeFlags);
} else {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}
}
i want to disable swipe where object Marked Type not equal to 1
#Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
final int position = viewHolder.getAdapterPosition();
int sectionIndex = listAdapter.getSectionForAdapterPosition(position);
int itemIndex = listAdapter.getPositionOfItemInSection(sectionIndex, position);
myModelObject temp = filteredArrayList.get(sectionIndex).get(itemIndex);
if(!temp.getMarkedType().equals("1")){
return 0;
}
return super.getSwipeDirs(recyclerView, viewHolder);
}

How to use ItemTouchHelper properly

I'm trying to use a RecyclerView with ItemTouchHelper for basic “drag & drop” and “swipe-to-dismiss” implementation.
Swipe works correctly, items are deleted in adapter correctly, animation is correct, but “drag & drop” behaviour is very strange. After long click view isn't moving, however swapping items in adapter are correct.
this is how it works in my RecyclerView
and this is what I want
This code in my presenter, onSelectedChanged and clearView only to demonstrate clearly how items are selected.
addedCitiesRecycler.setLayoutManager(llmAddedCities);
adapterAddedCities = new AdapterAddedCities();
ItemTouchHelper.SimpleCallback callback = new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.START | ItemTouchHelper.END) {
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
adapterAddedCities.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
adapterAddedCities.onItemDismiss(viewHolder.getAdapterPosition());
}
#Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
AdapterAddedCities.ViewHolder holder = (AdapterAddedCities.ViewHolder) viewHolder;
holder.itemView.setBackgroundColor(Color.LTGRAY);
}
super.onSelectedChanged(viewHolder, actionState);
}
#Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
AdapterAddedCities.ViewHolder holder = (AdapterAddedCities.ViewHolder) viewHolder;
holder.itemView.setBackgroundColor(0);
}
};
itemTouchHelper = new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(addedCitiesRecycler);
this methods in my adapter
public void onItemDismiss(int position) {
citiesData.remove(position);
notifyItemRemoved(position);
}
public void onItemMove(int fromPosition, int toPosition) {
CityInfo tmp = citiesData.remove(fromPosition);
citiesData.add(toPosition > fromPosition ? toPosition - 1 : toPosition, tmp);
notifyItemMoved(fromPosition, toPosition);
}
I've updated com.android.support:recyclerview-v7:26.0.0-alpha1 to com.android.support:recyclerview-v7:27.0.0 in build.gradle and it works fine.
I think it was bug in the library, so if you face the same issue, just update the library to the latest version.

ItemTouchHelper onSwiped() doesn't update data from constructor

I have created a class to handle swipe events:
public class CardViewSwipeListener : ItemTouchHelper.Callback
{
private Context context;
private List<Person> listWithData;
private const int RESET_ADAPTER = 1;
public CardViewSwipeListener(Context context, List<Person> listWithData)
{
this.context = context;
this.listWithData = listWithData;
}
public override int GetMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)
{
int swipeFlags = ItemTouchHelper.Start | ItemTouchHelper.End;
return MakeMovementFlags(0, swipeFlags);
}
public override bool OnMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)
{
return true;
}
public override void OnSwiped(RecyclerView.ViewHolder viewHolder, int direction)
{
if (direction == ItemTouchHelper.End)
{
((Activity)context).StartActivityForResult(new Intent(Intent.ActionCall, Android.Net.Uri.Parse(string.Format("tel:{0}", listWithData[viewHolder.AdapterPosition].PhoneNumber))),RESET_ADAPTER);
Toast.MakeText(context,"Call "+listWithData[viewHolder.AdapterPosition].Name,ToastLength.Short).Show();
}
else if (direction == ItemTouchHelper.Start)
{
((Activity)context).StartActivityForResult(new Intent(Intent.ActionView, Android.Net.Uri.Parse(string.Format("sms:{0}", this.listWithData[viewHolder.AdapterPosition].PhoneNumber))),RESET_ADAPTER;
Toast.MakeText(context, "SMS " + this.listWithData[viewHolder.AdapterPosition].Name, ToastLength.Short).Show();
}
}
}
In MainActivivty onCreate I use the following code to provide the recycler view to handle swipe events.
itemTouchHelper = new ItemTouchHelper(new CardViewSwipeListener(this, listWithData));
recycler = FindViewById<RecyclerView>(Resource.Id.recycler);
recycler.HasFixedSize = true;
layoutManager = new LinearLayoutManager(this);
recycler.SetLayoutManager(layoutManager);
recycler.SetAdapter(new RecyclerViewAdapter(listWithData,this));
itemTouchHelper.AttachToRecyclerView(recycler);
The problem is that I need to change listWithData to another one, but when I do that onSwipe doesn't consider any changes.
Have no result:
itemTouchHelper = new ItemTouchHelper(new CardViewSwipeListener(this, NewList));
recycler.SetAdapter(new RecyclerViewAdapter(NewList,this));
itemTouchHelper.AttachToRecyclerView(recycler);
Java code solutions are also accepted)
The problem is that i need to change listWithData to another one, but when i do that onSwipe doesn't consider any changes.
You could write a Interface to listen for a dismissal event from a ItemTouchHelper.Callback :
public interface IItemHelper
{
//Called when an item has been dismissed by a swipe.
void onItemDismiss(int position);
}
Implement IItemHelper interface in your RecyclerViewAdapter class :
public class MyRecyclerViewAdapter : RecyclerView.Adapter,IItemHelper
{
List<string> items;
...
public MyRecyclerViewAdapter(List<string> data)
{
items = data;
}
...
//Called when an item has been dismissed by a swipe.
public void onItemDismiss(int position)
{
items.RemoveAt(position);
NotifyItemRemoved(position);
}
}
When you swip a Item, tell the adapter to dismiss this item:
public class CardViewSwipeListener : ItemTouchHelper.Callback
{
...
public override void OnSwiped(RecyclerView.ViewHolder viewHolder, int direction)
{
if (direction == ItemTouchHelper.End)
{
...
}
else if (direction == ItemTouchHelper.Start)
{
...
}
recyclerViewAdapter.onItemDismiss(viewHolder.AdapterPosition);
}
}
Effect like this.

change the position of two view (Text view ) using Drag And Drop functionality

i want change the position of Text View using drag and drop functionally in android using Drag listener and animation. i am done a design using following code. i want to change the order of text view using Drag Listener. thanks i give a image of design and i want change position of text view using drag and drop
public void loadtable()
{
Sorting_Linear = (LinearLayout) findViewById(R.id.Sorting_Linear);
submit = (Button) findViewById(R.id.submit);
LinearLayout[] llRow = new LinearLayout[5];
final TextView[] outletnametxt = new TextView[5];
final ImageView[] imageButtonup = new ImageView[5];
final ImageView[] imageButtondown = new ImageView[5];
final LinearLayout[] Linearlayout = new LinearLayout[5];
for (int i = 0; i < 5; i++) {
llRow[i] = new LinearLayout(mContext);
LinearLayout.LayoutParams paramsllRow = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
paramsllRow.setMargins(0, 2, 0, 0);
llRow[i].setLayoutParams(paramsllRow);
llRow[i].setOrientation(LinearLayout.HORIZONTAL);
outletnametxt[i] = new TextView(mContext);
outletnametxt[i].setLayoutParams(nametxt);
outletnametxt[i].setText(olm_name[i]);
outletnametxt[i].setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
outletnametxt[i].setTextSize(20);
outletnametxt[i].setGravity(Gravity.CENTER);
outletnametxt[i].setBackgroundColor(mContext.getResources().getColor(android.R.color.white));
llRow[i].addView(outletnametxt[i]);
imageButtonup[i] = new ImageView(mContext);
imageButtonup[i].setLayoutParams(imagebtnup);
imageButtonup[i].setImageResource(R.drawable.arrowup);
imageButtondown[i] = new ImageView(mContext);
imageButtondown[i].setLayoutParams(imagebtndown);
imageButtondown[i].setImageResource(R.drawable.arrowdown);
Linearlayout[i] = new LinearLayout(mContext);
Linearlayout[i].setLayoutParams(linearlayout);
Linearlayout[i].setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
Linearlayout[i].setBackgroundColor(mContext.getResources().getColor(android.R.color.white));
Linearlayout[i].setOrientation(LinearLayout.VERTICAL);
Linearlayout[i].addView(imageButtonup[i]);
Linearlayout[i].addView(imageButtondown[i]);
llRow[i].addView(Linearlayout[i]);
Sorting_Linear.addView(llRow[i]);
}
Create below interface ItemTouchHelperAdapter
public interface ItemTouchHelperAdapter {
boolean onItemMove(int fromPosition, int toPosition);
void onItemDismiss(int position);}
Create second interface ItemTouchHelperViewHolder
public interface ItemTouchHelperViewHolder {
void onItemSelected();
void onItemClear();}
Create OnStartDragListener
public interface OnStartDragListener {
void onStartDrag(RecyclerView.ViewHolder viewHolder);}
Create below class
public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
public static final float ALPHA_FULL = 1.0f;
private final ItemTouchHelperAdapter mAdapter;
public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
mAdapter = adapter;
}
#Override
public boolean isLongPressDragEnabled() {
return true;
}
#Override
public boolean isItemViewSwipeEnabled() {
return true;
}
#Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
// Set movement flags based on the layout manager
if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
final int swipeFlags = 0;
return makeMovementFlags(dragFlags, swipeFlags);
} else {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
final int swipeFlags = 0;
return makeMovementFlags(dragFlags, swipeFlags);
}
}
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) {
if (source.getItemViewType() != target.getItemViewType()) {
return false;
}
// Notify the adapter of the move
mAdapter.onItemMove(source.getAdapterPosition(), target.getAdapterPosition());
return true;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int i) {
// Notify the adapter of the dismissal
mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
}
#Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
// Fade out the view as it is swiped out of the parent's bounds
final float alpha = ALPHA_FULL - Math.abs(dX) / (float) viewHolder.itemView.getWidth();
viewHolder.itemView.setAlpha(alpha);
viewHolder.itemView.setTranslationX(dX);
} else {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
}
#Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
// We only want the active item to change
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
if (viewHolder instanceof ItemTouchHelperViewHolder) {
// Let the view holder know that this item is being moved or dragged
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
itemViewHolder.onItemSelected();
}
}
super.onSelectedChanged(viewHolder, actionState);
}
#Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setAlpha(ALPHA_FULL);
if (viewHolder instanceof ItemTouchHelperViewHolder) {
// Tell the view holder it's time to restore the idle state
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
itemViewHolder.onItemClear();
}
}}
Now just add this code to your recycler view adapter
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new RecyclerListAdapter(Activity_OutletSorting.this, onStartDragListener, olm_name,idopeningclosing);
recyclerView.setAdapter(adapter);
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter);
mItemTouchHelper = new ItemTouchHelper(callback);
mItemTouchHelper.attachToRecyclerView(recyclerView);

Categories

Resources