Android自定义组件系列【14】——Android5.0按钮波纹效果实现

今天任老师发表了一篇关于Android5.0中按钮按下的波纹效果实现《Android L中水波纹点击效果的实现》,出于好奇我下载了源代码看了一下效果,正好手边有一个Nexus手机,我结合实际效果看了一下,发现有一些地方和实际效果稍有不同,参考任老师的博文实现简单实现了一个重写View组件的代码,将全部代码贴出,如果有什么问题或者更好的方式请指出,在此再次感谢任老师的这篇博文。

转载请说明出处:http://blog.csdn.net/dawanganban

顺便在这里拉一下票,如果你觉得这篇文章对你有所帮助,给阳光小强投一票吧:点击投票

主要改变的地方有:

1、在手指按下的时候会有两个变化,一个是在按钮上产生一个暗色全铺背景,然后再出现一个扩散的水波。

2、有长按和点击的区别,长按的时候水波是慢慢扩散,如果点击则会迅速扩散。

演示效果(这里暂时不贴图了,没有安装Android模拟器,动画效果录制不理想)

实现过程可以参考任老师的博文,并参考代码注释(注释的很详细,想必不难理解)

MyButton.java

package com.example.myreveallayout;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
/**
 * Android 5.0按钮点击效果
 * 说明:可以将View替换成Button、ImageButton等组件。
 * @author 阳光小强  http://blog.csdn.net/dawanganban
 *
 */
public class MyButton extends View{
	
	private static final int INVALIDATE_DURATION = 20; //每次刷新的时间间隔
	private static int DIFFUSE_GAP = 10;				  //扩散半径增量
	private static int TAP_TIMEOUT;					  //判断点击和长按的时间
	
	private int viewWidth;							  //控件宽度和高度
	private int viewHeight;                            
	private int pointX;								  //控件原点坐标(左上角)
	private int pointY;
	private int maxRadio;							  //扩散的最大半径
	private int shaderRadio;
	
	private Paint bottomPaint;						  //画笔
	private Paint colorPaint;
	
	private boolean isPushButton;  					  //记录是否按钮被按下

	public MyButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		initPaint();
		TAP_TIMEOUT = ViewConfiguration.getLongPressTimeout();
	}
	
	/**
	 * 初始化画笔资源
	 */
	private void initPaint() {
		colorPaint = new Paint();
		bottomPaint = new Paint();
		colorPaint.setColor(getResources().getColor(R.color.reveal_color));
		bottomPaint.setColor(getResources().getColor(R.color.bottom_color));
	}
	
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		this.viewWidth = w;
		this.viewHeight = h;
	}
	
	private int eventX;
	private int eventY;
	private long downTime = 0;
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			//只需要取一次时间
			if(downTime == 0){
				downTime = SystemClock.elapsedRealtime();
			}
			eventX = (int)event.getX();
			eventY = (int)event.getY();
			//计算最大半径
			countMaxRadio();
			isPushButton = true;
			postInvalidateDelayed(INVALIDATE_DURATION);
			break;
		case MotionEvent.ACTION_UP:
		case MotionEvent.ACTION_CANCEL:
			if(SystemClock.elapsedRealtime() - downTime < TAP_TIMEOUT){
				DIFFUSE_GAP = 30;
				postInvalidate();
			}else{
				clearData();
			}
			break;
		}
		return true;
	}

	/**
	 * 计算此时的最大半径
	 */
	private void countMaxRadio() {
		if(viewWidth > viewHeight){
			if(eventX < viewWidth / 2){
				maxRadio = viewWidth - eventX;
			}else{
				maxRadio = viewWidth / 2 + eventX;
			}
		}else{
			if(eventY < viewHeight / 2){
				maxRadio = viewHeight - eventY;
			}else{
				maxRadio = viewHeight / 2 + eventY;
			}
		}
	}
	
	/**
	 * 清理改变的数据(初始化数据)
	 */
	private void clearData(){
		downTime = 0;
		DIFFUSE_GAP = 10;
		isPushButton = false;
		shaderRadio = 0;
		postInvalidate();
	}
	
	@Override
	protected void dispatchDraw(Canvas canvas) {
		super.dispatchDraw(canvas);
		if(!isPushButton) return; //如果按钮没有被按下则返回
		
		//绘制按下后的整个背景
		canvas.drawRect(pointX, pointY, pointX + viewWidth, pointY + viewHeight, bottomPaint);
		canvas.save();
		//绘制扩散圆形背景
		canvas.clipRect(pointX, pointY, pointX + viewWidth, pointY + viewHeight);
		canvas.drawCircle(eventX, eventY, shaderRadio, colorPaint);
		canvas.restore();
		//直到半径等于最大半径
		if(shaderRadio < maxRadio){
			postInvalidateDelayed(INVALIDATE_DURATION, 
					pointX, pointY, pointX + viewWidth, pointY + viewHeight);
			shaderRadio += DIFFUSE_GAP;
		}else{
			clearData();
		}
	}
}
完整源代码下载请点击右下角跳舞的小人,在群共享中可下载。

posted on 2015-01-13 00:03  岚之山  阅读(515)  评论(0编辑  收藏  举报

导航