This is the second article about Recyclerview, how to customize the item animation, but note that this article does not contain the specific animation implementation methods, just tell you how to customize the animation, how to refer to the source code.
We know that Recyclerview uses Defaultitemanimator by default, so if we need to customize the animation, we should read the source code of this class, not only to learn how to customize, but also to learn the design mode of Android.
To understand one thing first, Defaultitemanimator inherits from Simpleitemanimator, Simpleitemanimator inherits from Recyclerview.itemanimator, so if you need to customize the animation, the easiest way is to inherit simpleitemanimator. Second, there are four types of animations, respectively, add, remove, move, and change, and here we only list Remove, extrapolate.
We first look at the source code in the Simpleitemanimator, there are several important methods in Simpleitemanimator:
@Override public boolean animatedisappearance (@NonNull viewholder viewholder, @NonNull itemholderinfo prelayoutinfo,
@Nullable itemholderinfo postlayoutinfo) {int oldleft = Prelayoutinfo.left;
int oldtop = Prelayoutinfo.top;
View Disappearingitemview = Viewholder.itemview; int newleft = Postlayoutinfo = null?
Disappearingitemview.getleft (): Postlayoutinfo.left; int newtop = Postlayoutinfo = null?
Disappearingitemview.gettop (): postlayoutinfo.top; if (!viewholder.isremoved () && (oldleft!= newleft | | oldtop!=)) {Newtop (disappearingitemview.layout,
Newtop, Newleft + disappearingitemview.getwidth (), Newtop + disappearingitemview.getheight ());
if (DEBUG) {log.d (TAG, "disappearing:" + Viewholder + "with view" + Disappearingitemview);
Return Animatemove (Viewholder, OldLeft, OldTop, Newleft, newtop);
else {if (DEBUG) {log.d (TAG, "removed:" + Viewholder + "with view" + Disappearingitemview); } return Animateremove (Viewholder); }
}
parsing: This function overrides Recyclerview.itemanimator, and the parameters in the interface are Viewholder, Prelayoutinfo, and Postlayoutinfo, respectively. The first parameter refers to the Viewholder of the item, which can be used to obtain its view through the object's Itemview, the second parameter refers to the position information before the item is deleted, and the third refers to the new position information. The next step is to determine if Viewholder has been removed and whether the position has changed, and then call the Animateremove abstract method, and if we want to customize the animation, we need to implement it (callback thought).
Public final void Dispatchremovestarting (Viewholder item) {
onremovestarting (item);
}
public void onremovestarting (Viewholder item) {
}
parsing:dispatchremovestaring is a final method that cannot be rewritten, and if we need to deal with some of the logic at the start of the remove, we need to call this method in the Animateremove method, This method executes a onremovestaring method that allows us to rewrite, so the logic should be written in onremovestaring, and when we call Dispatchremovestaring, Onremovestaring will be executed.
There are only two of them here, but the other moves are not just two ...
So, when we inherit the simpleitemanimator, we need to implement some of the methods inside, generally as follows:
①animateremove (ADD, Move and change): These methods will be recalled at the time of the animation, typically using the list to record the animation of each item and the properties
②endanimation, Endanimations: Callback
③isrunning When an item or multiple item needs to be stopped immediately: if you need to slide smoothly, you must override this method, A lot of times, like when the Web is loaded, it's the wrong way to do this.
④run ' pendinganimations: This is the most important method. Because methods such as animatedisappearence return values that are returned by methods such as Animateremove, the method is based on these values to determine whether a prepared animation needs to be played, and if so, the method is recalled. In this method we need to handle the animation of each action (Remove, ADD, move, and change)
So, our general step is:
① to create a simpleitemanimator subclass
② Create a list of actions for each action
③ rewrite methods such as Animateremove, when there is an action in the interface, these functions are called back, and this records and returns true so that run ' pendinganimations starts executing
④ rewrite run ' pendinganimations, when the ③ method returns True, it thinks that animation needs to be performed, and we need to write the logic of the animation in here.
⑤ rewrite isrunning to provide an animated playback state, typically to return whether the action list is empty
⑥, if necessary, rewrite endanimation, Endanimations, Onremovefinish, and other methods
specific steps have, but we still do not know how to build it, do not worry, in order to facilitate us, Google has actually provided the defaultitemanimator, we can refer to some of its source code, no one said than the source code is reasonable, What we need is to have enough patience!
Defaultitemanimator defines some ArrayList to hold the action information, as follows:
Private arraylist<viewholder> mpendingremovals = new arraylist<> ();
Private arraylist<viewholder> mremoveanimations = new arraylist<> ();
@Override Public
Boolean animateremove (final Viewholder holder) {
resetanimation (holder);
Mpendingremovals.add (holder);
return true;
}
parsing: You can see that the Animatorremove method directly adds Viewholder to the list, and then returns True
@Override public
void Runpendinganimations () {
Boolean removalspending =!mpendingremovals.isempty ();
Boolean movespending =!mpendingmoves.isempty ();
Boolean changespending =!mpendingchanges.isempty ();
Boolean additionspending =!mpendingadditions.isempty ();
if (!removalspending &&!movespending &&!additionspending &&!changespending) {
//Nothing to animate return
;
A, remove stuff for
(Viewholder holder:mpendingremovals) {
animateremoveimpl (holder);
}
Mpendingremovals.clear ();
Next, move stuff ...
Next, change stuff, to run in parallel with move animations ...
Next, add stuff ...
}
parsing: According to the above can be known, runpendinganimations will perform, you can see, in this method traversing the list of actions, and so that each item has executed the Animatorremoveimpl method, the other action methods for the time being omitted , interested can read it by themselves.
private void Animateremoveimpl (final viewholder holder) {
final view view = Holder.itemview;
Final Viewpropertyanimatorcompat animation = viewcompat.animate (view);
Mremoveanimations.add (holder);
Animation.setduration (Getremoveduration ())
. Alpha (0). Setlistener (New Vpalisteneradapter () {
@Override Public
void Onanimationstart (view view) {
dispatchremovestarting (holder);
}
@Override public
void Onanimationend (view view) {
animation.setlistener (null);
Viewcompat.setalpha (view, 1);
dispatchremovefinished (holder);
Mremoveanimations.remove (holder);
Dispatchfinishedwhendone ();
}
}). Start ();
}
parsing: You can see the Animatorremoveimpl method to achieve the entire animation of the specific logic, specifically how to do not in the scope of this article, after we executed the animation, That is, in the animation of the listener Onanimatorend called the Dispatchremovefinish, remember this method, it will execute the Onremovefinish method, The Onremovefinish method can be supplied to us for rewriting. Then remove the item from the action list.
@Override Public
Boolean isrunning () {return
(!mpendingadditions.isempty ()) | |
! Mpendingchanges.isempty () | | |
! Mpendingmoves.isempty () | | |
! Mpendingremovals.isempty () | | |
! Mmoveanimations.isempty () | | |
! Mremoveanimations.isempty () | | |
! Maddanimations.isempty () | | |
! Mchangeanimations.isempty () | | |
! Mmoveslist.isempty () | | |
! Madditionslist.isempty () | | |
! Mchangeslist.isempty ());
}
parsing:The IsRunning method actually returns results based on whether the action list is empty
There are other functions that can read the source code for themselves.
The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.