When I delete an item from a RecyclerView I want to show a "swipe" animation, that is that the item is moved sideways off the screen. I believe there is support for "swipe to dismiss" using ItemTouchHelper, but this is touch-initiated whereas I want to be able to initiate the swipe programmatically.
I have also tried setting the RecyclerView item animator by extending DefaultItemAnimator. Using this method I can get items to swipe left and right but unfortunately the gap in the list closes quickly such that the swipe does not finish before the list item gap has closed.
Anyone know how to do this?
You can use ItemAnimators offered by this library. More specifically, your would use their SlideInLeftAnimator or SlideInRightAnimator.
Although it's already answered with external library; probably someone wants to do it with raw java.. I have done it with the solution in here
The idea is that, you take off the list item view of the RecyclerView to be deleted and animate it; and normally remove it from the adapter
private void removeListItem(View rowView, final int position) {
Animation anim = AnimationUtils.loadAnimation(this,
android.R.anim.slide_out_right);
anim.setDuration(500);
rowView.startAnimation(anim);
new Handler().postDelayed(new Runnable() {
public void run() {
values.remove(position); //Remove the current content from the array
adapter.notifyDataSetChanged(); //Refresh list
}
}, anim.getDuration());
}
Related
I would like to show a custom animation to match the other animations that I have in my RecyclerView. I can’t find a straight forward way of adding custom animations for removal. I know that when RecyclerView replaced ListView one of the talking points was the ability to know when items are added or removed rather than simply saying the dataset has changed and updating everything, so I figured there would be an easy way to add an animation to a View when it is removed that I am missing.
When I add an animation to a view that is removed the animation will not play. This is likely because the View is removed and the animation stops. Is there an easy way to add an animation to a View that doesn’t get cut off? I'm assuming that I could use a second thread, but I want to know if I am missing something.
//code for removal
holder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//animation to be added here on view
list.remove(holder.getAdapterPosition());
notifyItemRemoved(position);
notifyItemRangeChanged(position,list.size()-position);
}
});
All add/change/delete/move animations in recyclerView are made by ItemAnimator (by default animator is DefaultItemAnimator). So if you need custom delete animation you should provide custom ItemAnimator via recyclerView.setItemAnimator(animator) method.
I suggest to extend from SimpleItemAnimator and override animateRemove method.
I want to catch a vertical swipe in an horizontal RecyclerView. Each item is simply a CircleImageView.
I found many resources on internet (like Drag and swipe with RecyclerView, Android - Swipe to delete RecyclerView) but those solutions ends deleting the item. I don't know if the term swipe requires also that the item is deleted or not.
What I want to achieve is to catch the swipe action on an item in the RecyclerView, but without delete the item itself from the RecyclerView.
I think that a good idea is to override the method onChildDraw() like suggested here: How to detect if Recyclerview item is being swiped?, but I can't understand how to achieve the behaviour I want.
My idea is: while the user swipes an item, the item itself moves in that direction; when the user end the touch event, the item has to come back to the original position (maybe changing the background color).
EDIT 1:
How to have swipe to delete and swipe to archive in two colours in Recyclerview Android probably can help, but it doesn't achieve the behaviour that I need. The item has to come back to the original position.
Your RecyclerView has RecyclerView.Adapter attached to it. The adapter determines what information that the RecyclerView can see and display. So, if item number 10, out of a 100-item backing array (managed by you) is swiped, the adapter can report that the array now contains 99 items and not ever present the swiped item to the RecyclerView. That way the item appears to be deleted but is maintained internally and still accessible programmatically. How you manage that internal state is up to you and dependent upon your implementation.
If, however you want to not remove the item from the screen but just change its appearance, I think that you would need to look at the method onItemDismiss that actually removes the item and notifies the adapter of the data change.
public void onItemDismiss(int position) {
mItems.remove(position);
notifyItemRemoved(position);
}
It is here that you would make the change. The item would stay in the adapter. You would also need to flag that position as "swiped" in case the view holders are recycle so you can maintain the visual "swiped" state.
public void onItemDismiss(int position) {
// Change background color, etc.
}
Take a look at code that has a "swipe to delete" function with "undo" for some ideas. Here is an example with a dialog that is called before deletion actually occurs if "Cancel" is clicked. There are many other examples of "undo" available. What you are trying to do can be considered to be an immediate and implicit "undo" with a visual change to the background.
If you want to have the item move back into position after a swipe, the following should work:
public void onItemDismiss(int position) {
notifyItemChanged(position);
}
How do i get a specific view inside of a RecyclerView item? For example I have a floating action button inside of a recyclerview item. The recyclerview card can swipe to trigger an event (new activity) and when the user swipes i am making the fab invisible. I want so that when the user returns back to the activity with the recyclerview, the fab is visible again.
I've tried to implement this a few ways, but for some reason it's taking the fab from the NEXT card/item and placing it on the original card/item that was swiped. This is a problem because the next card might have a different colored fab or no fab at all. What is happening is that it's taking the most recent viewholder item, even if the previous one is the one I want to deal with.
So i need a way to reference the fab in the current item. I'm currently setting it to currentFab = holder.mFab (but again, it's taking the most recent holder item even though it's not the one I pressed on). I need a way to reference the fab in a specific item.
I've tried something similar in the past, I've added the Swipe function in "onBindViewHolder ", Using a Swipe Library.
What I have made is, A CardView, Inside it there are 2 Strings, And a Button, this Button will be invisible according to specific conditions, So because it's inside onBindVewHolder, it was easy to make some edits on the button.
Here's a sample :
holder.Button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.Button.setVisibility(View.GONE);
}
});
Ofcourse this isn't a "fully working code" it's just an example, Plus you didn't put any code that you have tried.
I am trying to add pagination in my listView.
I added a method in my custom BaseAdapter which adds next page results at top of list on scroll to first item in list.
public void addEntriesToTop(List<ChatModel> entries) {
// Add entries to the top of the list
this.chatMessages.addAll(0, entries);
notifyDataSetChanged();
}
So if I have to add next page on top of ListView, I am using like this in my activity.
//result contain new items to be added to top of list
adapter.addEntriesToTop(result);
//so that list scroll sets to last visible message to user
final int index = result.size();
listView.post(new Runnable() {
#Override
public void run() {
//go to user's last scroll position
messagesContainer.setSelectionFromTop(index, 0);
}
});
This method is working fine and retains user's last scroll position. But it has a problem, when I call addEntriesToTop() it scrolls the ListView to bottom(because of notifyDataSetChanged() ) and then when I call setSelectionFromTop it scrolls to user's last position. In this transition, there is small jerk.
Please help me to smooth this transition.
Thanks
As ListView is old and now its obselete, now you can use Recyclerview
instead of ListView, here is the link that helps you to convert your
ListView to RecyclerView. RecyclerView have many methods to add your custom animations and also it have not any jerks while adding/removing items.
Replacing ListView with RecyclerView
For Default Animations you can use this link:
RecyclerView Animations – Add & Remove Items
I have a listView that has a layout animation that fades in each item one at a time.
lac = new LayoutAnimationController(AnimationUtils.loadAnimation(this, R.anim.listview_2), 0.25f);
listOptions.setLayoutAnimation(lac);
listOptions.setLayoutAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
When the user selects an item, the listView displays a new set of items - each fading in one at a time. However, if the fade in animation of the items has not completed when the user selects an item and causes a new set to fade in, then these animations overlap causing and the previous items can be seen while the new ones are fading in. It looks like a blinking glitch on the ListView.
onItemClick(), even if I call listView.getLayoutAnimation.getAnimation().cancel(); I still get the same blinking problem.
I have also tried listView.clearAnimation();, still didn't work.
I have also tried: listView.setLayoutAnimation(null); and resetting. Still didn't work.
It appears I am unable to stop or cancel the animation!
All I want to do is, onItemclick() in my listView, to stop the animation or empty / clear the listView then reload the new items into the listView and fade them in using the animation, with no overlap - and therefore - no blinking glitch.
I do not want to disable the listView until the animation completes, then re-enable, because it can create awkwardly long wait times.
Animation in ListViews are challenging which is one of the reasons Google released RecyclerView. However, this video may have some clues for how to make this work for you: https://www.youtube.com/watch?v=8MIfSxgsHIs