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

android 路径动画制作

2015-03-06 10:23 113 查看
1、前言

今天项目要用到一个类似微信发送么么哒,那种屏幕飘表情的功能,所以分析研究了一下,用到的技术应该是路径动画,不知道这样就正不正确,反正就是画一个路径线,然后对象根据这个路径去运动。所以就叫他路径动画了。

路径动画要首先要解决的问题就是怎么画这个路径?然后路径画出来后怎么取路径上的所有点的坐标值?

这里解决这两个问题就看一个类PathMeasure 这个类接收一个path对象,然后可以根据pathMeasure.getPosTan()可以得到长度比例的坐标值。这两个问题就直接搞定了。用path画一个路径然后取点,动态移动对象,就变成了路径动画了。是不是很简单。

2、看效果



3、核心代码

[java] view
plaincopy





/**

* 撒花

*

* @author yd

*

用到的知识点:

1、android属性动画

2、Path路径绘制

3、贝塞尔曲线

*

*

*

*

*

*

*

*

*/

public class FllowerAnimation extends View implements AnimatorUpdateListener {

/**

* 动画改变的属性值

*/

private float phase1 = 0f;

private float phase2 = 0f;

private float phase3 = 0f;

/**

* 小球集合

*/

private List<Fllower> fllowers1 = new ArrayList<Fllower>();

private List<Fllower> fllowers2 = new ArrayList<Fllower>();

private List<Fllower> fllowers3 = new ArrayList<Fllower>();

/**

* 动画播放的时间

*/

private int time = 4000;

/**

* 动画间隔

*/

private int delay = 500;

/**

* 资源ID

*/

// private int resId = R.drawable.fllower_love;

public FllowerAnimation(Context context) {

super(context);

init(context);

// this.resId = resId;

}

@SuppressWarnings("deprecation")

private void init(Context context) {

WindowManager wm = (WindowManager) context

.getSystemService(Context.WINDOW_SERVICE);

width = wm.getDefaultDisplay().getWidth();

height = (int) (wm.getDefaultDisplay().getHeight() * 3 / 2f);

mPaint = new Paint();

mPaint.setAntiAlias(true);

mPaint.setStrokeWidth(2);

mPaint.setColor(Color.BLUE);

mPaint.setStyle(Style.STROKE);

pathMeasure = new PathMeasure();

builderFollower(fllowerCount, fllowers1);

builderFollower(fllowerCount , fllowers2);

builderFollower(fllowerCount , fllowers3);

}

/**

* 宽度

*/

private int width = 0;

/**

* 高度

*/

private int height = 0;

/**

* 曲线高度个数分割

*/

private int quadCount = 10;

/**

* 曲度

*/

private float intensity = 0.2f;

/**

* 第一批个数

*/

private int fllowerCount = 4;

/**

* 创建花

*/

private void builderFollower(int count, List<Fllower> fllowers) {

int max = (int) (width * 3 / 4f);

int min = (int) (width / 4f);

Random random = new Random();

for (int i = 0; i < count; i++) {

int s = random.nextInt(max) % (max - min + 1) + min;

Path path = new Path();

CPoint CPoint = new CPoint(s, 0);

List<CPoint> points = builderPath(CPoint);

drawFllowerPath(path, points);

Fllower fllower = new Fllower();

fllower.setPath(path);

fllowers.add(fllower);

}

}

/**

* 画曲线

* @param path

* @param points

*/

private void drawFllowerPath(Path path, List<CPoint> points) {

if (points.size() > 1) {

for (int j = 0; j < points.size(); j++) {

CPoint point = points.get(j);

if (j == 0) {

CPoint next = points.get(j + 1);

point.dx = ((next.x - point.x) * intensity);

point.dy = ((next.y - point.y) * intensity);

} else if (j == points.size() - 1) {

CPoint prev = points.get(j - 1);

point.dx = ((point.x - prev.x) * intensity);

point.dy = ((point.y - prev.y) * intensity);

} else {

CPoint next = points.get(j + 1);

CPoint prev = points.get(j - 1);

point.dx = ((next.x - prev.x) * intensity);

point.dy = ((next.y - prev.y) * intensity);

}

// create the cubic-spline path

if (j == 0) {

path.moveTo(point.x, point.y);

} else {

CPoint prev = points.get(j - 1);

path.cubicTo(prev.x + prev.dx, (prev.y + prev.dy),

point.x - point.dx, (point.y - point.dy),

point.x, point.y);

}

}

}

}

/**

* 曲线摇摆的幅度

*/

private int range = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 70, getResources().getDisplayMetrics());

