Reputation: 111
I'm trying to implement a ToDo list that contains a list and some other views below it on the activity page.
I am using a LinearLayout
for the entire page and a RecyclerView
for the list, alongside other views below the RecyclerView
(ImageView
, Buttons
...etc.)
Here's my final view hierarchy:
<LinearLayout>
<TextView />
<RecyclerView />
<Button />
<EditText />
<ImageView />
</LinearLayout>
I have implemented the RecyclerView
where I can add and remove items.
I am using a LinearLayoutManager
without specifying an ItemAnimator
so DefaultItemAnimator
is used.
Adding items to the list works as expected. My problem is that the page doesn't animate well when I remove an item from the RecyclerView
(by removing it from the dataset first then using RecyclerViewAdapter.notifyItemRemoved
).
What happens is that the entire page snaps first to adapt to the new RecyclerView
height, and then the RecyclerView
item remove animation completes, which makes the behavior of the page look weird since all the views below the RecyclerView
snap up while the deleted item fades out but hasn't lost its height yet, then the remaining RecyclerView
items (below the deleted item) scroll up, looking like they're sliding up from under a wall.
I tried to look for solutions on the web and couldn't find anything to solve my problem.
I have found this unanswered question describing the same problem. Please refer to it in case my explanation wasn't clear enough.
Anyone encountering the same issue? Any suggestions?
Thanks.
Upvotes: 8
Views: 3407
Reputation: 1403
You need to set the height of your recyclerview or the containers that hold it to: "match_parent". Worked like a cahrm for me.
Upvotes: 0
Reputation: 21
Create subclass of RecyclerView
and override onTouchEvent
method like this:
@Override
public boolean onTouchEvent(MotionEvent e) {
if (findChildViewUnder(e.getX(), e.getY()) == null) {
return false;
}
return super.onTouchEvent(e);
}
Also, don't use wrap_content
as RecyclerView
height/width depending on your orientation.
This way RecyclerView
has fixed size and does not cut off items while removing them. Manipulation of onTouchEvent
method assures that part of RecyclerView
without items does not consumes click events and sends them to parent view of RecyclerView
.
Upvotes: 1
Reputation: 1103
I had the same problem. In my situation just this line helped:
recyclerView.setHasFixedSize(true);
Upvotes: 3
Reputation: 2576
Try this one and check if it is working as your expectation:
recyclerView.setHasFixedSize(true);
recyclerView.setItemAnimator(new MyAnim());
public static class MyAnim extends RecyclerView.ItemAnimator {
@Override
public boolean animateDisappearance(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull ItemHolderInfo preLayoutInfo, @Nullable ItemHolderInfo postLayoutInfo) {
return false;
}
@Override
public boolean animateAppearance(@NonNull RecyclerView.ViewHolder viewHolder, @Nullable ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
return false;
}
@Override
public boolean animatePersistence(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
return false;
}
@Override
public boolean animateChange(@NonNull RecyclerView.ViewHolder oldHolder, @NonNull RecyclerView.ViewHolder newHolder, @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
final float prevAlpha = ViewCompat.getAlpha(oldHolder.itemView);
ViewCompat.setAlpha(oldHolder.itemView, prevAlpha);
ViewCompat.setAlpha(newHolder.itemView, 0);
return true;
}
@Override
public void runPendingAnimations() {
}
@Override
public void endAnimation(RecyclerView.ViewHolder item) {
}
@Override
public void endAnimations() {
}
@Override
public boolean isRunning() {
return false;
}
}
Upvotes: 1