android 爱心动画,Android之二阶贝塞尔曲线的波浪头像(三阶的爱心飞出)

1、写这个demo主要是因为一个同事给我看了一个ios的效果,因为感觉好玩所以我就写了android样式的,具体的效果就如下图展示(图是ios的gif不过效果是一样的),有需要的朋友在下面会给出下载地址

0c76ca06c3a2e845ad7f4782e0d84152.png

首先分析一下我的做法,我是将波浪的部分和头像分开考虑,根据波浪的移动高度将头像画出

81980f250932e6b130371191b7149c45.png

一、定义属性

其实我在做的时候我是直接开始画,画完了才去优化自定义属性,然而现在这些过程已经不重要了,我就先介绍下定义的属性分别都是什么含义。

android:id="@+id/cv_waves"

android:layout_width="match_parent"

android:layout_marginTop="100dp"

app:imgSize="50dp"

app:waveHeight="20dp"

app:rollTime="20"

app:rollDistance="5"

android:layout_height="70dp" />

app:imgSize=”50dp”定义的是头像的大小

app:waveHeight=”20dp”波浪的高度

app:rollTime=”20”移动一次的时间

app:rollDistance=”5”移动一次的距离,像素

二、开始画CorrugateView这个控件

(1)获取所有属性的值和初始化所需要的画笔

public void init(Context context, AttributeSet attrs) {

TypedArray attr = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CorrugateView, 0, 0);

try {

imgSize = (int) attr.getDimension(R.styleable.CorrugateView_imgSize, getResources().getDimensionPixelSize(

R.dimen.top_distance));

waveHeight = (int) attr.getDimension(R.styleable.CorrugateView_waveHeight, getResources().getDimensionPixelSize(

R.dimen.top_distance_20));

rollTime = attr.getInteger(R.styleable.CorrugateView_rollTime, 30);

rollDistance = attr.getInteger(R.styleable.CorrugateView_rollDistance, 5);

} finally {

attr.recycle();

}

length = rollDistance;

//保存上面一条曲线的数组

mPointsList = new ArrayList();

//保存下面一条曲线的数组

mPointsListBottom = new ArrayList();

//画上面曲线的画笔和线

mWavePath = new Path();

mPaint = new Paint();

mPaint.setAntiAlias(true);

mPaint.setStyle(Paint.Style.FILL);

mPaint.setColor(getResources().getColor(R.color.white));

//画下面曲线的画笔和线

mWavePathBottom = new Path();

mPaintBottom = new Paint();

mPaintBottom.setAntiAlias(true);

mPaintBottom.setStyle(Paint.Style.FILL);

mPaintBottom.setColor(getResources().getColor(R.color.top_withe));

}

(2)获取控件的宽高和初始化要画的波浪的每个点

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

mWidth = getMeasuredWidth();

//控件高度=图片的高度加上波浪的高度

mHeight = waveHeight + imgSize;

//初始化每个点

initPoint();

invalidate();

//开启一个计时器

if (timer == null)

start();

}

initPoint();这个方法就是画二阶贝塞尔曲线的每个点,具体看代码,因为有点长就不贴进来了

start();开启一个计时器,主要作用是在一定时间按一定的距离将曲线向右移动

(3)画曲线

@Override

protected void onDraw(Canvas canvas) {

//画两条曲线

mWavePath.reset();

mWavePathBottom.reset();

mWavePathBottom.moveTo(mPointsListBottom.get(0).x, mPointsListBottom.get(0).y);

mWavePathBottom.quadTo(mPointsListBottom.get(1).x, mPointsListBottom.get(1).y, mPointsListBottom.get(2).x, mPointsListBottom.get(2).y);

mWavePathBottom.quadTo(mPointsListBottom.get(3).x, mPointsListBottom.get(3).y, mPointsListBottom.get(4).x, mPointsListBottom.get(4).y);

mWavePathBottom.quadTo(mPointsListBottom.get(5).x, mPointsListBottom.get(5).y, mPointsListBottom.get(6).x, mPointsListBottom.get(6).y);

mWavePathBottom.quadTo(mPointsListBottom.get(7).x, mPointsListBottom.get(7).y, mPointsListBottom.get(8).x, mPointsListBottom.get(8).y);

mWavePathBottom.quadTo(mPointsListBottom.get(9).x, mPointsListBottom.get(9).y, mPointsListBottom.get(10).x, mPointsListBottom.get(10).y);

mWavePathBottom.lineTo(mPointsListBottom.get(10).x, mHeight);

mWavePathBottom.lineTo(mPointsListBottom.get(0).x, mHeight);

mWavePathBottom.lineTo(mPointsListBottom.get(0).x, mPointsListBottom.get(0).y);

mWavePathBottom.close();

canvas.drawPath(mWavePathBottom, mPaintBottom);

mWavePath.moveTo(mPointsList.get(0).x, mPointsList.get(0).y);

mWavePath.quadTo(mPointsList.get(1).x, mPointsList.get(1).y, mPointsList.get(2).x, mPointsList.get(2).y);

mWavePath.quadTo(mPointsList.get(3).x, mPointsList.get(3).y, mPointsList.get(4).x, mPointsList.get(4).y);

mWavePath.quadTo(mPointsList.get(5).x, mPointsList.get(5).y, mPointsList.get(6).x, mPointsList.get(6).y);

mWavePath.quadTo(mPointsList.get(7).x, mPointsList.get(7).y, mPointsList.get(8).x, mPointsList.get(8).y);

mWavePath.lineTo(mPointsList.get(8).x, mHeight);

mWavePath.lineTo(mPointsList.get(0).x, mHeight);

mWavePath.lineTo(mPointsList.get(0).x, mPointsList.get(0).y);

mWavePath.close();

canvas.drawPath(mWavePath, mPaint);

//画头像

Bitmap bitmap = BitmapFactory.decodeResource(this.getContext()

.getResources(), R.mipmap.icon_2017);

drawImage(canvas, bitmap, (mWidth - imgSize) / 2, (int) getHeigthIcon() - imgSize,

imgSize, imgSize, 0, 0, mPaint);

//当移动的长度大于等于屏幕宽度重置点的坐标

if (allLength >= mWidth) {

resetPoints();

allLength = 0;

}

}

getHeigthIcon()这个方法比较重要,控制着头像的上下移动,主要运用贝塞尔曲线的二阶公式计算头像的高度,下图所示

d4a56fc09226aa189f14e8ae25c468cb.png

/** * 获取头像中心的x对应的曲线的y值 *@return */

private float getHeigthIcon() {

//移动的比率

float t = (float) allHeight * 2 / mWidth;

float y;

//ismHeight为true表示向下移动 false表示向上移动

if (ismHeight) {

//二价的贝塞尔曲线公式计算下面的曲线的根据t变化的高度

y = mPointsList.get(2).y * (1 - t) * (1 - t)

+ 2 * mPointsList.get(3).y * t * (1 - t)

+ mPointsList.get(4).y * t * t;

} else {

//二价的贝塞尔曲线公式计算上面的曲线的根据t变化的高度

y = mPointsList.get(0).y * (1 - t) * (1 - t)

+ 2 * mPointsList.get(1).y * t * (1 - t)

+ mPointsList.get(2).y * t * t;

}

return y;

}

drawImage(Canvas canvas, Bitmap blt, int x, int y, int w,int h, int bx, int by, Paint paint)画图片的方法,具体看代码,至此一个波浪的头像就算完成啦!感兴趣的下demo去看啦!

哦!差点忘了还有一个三阶的爱心,demo的LoveLayout.java这个文件哟!感兴趣的自己去看哟!

效果效果图,我又忘了!如下所示,里面使用了透明度的渐变,所以越高就越透明了,每个爱心的路径都是一条随机的三阶贝塞尔曲线,demo中只要点界面就会抛出一个爱心,自己去欣赏吧!

8f9e0425518f1d5e8d930a5c6052ac2f.png

demo下载地址:https://github.com/972242736/BubblingDemo.git

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值