2014-11-6Android学习------苹果切水果游戏手指滑动效果实现--------动画Animation学习篇

来源:互联网 发布:旋转轮胎怎么修改数据 编辑:程序博客网 时间:2024/05/17 22:59

写一篇文章很辛苦啊!!!

转载请注明,联系请邮件nlp30508@qq.com


我学习Android都是结合源代码去学习,这样比较直观,非常清楚的看清效果,觉得很好,今天的学习源码是网上找的源码 百度搜就知道很多下载的地方  网上源码的名字叫:水果忍者点击屏幕效果.zip  我的博客写的比较乱,如果本篇文章没有看懂,

请先看上篇文章,地址:http://blog.csdn.net/u014737138/article/details/40859913


实现的原理就是一个视图,在视图上用手指画,主要的就是坐标处理,

继承Android.view.View,构造函数,重载onDraw(),手指触摸屏幕引发的坐标变换处理

主要是上面的几个步骤。接下来一步一步 解析:

1.继承类

public class GestureView extends View {

2.主要的变量定义

private Paint paint;private float startX = Float.NaN;// 手指开始画的坐标private float startY = Float.NaN;private float endX = Float.NaN;// 手指结束的坐标private float endY = Float.NaN;// 下层view// private View viewer;private static final int gestureColor = Color.rgb(153, 153, 153);// 手指画的颜色private static final int alpha = 220;// 透明度private static final int alpha_full = 255;// 刀锋长度private static final int shape_length = 80;// 刀锋截短时间private static final int shape_cut_time = 150;

关于final关键词可以看我前面的一篇java文章,http://blog.csdn.net/u014737138/article/details/40748485

3.构造函数

public GestureView(Context context) {super(context);// TODO Auto-generated constructor stubpaint = new Paint();//画笔初始化paint.setStyle(Paint.Style.FILL);//设置画笔样式}

4.重载onDraw(Canvas canvas)

@Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.onDraw(canvas);// NaN,是Not a Number的缩写 NaN 用于处理计算中出现的错误情况,比如 0.0 除以 0.0 或者求负数的平方根if (!Float.isNaN(startX) && !Float.isNaN(endY)) {float gap = getGap(startX, startY, endX, endY);float w = gap / 10;// 背景shape外侧点高度float h = w > 7 ? 7 : w;// 填充shape外侧点高度float h2 = h * 2 / 3;double length = Math.pow(Math.pow(w, 2) + Math.pow((h), 2), 0.5);double length2 = Math.pow(Math.pow(w, 2) + Math.pow((h2), 2), 0.5);double ang1_1 = Math.atan((endY - startY) / (endX - startX));double ang1_2 = Math.atan(h / w);double angle1_1 = ang1_1 + ang1_2;double angle1_2 = ang1_1 - ang1_2;double ang2_2 = Math.atan(h2 / w);double angle2_1 = ang1_1 + ang2_2;double angle2_2 = ang1_1 - ang2_2;if (endX > startX) {float xx1 = endX - (float) (length * Math.cos(angle1_1));float yy1 = endY - (float) (length * Math.sin(angle1_1));float xx2 = endX - (float) (length * Math.cos(angle1_2));float yy2 = endY - (float) (length * Math.sin(angle1_2));float xx12 = endX - (float) (length2 * Math.cos(angle2_1));float yy12 = endY - (float) (length2 * Math.sin(angle2_1));float xx22 = endX - (float) (length2 * Math.cos(angle2_2));float yy22 = endY - (float) (length2 * Math.sin(angle2_2));Path backPath = new Path();backPath.moveTo(startX, startY);backPath.lineTo(xx1, yy1);backPath.lineTo(endX, endY);backPath.lineTo(xx2, yy2);backPath.close();Path fillPath = new Path();fillPath.moveTo(startX, startY);fillPath.lineTo(xx12, yy12);fillPath.lineTo(endX, endY);fillPath.lineTo(xx22, yy22);fillPath.close();paint.setColor(Color.RED);paint.setAlpha(alpha);canvas.drawPath(backPath, paint);paint.setColor(Color.RED);paint.setAlpha(alpha_full);canvas.drawPath(fillPath, paint);} else {float xx1 = endX + (float) (length * Math.cos(angle1_1));float yy1 = endY + (float) (length * Math.sin(angle1_1));float xx2 = endX + (float) (length * Math.cos(angle1_2));float yy2 = endY + (float) (length * Math.sin(angle1_2));float xx12 = endX + (float) (length2 * Math.cos(angle2_1));float yy12 = endY + (float) (length2 * Math.sin(angle2_1));float xx22 = endX + (float) (length2 * Math.cos(angle2_2));float yy22 = endY + (float) (length2 * Math.sin(angle2_2));Path backPath = new Path();backPath.moveTo(startX, startY);backPath.lineTo(xx1, yy1);backPath.lineTo(endX, endY);backPath.lineTo(xx2, yy2);backPath.close();Path fillPath = new Path();fillPath.moveTo(startX, startY);fillPath.lineTo(xx12, yy12);fillPath.lineTo(endX, endY);fillPath.lineTo(xx22, yy22);fillPath.close();paint.setColor(Color.WHITE);paint.setAlpha(alpha);canvas.drawPath(backPath, paint);paint.setColor(Color.WHITE);paint.setAlpha(alpha_full);canvas.drawPath(fillPath, paint);}}}

看下有些数学方法的意义:

1).Java.lang.Float.isNaN()方法用法实例教程 - 此方法如果此对象所表示的值是NaN,返回true,否则返回false

什么叫做NaN? ------------not a number 

NaN 用于处理计算中出现的错误情况,比如 0.0 除以 0.0 或者求负数的平方根。由上面的表中可以看出,对于单精度浮点数,NaN 表示为指数为 emax + 1 = 128(指数域全为 1),且尾数域不等于零的浮点数。IEEE 标准没有要求具体的尾数域,所以 NaN 实际上不是一个,而是一族。

有个例子说明这个问题:

实例

下面的例子说明了如何使用java.lang.Float.isNaN()方法。

package com.yiibai;import java.lang.*;public class FloatDemo {   public static void main(String[] args) {     Float f1 = new Float(-1.0/0.0);     Float f2 = new Float(0.0/0.0);       // returns true if this Float value is a Not-a-Number(NaN), else false     System.out.println(f1 + " = " + f1.isNaN());       System.out.println(f2 + " = " + f2.isNaN());   }}   

让我们来编译和运行上面的程序,这将产生以下结果:

-Infinity = falseNaN = true
2).java.lang.Math.pow(double a, double b) 返回的第一个参数的值提高到第二个参数的幂

下面的例子说明了如何使用lang.Math.pow()方法。

package com.yiibai;import java.lang.*;public class MathDemo {   public static void main(String[] args) {      // get two double numbers      double x = 2.0;      double y = 5.4;      // print x raised by y and then y raised by x      System.out.println("Math.pow(" + x + "," + y + ")=" + Math.pow(x, y));      System.out.println("Math.pow(" + y + "," + x + ")=" + Math.pow(y, x));   }}

让我们来编译和运行上面的程序,这将产生以下结果:

Math.pow(2.0, 5.4)=42.22425314473263Math.pow(5.4, 2.0)=29.160000000000004
在这个例子中用到这样的一个方法:

public static final float getGap(float x0, float y0, float x1, float y1) {return (float) Math.pow(Math.pow((x0 - x1), 2) + Math.pow((y0 - y1), 2), 0.5);}

这个方法就是计算两个点之间的直线距离:


3)

java.lang.Math.atan(double a) 返回一个角的反正切,在到pi / 2,-π/ 2的范围内。特殊情况:

  • 如果参数是NaN,那么结果为NaN.

  • 如果参数是零,那么结果是零的同号作为参数.

因此,必须正确舍入的结果的1 ulp范围内。结果必须是半单调性.

下面的示例演示使用的lang.Math.atan()方法.

package com.yiibai;import java.lang.*;public class MathDemo {   public static void main(String[] args) {      // get a variable x which is equal to PI/2      double x = Math.PI / 2;      // convert x to radians      x = Math.toRadians(x);      // get the arc tangent of x      System.out.println("Math.atan(" + x + ")" + Math.atan(x));   }}

让我们来编译和运行上面的程序,这将产生以下结果:

Math.atan(0.027415567780803774)0.0274087022410345
本例子中有该函数的应用:

double ang1_1 = Math.atan((endY - startY) / (endX - startX));

这个函数的结果就是你手指向上滑动的方向与x轴的夹角


其他的函数就不介绍了,求cos sin 等等

这里的坐标处理就是求出  路径,以便画笔paint按照这条路径去画出你手指的移动方向

5.手指触摸事务处理

// 屏幕触摸事务处理@Overridepublic boolean onTouchEvent(android.view.MotionEvent event) {if (event.getPointerCount() == 1) {int action = event.getAction();if (MotionEvent.ACTION_DOWN == action) {startX = event.getX();startY = event.getY();} else if (MotionEvent.ACTION_MOVE == action) {endX = event.getX();endY = event.getY();// 刀锋截短时间,则截短至一半if ((event.getEventTime() - event.getDownTime()) > shape_cut_time) {if (Math.abs(endX - startX) > shape_length&& Math.abs(endY - startY) > shape_length) {startX = (float) (startX + (endX - startX) * 0.5);startY = (float) (startY + (endY - startY) * 0.5);}}invalidate();} else if (MotionEvent.ACTION_UP == action) {startX = Float.NaN;startY = Float.NaN;endX = Float.NaN;endY = Float.NaN;invalidate();}}// 该view消费了event,所以下层的view必须dispatchTouchEvent才能获得事件// MotionEvent newEvent = MotionEvent.obtain(event);// viewer.dispatchTouchEvent(newEvent);return true;}

主要是处理拖动过程中坐标的变化:通过时间来判断  

如果我手指移动的距离超过刀锋规定的长度  :80,那么就需要把刀锋的效果缩小,游戏中没有可以从左下加拖动右上角把,

也就是说你手指滑动的过程只有一定的距离可以有效的切开水果。这里设置的距离是减半


如果当你手指松开的时候,所有的坐标都失效了,让他变成一个NaN,然后更新视图

如果手指按下了,必须马上获取你手指的坐标


这里有个形状,是在你拖动的过程中如果距离跨度很大,有个箭头的形状,大部分的计算都是为了这个形状去服务。代码应该很好懂


整个技术实现很简单,就是用画笔上画布上面画,没有太多的技巧

看看运行的效果:


0 0
原创粉丝点击