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

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

转载请注明,联系请邮件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 stub
		paint = new Paint();//画笔初始化
		paint.setStyle(Paint.Style.FILL);//设置画笔样式
	}

4.重载onDraw(Canvas canvas)

	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.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 = false
NaN = 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.22425314473263
Math.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.手指触摸事务处理

	// 屏幕触摸事务处理
	@Override
	public 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,然后更新视图

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


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


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

看看运行的效果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值