版本4.0有个问题当手指抬起的时候风车停止了,现在就解决这个问题,手指抬起的时候继续让风车由于惯性而继续旋转一段时间。思路如下
1)需要获取手指抬起时风车转动的瞬间速度,这个难度不小,在我的demo里面我只是简单的计算了手指按下到抬起经过的时间和弧度差,用弧度差除以时间来模拟下速度。
具体的还真不好用语言描述,所以偷个懒,直接上代码吧速度控制器添加了speed变量,并根据弧度差和经过的时间来计算速度
package rotation.demo.bean; import android.util.Log; /*** * 当手指移动的时候,补货手指抬起时风车转动的瞬间的速度:在这里暂且模拟为手指按下到抬起时的弧度减去按下时的弧度,除以经过的时间 * @author YanQiu * */ public class SpeedControl { /** 手指按下时候的弧度 **/ private float down_rad; /** 手指move时当前坐标的弧度 **/ private float current_move_rad; /** 弧度增量,它的值等于current_move_rad - down_rad**/ private float Δrad; /** 图片的中心原点 **/ private float x0, y0; /**手指抬起时的速度**/ private float speed; public SpeedControl(float x0, float y0) { this.x0 = x0; this.y0 = y0; } /* *//** * 判断是否是顺时针 * @param current_move_x 手指 * @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; } */ /*** * 计算当前坐标点与x轴的夹角所代表的弧度,弧度计算公式为 1rad = 180/Math.PI,<br> * 需要注意的是直角坐标系分四个象限,每个象限的坐标点与x轴的夹角计算时需要计算一下 * * @param current_x * 当前坐标点的横坐标点 * @param current_y * 当前坐标点的纵坐标点 * @return */ public float computeRad(float current_x, float current_y) { final float Δx = current_x - x0; final float Δy = current_y - y0; double θ = 0f;// 夹角 // 求夹角的正切的绝对值 float tanθ = Math.abs(Δy / Δx); if (Δx > 0) {// 当坐标点在1或者4象限的情况 if (Δy >= 0) {// 坐标点位于第一象限 θ = Math.atan(tanθ); } else {// 当坐标点位于第四象限 θ = 2 * Math.PI - Math.atan(tanθ); } } else {// 当坐标点位于2或3象限 if (Δy >= 0) {// 位于第二象限 θ = Math.PI - Math.atan(tanθ); } else {// 位于第三象限 θ = 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Δrad() { return Δrad; } public void setΔrad(float δrad) { Δrad = δrad; } public float getSpeed() { return speed; } public void setSpeed(float δrad,long duration) { δrad = 1000*Math.abs(δrad); Log.e("", "δrad==="+δrad + "---duration=="+duration + " speed =="+Math.abs(δrad/duration)); this.speed = Math.abs(δrad/duration); } }
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; /** * verson3.0 前两个版本都是手指离开屏幕的时候就会立即停止转动,现在这个版本让当手指抬起的时候,由于惯性让风车继续转动一点时间。 * 思路:监听手指抬起事件,然后重绘 * * @author YanQiu * */ public class RotationView extends View { /** 要转动的图片 **/ private Bitmap bitMap; /** 风车每次转动的弧度 **/ private int degree = 0; /** 图片的宽度:在这里提供的是正方形的图片,所以宽度和高度是一样的 **/ private int width = 0; /*** 图片的高度:在这里提供的是正方形的图片,所以宽度和高度是一样的 **/ private int height = 0; /** 定义一个画笔 **/ private Paint paint = new Paint(); /**手指抬起的时间**/ private long upTime = 0; /**手指抬起的时候风车持续转动的时间**/ 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 = ""; /** * 计算图片的圆心 */ 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; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(width, width); } @Override protected void onDraw(Canvas canvas) { Matrix matrix = new Matrix(); // 设置转轴位置 matrix.setTranslate((float) width / 2, (float) height / 2); matrix.preRotate(speedControl.getΔrad()); // 转轴还原 matrix.preTranslate(-(float) width / 2, -(float) height / 2); canvas.drawBitmap(bitMap, matrix, paint); super.onDraw(canvas); } /**手指滑动时此时的时间**/ private long current_move_time; @Override public 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:// 随着手指的move而不断进行重绘 final float current_move_rad = speedControl.computeRad(event.getX(), event.getY()); final float Δrad = current_move_rad - speedControl.getDown_rad(); speedControl.setΔrad(Δrad); //该方法在UI线程自身中使用 postInvalidate(); break; case MotionEvent.ACTION_UP:// 随着手指的move而不断进行重绘 final float up_rad = speedControl.computeRad(event.getX(), event.getY()); //手指抬起和按下经过的弧度差 final float δrad = up_rad - speedControl.getDown_rad(); upTime = System.currentTimeMillis(); final long duration = upTime - current_move_time; //设置手指离开时的速度 speedControl.setSpeed(δrad, duration); post(new Runnable() { @Override public void run() { long stopDuration = System.currentTimeMillis()-upTime; //long //speedControl.setSpeed(duration); if(stopDuration == stopTimeDuration) { return; }else if(stopDuration<stopTimeDuration){ post(this); } //计算此时转过的弧度 speedControl.setΔrad(speedControl.getSpeed()*1000/stopDuration); invalidate(); } }); break; } //此处必须返回true,否则不会执行此处的事件,详见博客 return true; } }
原文地址:http://blog.csdn.net/chunqiuwei/article/details/45439019