Custom swipe ItemTouchHelper - android

Hi i have add ItemTouchHelper to my listview and i have do MyItemTouchHelper.attachToRecyclerView(myRecyclerView), then i have implements code for swipe to right:
private ItemTouchHelper itemTouchHelperEventi = new ItemTouchHelper(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 swipeDir) {
Evento ev = lista_eventi.get(viewHolder.getAdapterPosition());
analizzaEvento = new AnalizzaEvento(ev.getNome_evento());
adapterRecyclerViewEventi.remove(positionForResult);
adapterRecyclerViewEventi.notifyDataSetChanged();
}
});
Now i want to implement swipe code to remove item how gmail, i want that when i swipe to right background row becomes red and at left of row there is label undo and at right of row there is label delete (or confirm) if i click on right i delete item if i click on left return to the previous situation.
Please don't link other library i want to add this festure at my code without using external library, i don't want to rewrite all code only for this feature.
Is it possible?

Here is sample code
ItemTouchHelper.Callback simpleItemTouchCallback=new ItemTouchHelper.Callback() {
#Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
//Unlock the movement of the item
//If you want only left to right unlock that moment only
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags;
if(viewHolder instanceof HeterogenousAdapter.ImageViewHolder)
swipeFlags = ItemTouchHelper.ANIMATION_TYPE_SWIPE_CANCEL ;
else
swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END ;
return makeMovementFlags(dragFlags, swipeFlags);
}
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
//when user swiped this method getting call
int position = viewHolder.getAdapterPosition();
if (direction == ItemTouchHelper.LEFT){
adapter.removeItem(position);
}else {
removeView();
edit_position = position;
alertDialog.setTitle("Edit Country");
if (objectsArrayList.get(position) instanceof UserInfo){
UserInfo userInfo= (UserInfo) objectsArrayList.get(position);
et_country.setText(userInfo.getFirstName());
}else {
String abc= (String) objectsArrayList.get(position);
et_country.setText("ESHVAR");
}
alertDialog.show();
}
}
#Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
//when swiped started what you wants to do
//Here you can set Red color with icon on it
Bitmap icon;
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE){
View itemView = viewHolder.itemView;
float height=(float) itemView.getBottom() - (float) itemView.getTop();
float width =height/3;
if (dX > 0){
paint.setColor(Color.parseColor("#388e3c"));
RectF background = new RectF(
(float)itemView.getLeft(),
(float)itemView.getTop(),
dX,
(float)itemView.getBottom());
c.drawRect(background,paint);
icon = BitmapFactory.decodeResource(getResources(),R.drawable.action_search);
RectF icon_dest = new RectF(
(float)itemView.getLeft()+width,
itemView.getTop()+width,
(float)itemView.getLeft()+2*width,
(float)itemView.getBottom() - width);
c.drawBitmap(icon,null,icon_dest,paint);
}else {
paint.setColor(Color.parseColor("#d32f2f"));
RectF background = new RectF(
(float)itemView.getRight()+dX,
(float)itemView.getTop(),
(float)itemView.getRight(),
(float)itemView.getBottom());
c.drawRect(background,paint);
icon =BitmapFactory.decodeResource(getResources(),R.drawable.action_search);
RectF icon_dest=new RectF(
(float)itemView.getRight()-2*width,
(float)itemView.getTop()+width,
(float)itemView.getRight() - width,
(float)itemView.getBottom() - width);
c.drawBitmap(icon,null,icon_dest,paint);
}
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
};
//Adding Recycle view to Item touch helper
ItemTouchHelper itemTouchHelper=new ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(recyclerView);

Related

Android drag elevation translationz on cardview with itemTouchHelper in Recyclerview

i have a problem figuring out how to give cardViews temporarily elevation on drag. I use a recycler view with cardViews and this is my itemtouchhelper:
class ListTouchHelper extends ItemTouchHelper.Callback {
private final ActionCompletionContract contract;
public ListTouchHelper(ActionCompletionContract contract) {
this.contract = contract;
}
#Override
public int getMovementFlags(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
return makeMovementFlags(dragFlags, swipeFlags);
}
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
contract.onViewMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
if (direction == ItemTouchHelper.LEFT) {
contract.onViewSwipedLeft(viewHolder.getAdapterPosition());
} else if (direction == ItemTouchHelper.RIGHT) {
contract.onViewSwipedRight(viewHolder.getAdapterPosition());
}
}
public interface ActionCompletionContract {
void onViewMoved(int oldPosition, int newPosition);
void onViewSwipedLeft(int position);
void onViewSwipedRight(int position);
}
}
I have managed to give it temporarily elevation with:
Which resulted in: (the shadows are somehow clipped?)
However, once the view is just slightly moved, the elevation disappears:
My question is: how do i get the elevation (including shadows) when the cards are being dragged?
Thanks in advance!
#LivinTheNoobLife in your solution you are using the ViewPropertyAnimator, but you are not setting any translation to it, hence, no animations will be applied.
This is my solution with a properly working floating animation:
class DragHelper extends ItemTouchHelper.Callback {
private boolean cardPicked = true;
private boolean reset = false;
#Override
public void onChildDraw(#NonNull Canvas c, #NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
// elevate only when picked for the first time
if (cardPicked) {
ViewPropertyAnimator animator = viewHolder.itemView.animate();
animator.translationZ(16);
animator.setDuration(200);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.start();
cardPicked = false;
}
// when your item is not floating anymore
if (reset){
ViewPropertyAnimator animator = viewHolder.itemView.animate();
animator.translationZ(0);
animator.setDuration(200);
animator.setInterpolator(new AccelerateInterpolator());
animator.start();
cardPicked = true;
reset = false;
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
// As the doc says
// Called by the ItemTouchHelper when the user interaction with an element is over and it also completed its animation.
#Override
public void clearView(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
// interaction is over, time to reset our elevation
reset = true;
}
}
Ok so I solved it, kindof. I think for some other reason its not working by default, however I managed to write a workaround.
private boolean first = true; //first draw of cardView?
private boolean last = false; //last draw of cardView?
#Override
public void onChildDraw(#NonNull Canvas c, #NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
//add elevation on first draw
if (first) {
ViewPropertyAnimator animator = viewHolder.itemView.animate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //consider SDK version
viewHolder.itemView.setTranslationZ(7);
animator.start();
}
first = false;
}
//remove translationZ in last edit
if (last) {
ViewPropertyAnimator animator = viewHolder.itemView.animate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //consider SDK version
viewHolder.itemView.setTranslationZ(0);
animator.start();
}
//reset values
last=false;
first=true;
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
#Override
public void clearView(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
last = true; //only one more OnChildDrawWillBeCalled
}
The above code is added to your ItemTouchHelper.Callback and all should work.
The basic idea is to manually control the drawing of the translationz.
For that I figure out when is the first canvas drawn, and when the last, whereas the cancas will show the shadow.
Maxbe one more comment: the ViewPropertyAnimator in combination with the xml layout file is incredibly unintuitive and buggy, so if you can avoided I would reccomend to do so, and instead try programmatically animating the view changes and effects.
Hope this can help someone.

disable few cells in recycleView from swipe or hide delete while swiping

I have a custom recycleView with swipe to delete option. I am able to display custom recycleView and also delete the item by swipping it. Swipe to delete is implement by using a separate class which implements SimpleCallback. Now, i want to disable the swipe to delete or dont show delete button while swipping for few items based on the username displaying in the RecycleView.
public class SwipeHelper extends ItemTouchHelper.SimpleCallback {
private RecyclerItemTouchHelperListener listener;
SwipeHelper(int dragDirs, int swipeDirs, RecyclerItemTouchHelperListener listener) {
super(dragDirs, swipeDirs);
this.listener = listener;
}
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return true;
}
#Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
if (viewHolder != null) {
final View foregroundView = ((Adapter.ViewHolder) viewHolder).viewforeground;
getDefaultUIUtil().onSelected(foregroundView);
}
}
#Override
public void onChildDrawOver(Canvas c, RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder, float dX, float dY,
int actionState, boolean isCurrentlyActive) {
final View foregroundView = ((Adapter.ViewHolder) viewHolder).viewforeground;
getDefaultUIUtil().onDrawOver(c, recyclerView, foregroundView, dX, dY,
actionState, isCurrentlyActive);
}
#Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
final View foregroundView = ((Adapter.ViewHolder) viewHolder).viewforeground;
getDefaultUIUtil().clearView(foregroundView);
}
#Override
public void onChildDraw(Canvas c, RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder, float dX, float dY,
int actionState, boolean isCurrentlyActive) {
final View foregroundView = ((Adapter.ViewHolder) viewHolder).viewforeground;
getDefaultUIUtil().onDraw(c, recyclerView, foregroundView, dX, dY,
actionState, isCurrentlyActive);
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
listener.onSwiped(viewHolder, direction, viewHolder.getAdapterPosition());
}
#Override
public int convertToAbsoluteDirection(int flags, int layoutDirection) {
return super.convertToAbsoluteDirection(flags, layoutDirection);
}
public interface RecyclerItemTouchHelperListener {
void onSwiped(RecyclerView.ViewHolder viewHolder, int direction, int position);
}
}
And how I implemented
ItemTouchHelper.SimpleCallback itemTouchHelperCallback = new SwipeHelper(0, ItemTouchHelper.LEFT, this);
new ItemTouchHelper(itemTouchHelperCallback).attachToRecyclerView(recyclerView);
Viewholder in recycleView.
public class ViewHolder extends RecyclerView.ViewHolder {
TextView uname,time,comm;
CircleImageView civ;
RelativeLayout viewBackground,viewforeground;
ViewHolder(View itemView) {
super(itemView);
civ = (CircleImageView)itemView.findViewById(R.id.profile_image);
uname = (TextView) itemView.findViewById(R.id.username);
time = (TextView) itemView.findViewById(R.id.time);
comm = (TextView) itemView.findViewById(R.id.comments);
viewBackground = (RelativeLayout)itemView.findViewById(R.id.view_background);
viewforeground = (RelativeLayout)itemView.findViewById(R.id.view_foreground);
}
}
Now i want to disable the swipe for the username which is not matching with uname in viewholder. I searched SO they ask to do change in SwipeDirs method but there i am not able to get the viewHolder values inside of it. Please help.
Override getMovementFlags in your ItemTouchHelper.SimpleCallback to check the view holder for the conditions that permit swiping as follows:
#Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
final int dragFlags = 0;
final int swipeFlags;
swipeFlags = ([OK to swipe this view])
? ItemTouchHelper.START | ItemTouchHelper.END
: 0;
return makeMovementFlags(dragFlags, swipeFlags);
}
}

