Android水波纹效果

进入程序员的行业的时间也不短了,然而还没有发表过一篇文章,一直深表惭愧,本人了一直对android的各种特效深感兴趣,今天就来写写水波纹的特效,

通过继承View来自定义水波纹view,实现原理:通过计算出水波纹曲线的所有Y坐标,现曲Y点向控件底部画线构成一个水波纹的横面,现对整个横面进行平移再不断重绘达到动态的效果,废话不多说,看代码:


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.shouwei.csdn.R;
import com.shouwei.csdn.util.DensityUtils;

/**
 * 自定义水波纹控件
 * 
 * @author sw
 * @date 2015-7-1
 */
public class MyWaterRipples extends View {

	public final static double A = 8;
	public final static double CHUXIANG = 0;
	public final static double K = 0;
	// 波纹上升的高度
	public int riseHeight = 0;
	// 第一条水波移动速度
	private int translate_speed_one = 7;
	// 第二条水波移动速度
	private int translate_speed_two = 5;
	// 总宽度
	private int mTotalWidth = 0;
	// 总高度
	private int mTotalHeight = 0;
	// 原始波纹y坐标数组
	private float[] mYPositions;
	// 第一条波纹y坐标
	private float[] mYPositionsOne;
	// 第二条波纹Y坐标
	private float[] mYPositionsTwo;
	// 画笔
	private Paint mWavePaint;
	private PaintFlagsDrawFilter mDrawFilter;
	// 第一条波纹平移的长度
	private int YOffsetOne;
	// 第二条波纹平移的长度
	private int YOffsetTwo;
	public MyWaterRipples(Context context, AttributeSet attrs) {
		super(context, attrs);
		// 将dp转化为px统一不同分辨率下的速度一致
		translate_speed_one = DensityUtils.dp2px(context, translate_speed_one);
		translate_speed_two = DensityUtils.dp2px(context, translate_speed_two);
		// 画笔
		mWavePaint = new Paint();
		mWavePaint.setColor(getResources().getColor(R.color.seablue));
		mWavePaint.setAntiAlias(true);

		mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG
				| Paint.FILTER_BITMAP_FLAG);
	}
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// 获得屏幕宽度
		mTotalWidth = getWidth();
		mTotalHeight = getHeight();

		// 保存原始Y坐标数组
		mYPositions = new float[mTotalWidth];
		// 保存第一条波浪的Y坐标数组
		mYPositionsOne = new float[mTotalWidth];
		// 保存第二条波浪的Y坐标数组
		mYPositionsTwo = new float[mTotalHeight];
		// 根据view总宽度得出所有对应的y值
		// 正弦函数:y=Asin(ωx+φ)+k
		// A:决定峰值(即纵向拉伸压缩的倍数)
		// (ωx+φ)——相位,反映变量y所处的状态。
		// φ——初相,x=0时的相位;反映在坐标系上则为图像的左右移动。
		// k——偏距,反映在坐标系上则为图像的上移或下移。
		// ω——角速度, 控制正弦周期(单位角度内震动的次数)。
		// 将周期定为view总宽度
		for (int i = 0; i < mTotalWidth; i++) {
			mYPositions[i] = (float) (A
					* Math.sin(((float) (2 * Math.PI / mTotalWidth)) * i
							+ CHUXIANG) + K);
		}
	}
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		resetYPosition();
		Log.i("savion", "ondraw----------");
		// 从canvas层面去除绘制时锯齿
		canvas.setDrawFilter(mDrawFilter);
		if (mTotalWidth != 0) {
			for (int i = 0; i < mTotalWidth; i++) {
				// 减400只是为了控制波纹绘制的y的在屏幕的位置,大家可以改成一个变量,然后动态改变这个变量,从而形成波纹上升下降效果
				// 绘制第一条水波纹
				canvas.drawLine(i, mTotalHeight - mYPositionsOne[i]
						- riseHeight, i, mTotalHeight, mWavePaint);
				canvas.drawLine(i, mTotalHeight - mYPositionsTwo[i]
						- riseHeight, i, mTotalHeight, mWavePaint);
			}
		}
		YOffsetOne += translate_speed_one;
		YOffsetTwo += translate_speed_two;
		if (YOffsetOne >= mTotalWidth) {
			YOffsetOne = 0;
		}
		if (YOffsetTwo >= mTotalWidth) {
			YOffsetTwo = 0;
		}
		postInvalidate();
	}
	private void resetYPosition() {
		// 第一条水波纹
		int restLengthone = mYPositions.length - YOffsetOne;
		// 复制mYPosition数组中yoffsetone位置开始的元素到mYPositionsone数组中0位置,长度为restLenghtOne个
		System.arraycopy(mYPositions, YOffsetOne, mYPositionsOne, 0,
				restLengthone);
		// 复制mYPosition数组中0位置开始的元素到mYPositionsone数组中restLenghtOne位置,长度为YOffsetOne个
		System.arraycopy(mYPositions, 0, mYPositionsOne, restLengthone,
				YOffsetOne);
		// 第二条水波纹
		int restLenghttwo = mYPositions.length - YOffsetTwo;
		System.arraycopy(mYPositions, YOffsetTwo, mYPositionsTwo, 0,
				restLenghttwo);
		System.arraycopy(mYPositions, 0, mYPositionsTwo, restLenghttwo,
				YOffsetTwo);
	}
	public void setWaterHeight(int height) {
		if (mTotalHeight != 0) {
			this.riseHeight = mTotalHeight * height / 100;
		}
	}
	interface OnWaterWaveHeightChangeListener {
		public void onWaterHeightChange(int height);
	}
}



在onDraw中绘制水波纹并根据平移速度相应增加平移的长度,并调用重绘,如下:

protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		resetYPosition();
		Log.i("savion", "ondraw----------");
		// 从canvas层面去除绘制时锯齿
		canvas.setDrawFilter(mDrawFilter);
		if (mTotalWidth != 0) {
			for (int i = 0; i < mTotalWidth; i++) {
				// 减400只是为了控制波纹绘制的y的在屏幕的位置,大家可以改成一个变量,然后动态改变这个变量,从而形成波纹上升下降效果
				// 绘制第一条水波纹
				canvas.drawLine(i, mTotalHeight - mYPositionsOne[i]
						- riseHeight, i, mTotalHeight, mWavePaint);
				canvas.drawLine(i, mTotalHeight - mYPositionsTwo[i]
						- riseHeight, i, mTotalHeight, mWavePaint);
			}
		}

		YOffsetOne += translate_speed_one;
		YOffsetTwo += translate_speed_two;
		if (YOffsetOne >= mTotalWidth) {
			YOffsetOne = 0;
		}
		if (YOffsetTwo >= mTotalWidth) {
			YOffsetTwo = 0;
		}

		postInvalidate();
	}

最后配合setWaterHright方法可在外部调用对水波纹的高度进行动态设置:

public void setWaterHeight(int height) {
		if (mTotalHeight != 0) {
			this.riseHeight = mTotalHeight * height / 100;
		}
	}

最终效果如下:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值