/**

* 画路径

*

* @param point

* @return

*/

private List<CPoint> builderPath(CPoint point) {

List<CPoint> points = new ArrayList<CPoint>();

Random random = new Random();

for (int i = 0; i < quadCount; i++) {

if (i == 0) {

points.add(point);

} else {

CPoint tmp = new CPoint(0, 0);

if (random.nextInt(100) % 2 == 0) {

tmp.x = point.x + random.nextInt(range);

} else {

tmp.x = point.x - random.nextInt(range);

}

tmp.y = (int) (height / (float) quadCount * i);

points.add(tmp);

}

}

return points;

}

/**

* 画笔

*/

private Paint mPaint;

/**

* 测量路径的坐标位置

*/

private PathMeasure pathMeasure = null;

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

drawFllower(canvas, fllowers1);

drawFllower(canvas, fllowers2);

drawFllower(canvas, fllowers3);

}

/**

* 高度往上偏移量,把开始点移出屏幕顶部

*/

private float dy = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,40, getResources().getDisplayMetrics());

/**

*

* @param canvas

* @param fllowers

*/

private void drawFllower(Canvas canvas, List<Fllower> fllowers) {

for (Fllower fllower : fllowers) {

float[] pos = new float[2];

canvas.drawPath(fllower.getPath(),mPaint);

pathMeasure.setPath(fllower.getPath(), false);

pathMeasure.getPosTan(height * fllower.getValue(), pos, null);

canvas.drawCircle(pos[0], pos[1], 10, mPaint);

// Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId);

// canvas.drawBitmap(bitmap, pos[0], pos[1] - dy, null);

// bitmap.recycle();

}

}

public void startAnimation() {

ObjectAnimator mAnimator1 = ObjectAnimator.ofFloat(this, "phase1", 0f,

1f);

mAnimator1.setDuration(time);

mAnimator1.addUpdateListener(this);

mAnimator1.start();

mAnimator1.setInterpolator(new AccelerateInterpolator(1f));

ObjectAnimator mAnimator2 = ObjectAnimator.ofFloat(this, "phase2", 0f,

1f);

mAnimator2.setDuration(time);

mAnimator2.addUpdateListener(this);

mAnimator2.start();

mAnimator2.setInterpolator(new AccelerateInterpolator(1f));

mAnimator2.setStartDelay(delay);

ObjectAnimator mAnimator3 = ObjectAnimator.ofFloat(this, "phase3", 0f,

1f);

mAnimator3.setDuration(time);

mAnimator3.addUpdateListener(this);

mAnimator3.start();

mAnimator3.setInterpolator(new AccelerateInterpolator(1f));

mAnimator3.setStartDelay(delay * 2);

}

/**

* 跟新小球的位置

*

* @param value

* @param fllowers

*/

private void updateValue(float value, List<Fllower> fllowers) {

for (Fllower fllower : fllowers) {

fllower.setValue(value);

}

}

/**

* 动画改变回调

*/

@Override

public void onAnimationUpdate(ValueAnimator arg0) {

updateValue(getPhase1(), fllowers1);

updateValue(getPhase2(), fllowers2);

updateValue(getPhase3(), fllowers3);

Log.i(tag, getPhase1() + "");

invalidate();

}

public float getPhase1() {

return phase1;

}

public void setPhase1(float phase1) {

this.phase1 = phase1;

}

public float getPhase2() {

return phase2;

}

public void setPhase2(float phase2) {

this.phase2 = phase2;

}

public float getPhase3() {

return phase3;

}

public void setPhase3(float phase3) {

this.phase3 = phase3;

}

private String tag = this.getClass().getSimpleName();

private class CPoint {

public float x = 0f;

public float y = 0f;

/** x-axis distance */

public float dx = 0f;

/** y-axis distance */

public float dy = 0f;

public CPoint(float x, float y) {

this.x = x;

this.y = y;

}

}

}

4、项目地址
http://download.csdn.net/detail/hxc2008q/8473053
转自:http://blog.csdn.net/spring_he/article/details/44064607
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: