Haven’t written anything for a long time, come again, you may feel very simple after reading this eastern effect, but if you finish reading, I believe you will find that there is still a simple article, maybe not as simple as it looks, the essence of this article is performance

The old rule is to start with gifs

If you look at this picture, you don’t want to continue reading, thinking that this animation is very simple, just create a loop, create a view, animate each view, each view starts moving in a random direction, and give an accelerator. If you think that way, you should finish reading this article
Analysis:

  • Start by creating a drop animation, scaling with changes in transparency
  • Zoom is accompanied by movement when it disappears
  • The water drops are always floating up and down
  • Each drop floats up and down in a variable direction
  • Each drop is moving faster and slower. (You can’t see this, so I’ll make it bigger and create another GIF.)

To the chase

  • So let’s first create the view
1. Give the view a random orientation and save it to the view tag

// Randomly set the orientation of the view animation

            view.setTag(R.string.isUp, mRandom.nextBoolean());

2, set the view position randomly (I am not completely random here, but give some values and select them randomly), use a new set to hold the selected values, exclude these values in the next selection, because it is best not to completely coincide with the drops.

/** But this is not my final method, read on first, there are eggs **/

/ * *

* Gets a random value along the x or y axis

     *

     * @return

* /

    private double getX_YRandom(List<Float> choseRandoms,List<Float> saveRandoms) {

        float random = 0;

        while (random == 0 || saveRandoms.contains(random)) {

            random = choseRandoms.get(mRandom.nextInt(choseRandoms.size()));

        }

  

        saveRandoms.add(random);

        return random;

    }



Copy the code

There’s also an animation that shows the View, but I’m not going to show that, but I can do everything

  • Next, set an initial random acceleration for the view.
Private List<Float> mSpds = array.asList (2.0f, 1.7f, 1.5f, 1.3f); /** * Set the acceleration of all child views */ private voidsetViewsSpd() {
        for (int i = 0; i < mViews.size(); i++) {
            View view = mViews.get(i);
            setSpd(view); }} /** * Set the acceleration of all child views */ private voidsetViewsSpd() {
        for (int i = 0; i < mViews.size(); i++) {
            View view = mViews.get(i);
            setSpd(view); }}Copy the code
  • The next step is to use handler to set the view’s offset, which is also critical, including handling how fast and slow the water droplets move
/** * set offset */ private voidsetOffSet() {
        for (int i = 0; i < mViews.size(); i++) {
            View view = mViews.get(i);
            float spd = (float) view.getTag(R.string.spd);
            float original = (float) view.getTag(R.string.original_y);
            floatstep = CHANGE_RANGE / BASE_OFFSET_MUL * spd; Boolean isUp = (Boolean) view.getTag(r.string.isup);float translationY;
            if (isUp) {
                translationY = view.getY() - step;
            } else{ translationY = view.getY() + step; } // Control the view to move within the specified range, if this value is reached, then change the direction of the viewif (translationY - original > CHANGE_RANGE) {
                translationY = original + CHANGE_RANGE;
                view.setTag(R.string.isUp, true);
            } else if(translationY - original < -CHANGE_RANGE) { translationY = original - CHANGE_RANGE; // Every time the view moves to the bottom, change the acceleration of the view as it moves up againsetSpd(view);
                view.setTag(R.string.isUp, false); } view.setY(translationY); }}Copy the code
  • The next drop click after the disappearance of animation, also do not say, can be

This is the end of the animation, but my work is not done. When I open the profiler and look at OMG, I can see that the memory in the initializing view is skyrocketing

Private double getX_YRandom(List

choseRandoms, List

saveRandoms) = private double getX_YRandom(List

choseRandoms, List

saveRandoms) And create a random position for the view within the loop, but in order not to overlap exactly, I’m going to loop again until it’s a different value, so I’m going to loop twice



  • After the optimization selects a random value, it removes the value from the set, so that it will not get the same value, and it is really finished. After the optimization, there is no lag at all in the measured 200.Readers can optimize the location logic algorithm of water droplets according to their own needs, because our product explicitly states that the maximum number of drops is 6, so my current calculation logic of the drop position is enough, so LET’s make a GIF instead
In order to make the effect easier to see, I set the view range and acceleration gradient to be larger
Private static final int CHANGE_RANGE = 50; private static final int CHANGE_RANGE = 50; // private static final int CHANGE_RANGE = 10; Private List<Float> mSpds = array.asList (2.0f, 1.7f, 1.5f, 1.3f,2.3f); // private List<Float> mSpds = Arrays. AsList (2.0f, 1.7f, 1.5f, 1.3f); / / normalCopy the code

Making connections: WaterView

Like a like, your like is my motivation

Android Profiler explains how to use it