What is attribute animation?
Property animation can be implemented by directly changing the properties of View. For example:
- The effect of moving the View is achieved by constantly changing the coordinates of the View.
- By constantly changing the background of View to achieve the effect of background gradient of View;
- The effect of deforming the View is achieved by constantly changing the width of the View.
- ...
Thus, using attribute animation can handle almost any animation effect involving View.
actual combat
Specific details are not much to say, the corresponding online tutorials are also many. This blog is mainly to achieve the effect similar to the American Troupe take-out shopping cart.
Analysis
Firstly, the details of cart animation are analyzed: during the sliding process, the cart moves to the right until half of the cart hides to the right; while the finger stays in the screen, the cart hides to the right; when the finger leaves the screen, the cart moves back after a certain time.
The above animation details are closely related to the rolling events of RecycleView, so animation should be implemented in the rolling events of RecycleView.
Realizing Basic Layout
The blue image above is both the View we are dealing with.
Add scrolling events to RecycleView
Next, add a scroll event to RecycleView, and the image disappears when it slides or flies, and displays when it stops sliding.
1 // to rv Add scrolling events 2 rv.addOnScrollListener(new RecyclerView.OnScrollListener() { 3 @Override 4 public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { 5 switch (newState) { 6 case RecyclerView.SCROLL_STATE_DRAGGING:// Rolling 7 case RecyclerView.SCROLL_STATE_SETTLING:// Flying 8 iv.setVisibility(View.GONE); 9 break; 10 case RecyclerView.SCROLL_STATE_IDLE:// Stop scrolling 11 iv.setVisibility(View.VISIBLE); 12 break; 13 } 14 } 15 });
Design sketch:
Animation of disappearance
According to the above figure, we can see that the trigger time is basically no problem, the next thing to do is to make the disappearance not abrupt, plus the disappearance of the animation.
The essence of the disappearance is that the x coordinates of the View go from the current position to the right until they are half hidden. Let's achieve this effect:
1 // Basic properties of vanishing animation (from iv Current x The coordinates go up to the right half of the screen. 2 disappearAnimator = ValueAnimator.ofFloat(iv.getX(), (float) (Utils.getScreenWidth(this) - iv.getWidth() / 2.0)); 3 disappearAnimator.setDuration(400);// Animation duration 4 disappearAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 5 @Override 6 public void onAnimationUpdate(ValueAnimator animation) {// Value Update events 7 float curValue = (float) animation.getAnimatedValue(); 8 iv.setX(curValue); 9 } 10 }); 11 12 // to rv Add scrolling events 13 rv.addOnScrollListener(new RecyclerView.OnScrollListener() { 14 @Override 15 public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { 16 switch (newState) { 17 case RecyclerView.SCROLL_STATE_DRAGGING:// Rolling 18 case RecyclerView.SCROLL_STATE_SETTLING:// Flying 19 disappearAnimator.start(); 20 break; 21 case RecyclerView.SCROLL_STATE_IDLE:// Stop scrolling 22 iv.setVisibility(View.VISIBLE); 23 break; 24 } 25 } 26 });
However, it is found that in fact the animation is like this:
It was found that he moved from the far left to the far right, which was not in line with our needs.
After debugging, it was found that iv had not been initialized at onCreate, so the width and height as well as coordinates could not be obtained. So the coordinates and width obtained are all 0.
So you can get the coordinates and width of iv in the scrolling event. The changed code is as follows:
1 // to rv Add scrolling events 2 rv.addOnScrollListener(new RecyclerView.OnScrollListener() { 3 @Override 4 public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { 5 // Obtain iv Coordinates and width and height 6 if (0 == originX) { 7 originX = iv.getX(); 8 ivWidth = iv.getWidth(); 9 } 10 11 switch (newState) { 12 case RecyclerView.SCROLL_STATE_DRAGGING:// Rolling 13 case RecyclerView.SCROLL_STATE_SETTLING:// Flying 14 // Basic properties of vanishing animation (from iv Current x The coordinates go up to the right half of the screen. 15 if (disappearAnimator == null) { 16 disappearAnimator = ValueAnimator.ofFloat(originX, (float) (screenWidth - ivWidth / 2.0)); 17 disappearAnimator.setDuration(400);// Animation duration 18 disappearAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 19 @Override 20 public void onAnimationUpdate(ValueAnimator animation) {// Value Update events 21 float curValue = (float) animation.getAnimatedValue(); 22 iv.setX(curValue); 23 } 24 }); 25 } 26 27 disappearAnimator.start(); 28 break; 29 case RecyclerView.SCROLL_STATE_IDLE:// Stop scrolling 30 iv.setVisibility(View.VISIBLE); 31 break; 32 } 33 } 34 });
The effect is as follows:
Realize the animation that appears
Now that the disappeared animation has been realized, the animation that appears is not difficult. The essence of this is that the x coordinates of the View move from the right half to the original position.
1 case RecyclerView.SCROLL_STATE_IDLE:// Stop scrolling 2 // Basic attributes of animation (from the right half of the screen to the original position) 3 if (appearAnimator == null) { 4 appearAnimator = ValueAnimator.ofFloat((float) (screenWidth - ivWidth / 2.0), originX); 5 appearAnimator.setDuration(400);// Animation duration 6 appearAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 7 @Override 8 public void onAnimationUpdate(ValueAnimator animation) {// Value Update events 9 float curValue = (float) animation.getAnimatedValue(); 10 iv.setX(curValue); 11 } 12 }); 13 } 14 15 appearAnimator.start(); 16 break;
The results are as follows:
However, it was found that the animation would conflict if frequent sliding pauses occurred, so some judgments need to be made. If the animation is running, the animation will not be restarted. The modified code is as follows:
1 switch (newState) { 2 case RecyclerView.SCROLL_STATE_DRAGGING:// Rolling 3 case RecyclerView.SCROLL_STATE_SETTLING:// Flying 4 // Basic properties of vanishing animation (from iv Current x The coordinates go up to the right half of the screen. 5 if (disappearAnimator == null) { 6 disappearAnimator = ValueAnimator.ofFloat(originX, (float) (screenWidth - ivWidth / 2.0)); 7 disappearAnimator.setDuration(400);// Animation duration 8 disappearAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 9 @Override 10 public void onAnimationUpdate(ValueAnimator animation) {// Value Update events 11 float curValue = (float) animation.getAnimatedValue(); 12 iv.setX(curValue); 13 } 14 }); 15 } 16 17 // If the vanishing animation has not yet started to execute and iv If the location is in the original position, the execution will occur. 18 if (!disappearAnimator.isStarted() && originX == iv.getX()) { 19 disappearAnimator.start(); 20 } 21 break; 22 case RecyclerView.SCROLL_STATE_IDLE:// Stop scrolling 23 // Basic attributes of animation (from the right half of the screen to the original position) 24 if (appearAnimator == null) { 25 appearAnimator = ValueAnimator.ofFloat((float) (screenWidth - ivWidth / 2.0), originX); 26 appearAnimator.setDuration(400);// Animation duration 27 appearAnimator.setStartDelay(700);// delay time 28 appearAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 29 @Override 30 public void onAnimationUpdate(ValueAnimator animation) {// Value Update events 31 float curValue = (float) animation.getAnimatedValue(); 32 iv.setX(curValue); 33 } 34 }); 35 } 36 37 // If there is an animation that has not yet started execution, it will be executed 38 if (!appearAnimator.isStarted()) { 39 appearAnimator.start(); 40 } 41 break; 42 }
But there will still be conflicts. After detection, it is found that animation and vanishing animation interfere with each other. When the sliding has been suspended but the animation has not been completed, the sliding again triggers the vanishing animation.
Therefore, it is necessary to give an animation with a delay and cancel the animation if it is in a non-pause state. (Maybe the reason why the American Delivery Takeaway pause began to appear after a period of time is to prevent users from constantly sliding pause.)
The modified code is as follows:
case RecyclerView.SCROLL_STATE_DRAGGING:// Rolling case RecyclerView.SCROLL_STATE_SETTLING:// Flying // Basic properties of vanishing animation (from iv Current x The coordinates go up to the right half of the screen. if (disappearAnimator == null) { disappearAnimator = ValueAnimator.ofFloat(originX, (float) (screenWidth - ivWidth / 2.0)); disappearAnimator.setDuration(400);// Animation duration disappearAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) {// Value Update events float curValue = (float) animation.getAnimatedValue(); iv.setX(curValue); } }); } // If the animation has started at this time, cancel if (appearAnimator != null && appearAnimator.isStarted()) { appearAnimator.cancel(); } // If the vanishing animation has not yet started to execute and iv If the location is in the original position, the execution will occur. if (!disappearAnimator.isStarted() && originX == iv.getX()) { disappearAnimator.start(); } break;
The final effect is shown as follows:
summary
- If we want to achieve other effects, such as fading in and fading out, the same can be achieved.
- When multiple animations change the same View, we must pay attention to the conflict between animations.
- Attribute animation + function equation can achieve some rich and changeable effects, which need to be studied.
- The implementation of this article is still relatively simple, the best effect is that animation can be interrupted, because it is more troublesome, so it has not been achieved.
Github address: Initial battle of attribute animation
If you have any questions or suggestions, you can comment or mail The way to contact me, welcome your comments~