先看看效果图吧

d1c5cc5c077fc350d169d7150f6630d2.gif

实现这样的效果,你要知道贝塞尔曲线,何谓贝塞尔曲线?先在这里打个问号

下面就直接写了

1.activity_main.xml

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent" >

//撒花的区域

android:id="@+id/rlt_animation_layout"

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:id="@+id/btn_start"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentBottom="true"

android:layout_centerHorizontal="true"

android:layout_marginBottom="23dp"

android:text="开始撒花" />

2.Fllower

传参类

package com.lgl.test;

import android.graphics.Bitmap;

import android.graphics.Path;

import java.io.Serializable;

public class Fllower implements Serializable {

private static final long serialVersionUID = 1L;

private Bitmap image;

private float x;

private float y;

private Path path;

private float value;

public Bitmap getResId() {

return image;

}

public void setResId(Bitmap img) {

this.image = img;

}

public float getX() {

return x;

}

public void setX(float x) {

this.x = x;

}

public float getY() {

return y;

}

public void setY(float y) {

this.y = y;

}

public Path getPath() {

return path;

}

public void setPath(Path path) {

this.path = path;

}

public float getValue() {

return value;

}

public void setValue(float value) {

this.value = value;

}

@Override

public String toString() {

return "Fllower [ x=" + x + ", y=" + y + ", path=" + path + ", value="

+ value + "]";

}

}

3.FllowerAnimation

动画类

package com.lgl.test;

import java.util.ArrayList;

import java.util.List;

import java.util.Random;

import android.animation.ObjectAnimator;

import android.animation.ValueAnimator;

import android.animation.ValueAnimator.AnimatorUpdateListener;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.Canvas;

import android.graphics.Paint;

import android.graphics.Path;

import android.graphics.PathMeasure;

import android.util.Log;

import android.util.TypedValue;

import android.view.View;

import android.view.WindowManager;

import android.view.animation.AccelerateInterpolator;

/**

* 撒花 用到的知识点: 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 fllowers1 = new ArrayList();

private List fllowers2 = new ArrayList();

private List fllowers3 = new ArrayList();

/**

* 动画播放的时间

*/

private int time = 4000;

/**

* 动画间隔

*/

private int delay = 400;

int[] ylocations = { -100, -50, -25, 0 };

/**

* 资源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 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, ylocations[random.nextInt(3)]);

List points = builderPath(CPoint);

drawFllowerPath(path, points);

Fllower fllower = new Fllower();

fllower.setPath(path);

Bitmap bitmap = BitmapFactory.decodeResource(getResources(),

R.drawable.lift_flower);

fllower.setResId(bitmap);

fllowers.add(fllower);

}

}

/**

* 画曲线

*

* @param path

* @param points

*/

private void drawFllowerPath(Path path, List 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 builderPath(CPoint point) {

List points = new ArrayList();

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 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);

canvas.drawBitmap(fllower.getResId(), pos[0], pos[1] - dy, null);

}

}

ObjectAnimator mAnimator1;

ObjectAnimator mAnimator2;

ObjectAnimator mAnimator3;

public void startAnimation() {

if (mAnimator1 != null && mAnimator1.isRunning()) {

mAnimator1.cancel();

}

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

mAnimator1.setDuration(time);

mAnimator1.addUpdateListener(this);

mAnimator1.start();

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

if (mAnimator2 != null && mAnimator2.isRunning()) {

mAnimator2.cancel();

}

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

mAnimator2.setDuration(time);

mAnimator2.addUpdateListener(this);

mAnimator2.start();

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

mAnimator2.setStartDelay(delay);

if (mAnimator3 != null && mAnimator3.isRunning()) {

mAnimator3.cancel();

}

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 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.MainActivity

接着就看我们使用

package com.lgl.test;

import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.RelativeLayout;

public class MainActivity extends Activity {

private Button btn_start;

// 撒花特效

private RelativeLayout rlt_animation_layout;

private FllowerAnimation fllowerAnimation;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

// 撒花初始化

rlt_animation_layout = (RelativeLayout) findViewById(R.id.rlt_animation_layout);

rlt_animation_layout.setVisibility(View.VISIBLE);

fllowerAnimation = new FllowerAnimation(this);

RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(

RelativeLayout.LayoutParams.MATCH_PARENT,

RelativeLayout.LayoutParams.MATCH_PARENT);

fllowerAnimation.setLayoutParams(params);

rlt_animation_layout.addView(fllowerAnimation);

btn_start = (Button) findViewById(R.id.btn_start);

btn_start.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

// 开始撒花

fllowerAnimation.startAnimation();

}

});

}

}

好,我们现在来看看效果

5114538394b2ed695419be64ffd125f9.gif

好的,你也赶快去试一下吧!大家可以制作类似的雪花飘落效果等,Try!

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