您的位置:首页 > 移动开发 > Android开发

android水波纹RippleEffect源码解析

2015-07-08 14:14 260 查看

1.废话

来到公司的第一个任务,写出水波纹,仔细想想具体思路,点击一下就有水波 ,那也不能那里点击都有水波吧,那就继承一个相对布局呗,然后响应点击事件,绘画一个波纹,那就是动画了,OK,先去google,发现一个开源库 RippleView 最低兼容到2.3正好也是老大要求的兼容嘛。

效果图



github地址:https://github.com/traex/RippleEffect 作者没有做过多介绍事实是也没多少代码 github是AS构建的

2.作者思路呢:

① 继承相对布局,复写三个构造方法,实现init方法-获取属性,设置属性

属性分别是:

app:rv_alpha [integer def:90 0-255] --> Alpha of the ripple
app:rv_framerate [integer def:10] --> Frame rate of the ripple animation
app:rv_rippleDuration [integer def:400] --> Duration of the ripple animation
app:rv_ripplePadding [dimension def:0] --> Add a padding to the ripple
app:rv_color [color def:@android:color/white] --> Color of the ripple
app:rv_centered [boolean def:false] --> Center ripple in the child view
app:rv_type [enum (simpleRipple, doubleRipple) def:simpleRipple] --> Simple or double ripple
app:rv_zoom [boolean def:false] --> Enable zoom animation
app:rv_zoomDuration [integer def:150] --> Duration of zoom animation
app:rv_zoomScale [float def:1.03] --> Scale of zoom animation

源码还给了长按点击事件
② 自定义布局嘛,肯定还有OnDraw
绘画
判断动画是否开始,未开始先设置一些参数,而且判断是否到达下一次刷新的时间,到了就刷新一些,执行一次绘画,同时绘画的时候还要判断一些类型,比如type 你在xml里面设置的
super.draw(canvas);
//		判断动画是否开始
		if (animationRunning) {
//是否已经到达持续时间
			if (rippleDuration <= timer * frameRate) {
				animationRunning = false;
				timer = 0;
				durationEmpty = -1;
				timerEmpty = 0;
				canvas.restore();
				invalidate();
				if (onCompletionListener != null)
					onCompletionListener.onComplete(this);
				return;
			} else
				canvasHandler.postDelayed(runnable, frameRate);

			if (timer == 0)
				canvas.save();
//   画圆
			canvas.drawCircle(x, y, (radiusMax * (((float) timer * frameRate) / rippleDuration)), paint);
//设置颜色
			paint.setColor(Color.parseColor("#ffff4444"));
//判断是否是type1 
			if (rippleType == 1 && originBitmap != null && (((float) timer * frameRate) / rippleDuration) > 0.4f) {
				if (durationEmpty == -1)
					durationEmpty = rippleDuration - timer * frameRate;

				timerEmpty++;
				final Bitmap tmpBitmap = getCircleBitmap(
						(int) ((radiusMax) * (((float) timerEmpty * frameRate) / (durationEmpty))));
				canvas.drawBitmap(tmpBitmap, 0, 0, paint);
				tmpBitmap.recycle();
			}

			paint.setColor(rippleColor);

			if (rippleType == 1) {
				if ((((float) timer * frameRate) / rippleDuration) > 0.6f)
					paint.setAlpha((int) (rippleAlpha
							- ((rippleAlpha) * (((float) timerEmpty * frameRate) / (durationEmpty)))));
				else
					paint.setAlpha(rippleAlpha);
			} else
				paint.setAlpha((int) (rippleAlpha - ((rippleAlpha) * (((float) timer * frameRate) / rippleDuration))));

			timer++;
		}


3.大家都看到上面了,如果动画没开始是不会进行绘制的,所以要在touch时间中进行监控

@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (gestureDetector.onTouchEvent(event)) {
			animateRipple(event);
			sendClickEvent(false);
		}
		return super.onTouchEvent(event);
	}


animateRipple 开始波浪动画

private void createAnimation(final float x, final float y) {
		// 有不有开始
		if (this.isEnabled() && !animationRunning) {
			//要不要进行缩放效果同时也是在xml里面设置的
			if (hasToZoom)
				this.startAnimation(scaleAnimation);

			radiusMax = Math.max(WIDTH, HEIGHT);

			if (rippleType != 2)
				radiusMax /= 2;

			radiusMax -= ripplePadding;

			if (isCentered || rippleType == 1) {
				this.x = getMeasuredWidth() / 2;
				this.y = getMeasuredHeight() / 2;
			} else {
				this.x = x;
				this.y = y;
			}

			animationRunning = true;

			if (rippleType == 1 && originBitmap == null)
				originBitmap = getDrawingCache(true);

			invalidate();
		}
	}


4.其实还用了缓存的数据进行再次试用

private Bitmap getCircleBitmap(final int radius) {
		final Bitmap output = Bitmap.createBitmap(originBitmap.getWidth(), originBitmap.getHeight(),
				Bitmap.Config.ARGB_8888);
		final Canvas canvas = new Canvas(output);
		final Paint paint = new Paint();
		final Rect rect = new Rect((int) (x - radius), (int) (y - radius), (int) (x + radius), (int) (y + radius));

		paint.setAntiAlias(true);
		canvas.drawARGB(0, 0, 0, 0);
		canvas.drawCircle(x, y, radius, paint);

		paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
		canvas.drawBitmap(originBitmap, rect, rect, paint);

		return output;
	}




5.源码下载

点击下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: