本来想写写有点意思的东西的,哈哈。上篇文章说的。以后再写吧。今天先介绍一下一个水波载入动画,效果图例如以下:
做的比較简单。真机效果比这个好非常多,这个截图做的gif,有点蛋疼。
说说思路吧:
1. 首先画正弦曲线。这里取的是正弦周期的前3/4个周期。这样看起来比其它的周期变化非常好点;
2. 画了正弦曲线以后,就要让正弦曲线动起来,怎么动起来?乍一看认为非常困难的样子。事实上我们想想移动正弦曲线,只是是某个位置的Y轴值变化了,那么我们仅仅要给sin(x)中加入一个变量即可。即sin(x + offset)。offset的值按时间规律来变化。那么最后表现出来的效果就有移动的感觉。
3. 关于正弦曲线振幅不能设置的太高,由于我们的屏幕本来就非常小,假设振幅非常大就表现的非常不真实。我这里取的是30,看起来效果还不错。
4. 最后就是y轴方向的改变了。
要不停的提升。这里写死了,假设想用。就直接写个方法。去设置即可,比方你要设置百分比之类的。
最后上代码:
package com.zdl.wavedemo; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.view.View; /** * Created by zhoudailiang on 2015/7/14. */ public class WaveView extends View { private Paint paint; private Path mPath; private float offset = 0.0f; // 控制正弦曲线的变化 private MyThread thread; private final float amplidute = 30; // 振幅 private float gradualY; // Y方向的渐变量 private float gradualX; // X方向的渐变量 private boolean isMoving = true; // 能够移动 public WaveView(Context context) { super(context); init(); } public WaveView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { // 初始化画笔 paint = new Paint(); paint.setAntiAlias(true); paint.setColor(Color.BLUE); paint.setStrokeWidth(2); // 初始化变量 gradualX = 0.02f; // 初始化路径 mPath = new Path(); // 初始化线程 thread = new MyThread(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); gradualY = getMeasuredHeight(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int width = getMeasuredWidth(); int height = getMeasuredHeight(); mPath.reset(); for (float i = 0; i < width; i += 0.5) { float tmp = (float) (1.5 * Math.PI * i / width); float y = amplidute * (float)Math.sin(tmp + offset) + gradualY; if (i == 0) { mPath.moveTo(0f, y); } else { mPath.lineTo(i, y); } } mPath.lineTo(width, height); mPath.lineTo(0, height); mPath.close(); canvas.drawPath(mPath, paint); // 启动线程開始更新 if (!thread.isAlive() && isMoving) { thread.start(); } } class MyThread extends Thread { public void run() { while (isMoving) { offset = offset + gradualX > 2 * Math.PI ? 0 : offset + gradualX; gradualY -= 0.5; if (gradualY < -amplidute) { isMoving = false; break; } try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } postInvalidate(); } } } }
代码如上,非常easy。事实上这里还能够通过还有一种方式实现。下篇文章进行介绍。
2015-7-15补充:
使用贝塞尔曲线,代码例如以下:
package com.zdl.wavedemo; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.view.View; /** * Created by Administrator on 2015/7/14. */ public class WaveBesselView extends View{ private Paint paint; private Path mPath; private float offset = 0.0f; // 控制正弦曲线的变化 private MyThread thread; private final float amplidute = 100; // 振幅 private float gradualY; // Y方向的渐变量 private float gradualX; // X方向的渐变量 private boolean isMoving = true; // private int width, height; public WaveBesselView(Context context) { super(context); init(); } public WaveBesselView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { // 初始化画笔 paint = new Paint(); paint.setAntiAlias(true); paint.setColor(Color.BLUE); paint.setStrokeWidth(2); // 初始化变量 gradualX = 0.0f; // 初始化路径 mPath = new Path(); // 初始化线程 thread = new MyThread(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); gradualY = getMeasuredHeight() - amplidute; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); width = getMeasuredWidth(); height = getMeasuredHeight(); int ave = width / 4; mPath.reset(); mPath.moveTo(gradualX, gradualY); mPath.cubicTo(gradualX + 1.73f * ave, gradualY - amplidute, gradualX + width - 1.73f * ave, gradualY + amplidute, gradualX + width, gradualY); mPath.cubicTo(gradualX + 1.73f * ave + width, gradualY - amplidute, gradualX + 2 * width - 1.73f * ave, gradualY + amplidute, gradualX + 3 * width, gradualY); mPath.lineTo(width, height); mPath.lineTo(0, height); mPath.close(); canvas.drawPath(mPath, paint); // 启动线程開始更新 if (!thread.isAlive() && isMoving) { thread.start(); } } class MyThread extends Thread { public void run() { while (isMoving) { gradualX = gradualX - 1f > -width ? gradualX - 1f : gradualX - 1f + width; gradualY -= 0.2; if (gradualY < -amplidute) { isMoving = false; break; } try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } postInvalidate(); } } } }