自定义View之大风车系列demo(四)

版本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);}}RotationView代码修改如下,主要修改了action_up事件和post的Ruannable方法:

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;}@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 = 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;@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:// 随着手指的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() {@Overridepublic 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;}}到此为止,捣鼓了半天的小demo终于完成了,不过还有个问题:经过这一修改,不知道怎么判断手指是否是逆时针还是顺时针转动了,查了好些资料好些解决不了问题,希望有好的建议或者思路的给留个言

赶快上路吧,不要有一天我们在对方的葬礼上说,要是当时去了就好了。

自定义View之大风车系列demo(四)

相关文章:

你感兴趣的文章:

标签云: