/* * Treatment idea: * ->Customize a ViewGroup container with forest water droplets as a whole rather than a single view * ->Loop create view * ->Randomly set the position for the view (randomly select from some fixed sets to ensure that the water droplets do not coincide as much as possible) * ->Set an initial motion direction for the view (Note: since the motion direction of each view is different, I choose to bind the direction to the tag of the view) * ->Set an initial speed for the view (similarly: bind the initial speed to the tag of the view) * ->Add a view to the container and zoom the display with transparency * ->Start the handler to move the view up and down (Note: Here we need to set a critical value to change the speed of the view to reach the goal of fast and slow view) * ->Click view, zoom, transparency and displacement to remove water droplets * ->Stop calling handler when the interface is destroyed to avoid memory leakage, null pointer and other exceptions * */
###Topic
In the following explanation, I will post an important part of the code, that is, the key points of thinking. Please refer to the clone project for the complete code.
- First create the view
Create view code block:
/** * Add water drop view */ private void addWaterView(List<Water> waters) { for (int i = 0; i < waters.size(); i++) { final Water water = waters.get(i); View view = mInflater.inflate(mChildViewRes, this, false); TextView tvWater = view.findViewById(R.id.tv_water); view.setTag(water); tvWater.setText(String.valueOf(water.getNumber()) + "g"); view.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { handViewClick(view); } }); //Randomly set the direction of the view animation view.setTag(R.string.isUp, mRandom.nextBoolean()); setChildViewLocation(view); mViews.add(view); addShowViewAnimation(view); } }
explain
establish view The two most important things: 1,to view A random direction and save to view of tag in //Randomly set the direction of the view animation view.setTag(R.string.isUp, mRandom.nextBoolean()); 2,Random setting view The position of (here I don't completely random, but give some values, and then randomly select these values). Here, a new set is used to save the selected numbers. These values are excluded when selecting next time, because it's best not to completely overlap the water droplets. /**But in fact, this is not my final method. Look down first, and colored eggs**/ /** * Gets a random value on 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; }
- Animated view:
/** * Add display animation * @param view */ private void addShowViewAnimation(View view) { addView(view); view.setAlpha(0); view.setScaleX(0); view.setScaleY(0); view.animate().alpha(1).scaleX(1).scaleY(1).setDuration(ANIMATION_SHOW_VIEW_DURATION).start(); }
- Next, set an initial random acceleration for the view (in fact, it is also selected randomly from the existing values, because the speed difference cannot be too large)
/**Controls the speed of droplet animation*/ private List<Float> mSpds = Arrays.asList(0.5f, 0.3f, 0.2f, 0.1f); /** * Set the acceleration of all sub view s */ private void setViewsSpd() { for (int i = 0; i < mViews.size(); i++) { View view = mViews.get(i); setSpd(view); } } /** * Set spd of View * @param view */ private void setSpd(View view) { float spd = mSpds.get(mRandom.nextInt(mSpds.size())); //Save the random displacement velocity into the tag of view. You can Baidu the two parameters setTag() method that you don't know well view.setTag(R.string.spd, spd); }
- The next step is to start the animation and use the handler to set the offset of the view. This part is also very key, including the fast and slow processing of water droplets
/** * Set offset */ private void setOffSet() { for (int i = 0; i < mViews.size(); i++) { View view = mViews.get(i); //Get the speed of last view save float spd = (float) view.getTag(R.string.spd); //Initial position of water drop float original = (float) view.getTag(R.string.original_y); float step = spd; boolean isUp = (boolean) view.getTag(R.string.isUp); float translationY; //Move the view according to the up and down movement marks in the water drop tag if (isUp) { translationY = view.getY() - step; } else { translationY = view.getY() + step; } //Control of water drop displacement range if (translationY - original > CHANGE_RANGE) { translationY = original + CHANGE_RANGE; view.setTag(R.string.isUp, true); } else if (translationY - original < -CHANGE_RANGE) { translationY = original - CHANGE_RANGE; // Each time when the water drops return to the initial point, set the speed of the water drops again, so as to achieve the speed of sometimes fast and sometimes slow setSpd(view); view.setTag(R.string.isUp, false); } view.setY(translationY); } }
- Next, the water drop disappears after clicking
/** * Animation remove view * @param view */ private void animRemoveView(final View view) { final float x = view.getX(); final float y = view.getY(); //Calculate straight line distance float space = getDistance(new Point((int) x, (int) y), mDestroyPoint); ValueAnimator animator = ValueAnimator.ofFloat(x, 0); //Calculate animation execution time based on distance animator.setDuration((long) (REMOVE_DELAY_MILLIS / mMaxSpace * space)); animator.setInterpolator(new LinearInterpolator()); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { if (isCancelAnimtion) { return; } float value = (float) valueAnimator.getAnimatedValue(); float alpha = value / x; float translationY = y + (x - value) * (maxY - y) / x; setViewProperty(view, alpha, translationY, value); } }); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { //Remove water droplets from the container at the end removeView(view); } }); animator.start(); } /** * Set the properties of the view * @param view * @param alpha * @param translationY * @param translationX */ private void setViewProperty(View view, float alpha, float translationY, float translationX) { view.setTranslationY(translationY); view.setTranslationX(translationX); view.setAlpha(alpha); view.setScaleY(alpha); view.setScaleX(alpha); }
- Processing interface destroy
/** * Callback when interface is destroyed */ @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); onDestroy(); } /** * Destroy */ private void onDestroy() { isCancelAnimtion = true; mHandler.removeCallbacksAndMessages(this); } @SuppressLint("HandlerLeak") private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { //Identify whether to exit according to iscancelanimition to prevent changing the UI again when the interface is destroyed if (isCancelAnimtion) { return; } setOffSet(); mHandler.sendEmptyMessageDelayed(WHAT_ADD_PROGRESS, PROGRESS_DELAY_MILLIS); } };
Here, the dynamic effect is finished, and the operation can reach the desired appearance, but my work is not finished. Open the profiler and look at the OMG. The memory increases sharply at the place where the view is initialized. A little more (10) cards will be used. It seems that it is still optimized
Summary:
All walks of life will eliminate some people with poor ability, not just the IT industry. Therefore, don't be intimidated by such topics as the program ape eating youth food, and don't feel that if you find a job, you will enjoy a comfortable life. While you are comfortable, others are struggling to move forward, so the gap with others will be more and more distant. Come on, hope, Each of us, become better ourselves.
-
CodeChina open source project: Android learning notes summary + mobile architecture Video + big factory interview real questions + project actual combat source code
-
BAT large factory interview questions, exclusive interview toolkit,
-
The materials include data structure, Kotlin, computer network, Framework source code, data structure and algorithm, applet, NDK and fluent
-
CodeChina open source project: Android learning notes summary + mobile architecture Video + big factory interview real questions + project actual combat source code
-
BAT large factory interview questions, exclusive interview toolkit,
-
The materials include data structure, Kotlin, computer network, Framework source code, data structure and algorithm, applet, NDK and fluent
[external chain picture transferring... (img-n9uwWwlt-1630558783188)]