Animate single view in recyclerview after button click - android

I've got a button and a recycler view. The button refreshes the list. I want to animate one of the text views in my recycler view when it gets updated. Not the whole recyclerview, not the whole row - just one view (in every row).
I tried putting the animation in onBindViewHolder. But this starts the animation on scrolling and when i add a list entry:
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
Animation animation = AnimationUtils.loadAnimation(context, R.anim.rv_animation_clockwise);
((ViewHolderItem)holder).tv.startAnimation(animation);
Then i tried adding a TextChangedListener to my text view. But this has the same effect as putting it straight into onBindViewHolder:
((ViewHolderItem)holder).tv.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {
My last attempt was using findViewHolderForAdapterPosition. But it just doesn't do anything.
This is the refresh method which my button calls. It's in the RecyclerViewAdapter.
recyclerview is an instance variable which i set in onAttachedToRecyclerView:
RecyclerView recyclerView;
#Override
public void onAttachedToRecyclerView(#NonNull RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
this.recyclerView = recyclerView;
}
void refresh (List<Entry> al){
this.al = al;
notifyDataSetChanged();
((ViewHolderItem)recyclerView.findViewHolderForAdapterPosition(0)).tv.startAnimation(animation);
bump

You should implement your own ItemAnimator and set it to your RecyclerView. There is some useful information here: https://hackmd.io/#nesquena/r1IEQ-jAl?type=view

Thanks, i'll check out ItemAnimator later.
What i ended up doing yesterday was to add in a small delay between my adapter.refresh() and the animation. Like they suggested here. Weirdly this delay seems to be necessary even if notifyDataSetChanged(); is called after the animation. I don't think it's a good solution but it works for now.
final Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.rv_animation_clockwise);
recyclerView.postDelayed(new Runnable()
{
#Override
public void run()
{
for (int i = 0; i < al.size(); i++) {
if (recyclerView.findViewHolderForAdapterPosition(i)!=null) {
((RecyclerViewAdapter.ViewHolderItem) recyclerView.findViewHolderForAdapterPosition(i)).tv.startAnimation(animation);
}
}
}
},50);

Related

RecyclerView ItemTouchHelper doesn't remove item

I'm trying to implement swipe to archive note in RecyclerView.
It was working fine but after I added these codes to refresh the RecyclerView from onResume(), Swiping although does archive the Note, but the item doesn't get removed and stays at a state you can see in image below:
This is what I do in onResume() :
#Override
protected void onResume() {
super.onResume();
notes = noteDAO.getAllNotes();
noteAdapter = new NoteAdapter(notes,this);
recyclerView.setAdapter(noteAdapter);
}
ItemTouchHelper onSwiped():
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getAdapterPosition();
noteAdapter.deleteItem(position,rv);
}
deleteItem method in Adapter:
public void deleteItem(int position, RecyclerView rv) {
noteDAO = DBInjector.provideNoteDao(context);
recentlyDeletedNote = notes.get(position);
recentlyDeletedNotePosition = position;
recentlyDeletedNote.setArchive(true);
notes.remove(position);
noteDAO.archiveNote(recentlyDeletedNote);
notifyItemRemoved(position);
}
I have tried a lot of solutions, the only reason why it is not updating the view is that on updating recycler views, views are getting updated especially when ItemTouchHelper is used. As I didn't have much choice I used
recreate()
function for refreshing the whole activity and the error went off.
PS: This is not the ideal solution, it is just workaround fix.

Remove item from RecyclerView but View below not adjust

I have a delete button in each item of RecyclerView. It works fine but the view below RecyclerView doesn't follow up.
I try to follow Android RecyclerView addition & removal of items but it still not works
Here my code
public ViewHolder(View itemView) {
super(itemView);
btnDelete = (ImageButton)itemView.findViewById(R.id.detail_delete);
btnDelete.setOnClickListener(this);
}
#Override
public void onClick(View v) {
removeAt(getAdapterPosition());
}
private void removeAt(int position) {
scheduleList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, scheduleList.size());
}
I think the problem lies here...
notifyItemRangeChanged(position, scheduleList.size());
you're technically lying to the RecyclerView and the adapter by saying you've removed all items located after the specified position...that's what the last parameter is for...number of items to remove which is incorrect because you are passing in the size of the whole list. This what the last parameter stands for...from the javadocs...
itemCount - Number of items removed from the dataset
Basically, you will need to remove that line in the removeAt method so that you only notify the observers once...
private void removeAt(int position) {
scheduleList.remove(position);
notifyItemRemoved(position);
}
if it still doesn't work, then you might be having yet another problem somewhere else
Add the function notifyDataSetChanged(). I was facing the same problem
#Override
public void onClick(View v) {
removeAt(getAdapterPosition());
adapter.notifyDataSetChanged(); //adapter is your card adapter
}

Apply cascade animation RecyclerView Items in Android

I want to do the next animation:
When I click on an item of my RecyclerView the items before disappear with a cascade animation.
For example: I Click on my item placed at position 10, then the items from 0 to 9 have to disappear applying a cascade swipe-left animation.
How can do it?
At this moment I tried to apply like this:
ViewHolder methods:
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
swipeAnimation(position);
}
});
lstViewsHolder.add(holder.itemView);
setAnimation(holder.itemView, position);
}
private void swipeAnimation(int position){
int init = 0;
while(init < position){
lstViewsHolder.get(init).startAnimation(AnimationUtils.loadAnimation(context, R.anim.swipe_left));
init++;
}
}
The correct way of doing this is using a custom ItemAnimator. You should try to extend either SimpleItemAnimator or DefaultItemAnimator to apply your animation.
The ItemAnimators respond to data events from the adapter, so you should include logic in your adapter that calls notifyItemRemoved()or notifyItemRangeRemoved() so that the proper animation is triggered.
I think you should iterate over you're array and each time remove that item and then call notifyItemRemoved, you may want to delay each operation so that you're animation look smooth.
mResults.remove(position);
adapter.notifyItemRemoved(position);

RecyclerView scroll in incorrect direction when new element is inserted

I use smoothScrollToPosition to scroll RecyclerView. It does scroll every time a new entry is inserted; but to the top, not to the bottom, which is the direction i want.
list_chat = (RecyclerView) findViewById(R.id.list_chat);
//Set up Layout Manager
linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setStackFromEnd(true);
list_chat.setLayoutManager(linearLayoutManager);
//set adapter
list_chat.setAdapter(adapter);
//set scroll
list_chat.post(new Runnable() {
#Override
public void run() {
list_chat.smoothScrollToPosition(adapter.getItemCount());
}
});
The adapter is from Firebase
adapter = new FirebaseRecyclerAdapter<ChatItem, ChatRecylerViewHolder>(ChatItem.class,R.layout.chat_item
,ChatRecylerViewHolder.class,queryChat ) {
#Override
protected void populateViewHolder(ChatRecylerViewHolder viewHolder, ChatItem model, int position) {
viewHolder.tvAuthorChat.setText(model.chatAuthor);
viewHolder.tvContentChat.setText(model.chatContent);
}
};
You do notice you are using linearLayoutManager.setStackFromEnd(true); this mean you first position is at the bottom. I suggest you a better option.
RecycleView didn't work the way listView work, you can scroll it with your layout manager something like this
linearLayoutManager.scrollToPositionWithOffset(position,offset);
Which position is the position you want to scroll to, offset is the offset within the current position. You could just use with one parameter as well.
linearLayoutManager.scrollToPosition(position);
Ok. I found the answer.
First, the old problem with my question: i thought list_chat.post is called whenever an item is inserted (turn out that is wrong). The reason for it keeps scrolling top is linearLayoutManager.setStackFromEnd(true);
Thus, the question comes down to Where to call the scrolling ?
The answer is : Since adapter manages data, it makes sense to guess that adapter will notify the insertion.
Here is the code
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
#Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
list_chat.smoothScrollToPosition(adapter.getItemCount());
}
});

Recycler view adapter animation

After searching on SO, I have this piece of code to animate the appear animation of items in RecyclerView
#Override
public void onBindViewHolder(CourseViewHolder courseViewHolder, final int i) {
courseViewHolder.courseDate.setText(courseList.get(i).year);
courseViewHolder.courseName.setText(courseList.get(i).name);
setAnimation(courseViewHolder.view, i);
courseViewHolder.view.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
mListener.onClick(view, i);
}
});
}
private void setAnimation(View viewToAnimate, int position) {
// If the bound view wasn't previously displayed on screen, it's animated
if (position > lastPosition) {
Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
It kinda works, however the animation of all the items start at the same time. Is this possible to slide the items one by one? I thought about having a Handler to pass the delay after animating an item, but it does not work and I don't know where to put it (the onBindViewHolder still manages to show all the items at once).
Another question, where could I put the code to animate the disappear animation of all items in adapter? something to run when you refresh the RecyclerView in the OnRefreshListener of the SwipeRefreshLayout in your activity.

Categories

Resources