关闭

android水波纹RippleEffect源码解析

标签: android水波纹
1277人阅读 评论(0) 收藏 举报
分类:

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.源码下载


点击下载

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:408928次
    • 积分:5836
    • 等级:
    • 排名:第4356名
    • 原创:190篇
    • 转载:4篇
    • 译文:0篇
    • 评论:140条
    个人开发app
    深圳通已在360,豌豆荚市场上线小白工具箱已经360上线
    博客专栏
    最新评论