Demo series of custom View (4) and windmill demo
Version 4.0 has a problem. When the finger is lifted, the windmill stops. Now, the problem is solved. When the finger is lifted, the windmill continues to rotate for a period of time due to inertia. The idea is as follows:
1) It is difficult to get the instantaneous speed of the wind car when the finger is lifted. In my demo, I simply calculated the difference between the time when the finger is pressed and The radian, the radians are divided by time to simulate the speed.
It is really difficult to describe it in a language, so I am a little lazy. I directly add the speed variable to the speed controller, and calculate the speed based on the radians and elapsed time.
Package rotation. demo. bean; import android. util. log;/***** the instantaneous speed at which the wind car rotates when the finger is lifted when the finger is replenished: here, we simulate the radians from the fingers to the lifted point minus the radians from the pressed point, divided by the elapsed time * @ author YanQiu **/public class SpeedControl {/** radians when the finger is pressed **/private float down_rad; /** radian of the current coordinate when moving the finger **/private float current_move_rad;/** radian increment. Its value is equal to current_move_rad-down_rad **/private float △rad; /** image center origin **/private float x0, y0;/** speed when the finger is lifted **/private float speed; public SpeedControl (float x0, float y0) {this. x0 = x0; this. y0 = y0 ;} /** // *** determine whether it is clockwise * @ param current_move_x finger * @ param current_move_y * @ param up_x * @ param up_y * @ return * // * public boolean isClockWise (float current_move_x, float current_move_y, float up_x, float up_y) {return false;} * // ***** calculates the radians represented by the angle between the current coordinate point and the X axis, the radian formula is 1rad = 180/Math. PI, <br> * Note that the Cartesian coordinate system is divided into four quadrants, when calculating the coordinate between the coordinate point of each quadrant and the X axis, You need to calculate ** @ param current_x * The coordinate point of the current coordinate point * @ param current_y * The ordinate point of the current coordinate point * @ return */public float computeRad (float current_x, float current_y) {final float △x = current_x-x0; final float △y = current_y-y0; double θ = 0f; // angle // returns the absolute value float tan θ = Math. abs (△y/△x); if (△x> 0) {// when the coordinate point is in the 1 or 4 quadrant, if (△y> = 0) {// coordinate point in the first quadrant θ = Math. atan (tan θ);} else {// when the coordinate point is in the fourth quadrant θ = 2 * Math. PI-Math. atan (tan θ) ;}} else {// when the coordinate point is in the 2 or 3 Quadrant if (△y> = 0) {// located in the second quadrant θ = Math. PI-Math. atan (tan θ);} else {// located in the third quadrant θ = Math. PI + Math. atan (tan θ) ;}} float result = (float) (180 * θ)/Math. PI); return result;} public float getDown_rad () {return down_rad;} public void setDown_rad (float down_rad) {this. down_rad = down_rad;} public float getCurrent_move_rad () {return current_move_rad;} public void setCurrent_move_rad (float current_move_rad) {this. current_move_rad = current_move_rad;} public float get Delta rad () {return Delta rad;} public void set Delta rad (float Delta rad) {Delta rad = delta rad ;} public float getSpeed () {return speed;} public void setSpeed (float Delta rad, long duration) {Delta rad = 1000 * Math. abs (delta rad); Log. e ("", "delta rad =" + Delta rad + "--- duration =" + duration + "speed =" + Math. abs (delta rad/duration); this. speed = Math. abs (delta rad/duration );}}
The RotationView code is modified as follows. The action_up event and the post Ruannable method are modified as follows:
Package rotation. demo. view; import rotation. demo. bean. speedControl; import android. content. context; import android. graphics. bitmap; import android. graphics. canvas; import android. graphics. matrix; import android. graphics. paint; import android. util. attributeSet; import android. util. log; import android. view. motionEvent; import android. view. view;/*** the first two versions of verson3.0 stop rotating immediately when the finger leaves the screen. The current version allows the windmill to continue turning when the finger is lifted. Take a moment. * Idea: Listen to the finger lifting event and re-draw ** @ author YanQiu **/public class RotationView extends View {/** image to be rotated **/private Bitmap bitMap; /** The radian of a windmill **/private int degree = 0;/** width of the image: The square image is provided here, so the width and height are the same **/private int width = 0;/*** Image Height: here we provide a square image, so the width and height are the same **/private int height = 0;/** define a Paint brush **/private paint = new Paint (); /** time when the finger is lifted **/private long upTime = 0;/** time when the finger is lifted */private final long stopTimeDuration = 5000; private SpeedControl speedControl; public RotationView (Context context, AttributeSet attrs) {super (context, attrs);} public RotationView (Context context, AttributeSet attrs, int defStyleAttr) {super (context, attrs, defStyleAttr);} public RotationView (Context context) {super (context);} private String tag = ""; /*** calculate the center of the image */public void initSize () {width = bitMap. getWidth (); height = bitMap. getHeight (); speedControl = new SpeedControl (width/2, height/2); postInvalidate ();} public void setBitMap (Bitmap bitMap) {this. bitMap = bitMap;} @ Overrideprotected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stubsuper. onMeasure (widthMeasureSpec, heightMeasureSpec); setMeasuredDimension (width, width) ;}@ Overrideprotected void onDraw (Canvas canvas) {Matrix matrix Matrix = new matrix (); // set the Axis Position Matrix. setTranslate (float) width/2, (float) height/2); matrix. preRotate (speedControl. get △rad (); // restores matrix from a pivot. preTranslate (-(float) width/2,-(float) height/2); canvas. drawBitmap (bitMap, matrix, paint); super. onDraw (canvas);}/** time when the finger slides **/private long current_move_time; @ Overridepublic boolean onTouchEvent (MotionEvent event) {int action = event. getAction (); switch (action) {case MotionEvent. ACTION_DOWN: final float down_rad = speedControl. computeRad (event. getX (), event. getY (); speedControl. setDown_rad (down_rad); current_move_time = System. currentTimeMillis (); break; case MotionEvent. ACTION_MOVE: // re-paint final float current_move_rad = speedControl as your fingers move. computeRad (event. getX (), event. getY (); final float △rad = current_move_rad-speedControl. getDown_rad (); speedControl. set △rad (△rad); // This method uses postInvalidate (); break; case MotionEvent In the UI thread itself. ACTION_UP: // re-paint final float up_rad = speedControl as your fingers move. computeRad (event. getX (), event. getY (); // The radian difference between finger lifting and pressing final float Delta rad = up_rad-speedControl. getDown_rad (); upTime = System. currentTimeMillis (); final long duration = upTime-current_move_time; // sets the speedControl when the finger leaves. setSpeed (delta rad, duration); post (new Runnable () {@ Overridepublic void run () {long stopDuration = System. currentTimeMillis ()-upTime; // long // speedControl. setSpeed (duration); if (stopDuration = stopTimeDuration) {return;} else if (stopDuration <stopTimeDuration) {post (this) ;}// calculates the radian speedControl. set △rad (speedControl. getSpeed () * 1000/stopDuration); invalidate () ;}}); break ;}// true must be returned here; otherwise, the event will not be executed, for details, see blog return true ;}}
So far, the demo was completed after a long time, but there is another problem: After this modification, I don't know how to determine whether the finger is clockwise or clockwise, I have checked some information and cannot solve the problem. I hope I can leave some suggestions or ideas for me. in addition, the radians of inertial rotation calculation are not very good. They are just a simple simulation, and the effect of the gradual stop of windmills is not very satisfactory.