How to disable swipe Right in recylerview?

I have an app which contain recyclerview with adapter which populate some data in recyclerview.When i swipe left it delete item at that position. But problem is that i don't want swipe right i only want swipe left. How do i do that
code:-
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) {
int position = viewHolder.getAdapterPosition();
if (direction == ItemTouchHelper.LEFT){
adapter.removeItem(position);
}
}
#Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
Bitmap icon;
if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE){
View itemView = viewHolder.itemView;
float height = (float) itemView.getBottom() - (float) itemView.getTop();
float width = height / 3;
if(dX < 0){
p.setColor(Color.parseColor("#D32F2F"));
RectF background = new RectF((float) itemView.getRight() + dX, (float) itemView.getTop(),(float) itemView.getRight(), (float) itemView.getBottom());
c.drawRect(background,p);
icon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_delete);
RectF icon_dest = new RectF((float) itemView.getRight() - 2*width ,(float) itemView.getTop() + width,(float) itemView.getRight() - width,(float)itemView.getBottom() - width);
c.drawBitmap(icon,null,icon_dest,p);
}
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(notificationList);
Have you noticed your first line of code that this code will be fire when you swipe either LEFT or RIGHT
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
so Remove the RIGHT direction Code
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
and this will be works like charm :)
try this
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback
(0, ItemTouchHelper.LEFT ) {
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(recyclerView);
You can override this method in ItemTouchHelper.Callback:
#Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
final int swipeFlags = ItemTouchHelper.END; // or RIGHT
return makeMovementFlags(0, swipeFlags);
}

How to swipe both side left and right in recyclerview in android

I want to swipe recyclerview both side left and right like below image:-
But I can't do I see many library but I find only one side swipe . I want both side swipe how I do that help me to do do this.
Thanks in advance
You can try below given one lib you just have to some modification
https://github.com/daimajia/AndroidSwipeLayout
Thanks!
It maybe late, but could help.
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_childs, container, false);
recyclerView = v.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext(),LinearLayoutManager.VERTICAL,false));
recyclerView.addItemDecoration(new VerticalItemDecoration());
recyclerView.setAdapter(new ChildCareAdapter());
touchHelper.attachToRecyclerView(recyclerView); // Attaching with RecyclerView
return v;
}
ItemTouchHelper touchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder viewHolder1) {
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int i) {
if (i == ItemTouchHelper.LEFT) {
Toast.makeText(getContext(),"Swipe left",Toast.LENGTH_SHORT).show();
} else if (i == ItemTouchHelper.RIGHT) {
Toast.makeText(getContext(),"Swipe right",Toast.LENGTH_SHORT).show();
}
}
#Override
public void onChildDraw(#NonNull Canvas c, #NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
float alpha = 1 - (Math.abs(dX) / recyclerView.getWidth());
viewHolder.itemView.setAlpha(alpha);
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
});
You need something like this:
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getAdapterPosition();
if (direction == ItemTouchHelper.LEFT){
Log.i("ItemSwipe", "LEFT");
}
else if (direction == ItemTouchHelper.RIGHT){
Log.i("ItemSwipe", "RIGHT");
}
}

How to reset the recyclerview item after swiping using ItemTouchHelper

I have recyclerviewitem , on swiping left side , I am creating an image on the top of recyclerview item with the following code ,I am able to get the image on the top of the item but I am unable to reset the recyclerviewitem after swiping , rather its clearing the entire item
Code :
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT){
#Override
public boolean onMove(RecyclerView arg0,
RecyclerView.ViewHolder arg1,
RecyclerView.ViewHolder arg2) {
// TODO Auto-generated method stub
return false;
}
public void onChildDraw(android.graphics.Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE && isCurrentlyActive) {
// Get RecyclerView item from the ViewHolder
View itemView = viewHolder.itemView;
Drawable d = ContextCompat.getDrawable(getContext(), R.drawable.swipeleft);
d.setBounds(itemView.getLeft(), itemView.getTop(), (int) dX, itemView.getBottom());
d.draw(c);
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
};
#Override
public void onSwiped(
RecyclerView.ViewHolder viewHolder,
int Swipedir) {
}
};

Categories

Resources