iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >Android仿支付宝笑脸刷新加载动画的实现代码
  • 593
分享到

Android仿支付宝笑脸刷新加载动画的实现代码

支付宝动画Android 2022-06-06 05:06:15 593人浏览 八月长安
摘要

看到支付宝的下拉刷新有一个笑脸的动画,因此自己也动手实现一下。效果图如下: 一、总体思路 1、静态部分的笑脸。 这一部分的笑脸就是一个半圆弧,加上两颗眼睛,这部分比较简单,用

看到支付宝的下拉刷新有一个笑脸的动画,因此自己也动手实现一下。效果图如下:

这里写图片描述

一、总体思路

1、静态部分的笑脸。

这一部分的笑脸就是一个半圆弧,加上两颗眼睛,这部分比较简单,用于一开始的展示。

2、动态笑脸的实现。

2.1、先是从底部有一个圆形在运动,运动在左眼位置时把左眼给绘制,同时圆形继续运动,运动到右眼位置时绘制右眼,圆形继续运动到最右边的位置。

2.2、当上面的圆形运动到最右边时候,开始不断绘制脸,从右向左,脸不断增长,这里脸设置为接近半个圆形的大小。

2.3、当脸画完的时候,开始让脸旋转起来,就是一边在增长的同时,另一边是在缩短的。

2.4、最后脸的部分是慢慢缩为一个点的,此时动画结束。

2.5、时间可以看做时最底部的那个圆形运动了两周,因此可以用分数来表示每一部分的运动,如从底部开始到左眼睛的位置,用时比例为(1/4+1/8),最终控制每一部分的动画比例的和加起来为2即可。

大概是这样的时间比例:(1/4+1/8) + (1/4) +(1/8) +(1/2) +(1/4) +(1/4+1/4) ,其中1/4代表1/4个圆弧,也是1/4的时间,其它的类似。

二、代码实现

1、重写onMeasure()方法

处理为wrap_content情况,那么它的specMode是AT_MOST模式,在这种模式下它的宽/高等于spectSize,这种情况下view的spectSize是parentSize,而parentSize是父容器目前可以使用大小,就是父容器当前剩余的空间大小, 就相当于使用match_parent一样 的效果,因此我们可以设置一个默认的值。


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpectMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpectSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpectMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpectSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthSpectMode == MeasureSpec.AT_MOST
&& heightSpectMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(mWidth, mHeight);
} else if (widthSpectMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(mWidth, heightSpectSize);
} else if (heightSpectMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(widthSpectSize, mHeight);
}
}

2、在构造函数中调用init()方法

进行初始化,之所以看到运动中圆弧能够在右边增长的同时,左边的也在减少是使用PathMeasure类中的getSegment方法来截取任意一段长度的路径。


private void init(Context context, AttributeSet attrs) {
drawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG
| Paint.FILTER_BITMAP_FLAG);
lineWidth = dip2px(context, lineWidth);
radius = dip2px(context, radius);
path = new Path();
pathCircle = new Path();
pathCircle2 = new Path();
//在path中添加一个顺时针的圆,这时候路径的起点和终点在最后边
//在画前半部分的脸和运动中的脸,起点在最右边比较方便的计算,但在最后那部分,运动的终点
//是在圆形的底部,这样把路径圆进行转换到底部,方便计算
pathCircle.addCircle(0, 0, radius, Direction.CW);
pathCircle2.addCircle(0, 0, radius, Direction.CW);
//利用Matrix,让pathCircle中的圆旋转90度,这样它的路径的起点和终点都在底部了
Matrix m = new Matrix();
m.postRotate(90);
pathCircle.transfORM(m);
//画脸的笔
paint = new Paint();
//画眼睛的笔
eyePaint = new Paint();
paint.setColor(blue);
eyePaint.setColor(blue);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(lineWidth);
eyePaint.setStrokeWidth(lineWidth);
//设置画脸的笔的端点为圆角(即起点和终点都是圆角)
paint.setStrokeCap(Paint.Cap.ROUND);
//使用PathMeasure计算路径的信息
pm = new PathMeasure();
pm.setPath(pathCircle, false);
pm2 = new PathMeasure();
pm2.setPath(pathCircle2, false);
//路径的长度,两个路径都是圆形,因此只计算其中一个即可
length = pm.getLength();
eyeRadius = (float)(lineWidth/2.0+lineWidth/5.0);
}

3、画静态笑脸

pm2.getSegment()方法可以获取指定长度的路径,然后保存在path中,在第二步已经把一个圆加到path中去,并初始化了pm2了。



private void first(canvas canvas) {
pm2.getSegment(10, length / 2-10, path, true);
canvas.drawPath(path, paint);
path = new Path();
drawEye(canvas);
}

public void drawEye(Canvas canvas) {
float x = (float) ((radius) * Math.cos(Math.PI * 45 / 180));
float y = x;
canvas.drawCircle(-x, -y, eyeRadius , eyePaint);
canvas.drawCircle(x, -y, eyeRadius , eyePaint);
}

4、实现运动的圆形的方法,即动画开始部分。

这里记得要进行角度转换,π=180



private void drawCircle(Canvas canvas) {
float degree = 270 - 270 * 4 / 3 * fraction;
float x = (float) ((radius ) * Math.cos(Math.PI * degree/180));
float y = -(float) ((radius ) * Math.sin(Math.PI * degree/ 180));
canvas.drawCircle(x, y, eyeRadius, eyePaint);
}

5、在圆形运动的同时画眼睛

在圆形运动到左眼的位置时,同时绘制左眼,时间为1/4+1/8=3/8
运动到右眼位置时绘制右眼,时间为1/4+1/8+1/4=5/8
两个眼睛的位置都设为45度



public void drawOneEye(Canvas canvas, int pos) {
float x = (float) ((radius) * Math.cos(Math.PI * 45 / 180));
float y = x;
if (pos == 0) {
canvas.drawCircle(-x, -y, eyeRadius, eyePaint);
}else if(pos==1){
canvas.drawCircle(x, -y, eyeRadius , eyePaint);
}
}

6、动画进行之后绘制笑脸

笑脸部分是半个圆,因此截取的最大长度是length/2
用的时间是1/2,画完之后fraction应该到了5/4的时间了,1/4+1/8+1/4+1/8+1/2=5/4


public void drawFace(Canvas canvas){
//需要重新给path赋值
path=null;
path = new Path();
//根据时间来截取一定长度的路径,保存到path中,取值范围(0,length/2)
pm2.getSegment(0, (float) (length*(fraction-0.75)), path, true);
canvas.drawPath(path, paint);
}

7、笑脸绘制完成后,把它动起来。

把圆脸部分逆时针旋转起来,截取最大长度还是length/2, 用的是这个方法pm2.getSegment(),运动的时间为1/4时间,需要不断改变起点和终点,这样圆脸才会动起来


public void rotateFace(Canvas canvas){
path=null;
path = new Path();
pm2.getSegment((float)(length*(fraction-5.0/4)), (float)(length*(fraction-5.0/4)+length*0.5), path, true);
canvas.drawPath(path, paint);
}

8、最后那部分动画的实现。

剩下的1/4时间,就用另外一个PathMeasure,这个圆的路径起点是底部的,在初始化时候已经进行转换,因为这样设置比较方便的计算它的终点位置。


public void drawLastFact(Canvas canvas){
path = null;
path = new Path();
//从起点的1/4长度开始(即最左边的圆点),到圆的路径的终点(即底部)
pm.getSegment((float)(1.0/4*length+3.0/2*(fraction-3.0/2)*length), (float)(length/2.0+length/8.0+(fraction-3.0/2)*length), path, true);
canvas.drawPath(path, paint);
}

9、属性动画的实现


public void performAnim() {
//上面计算的时间比例,加起来就是2,是运动了两周,因此这里设置为(0,2)
val = ValueAnimator.ofFloat(0, 2);
val.setDuration(duration);
val.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator arg0) {
fraction = (float) arg0.getAnimatedValue();
postInvalidate();
}
});
val.setRepeatCount(repeaCount);
val.start();
val.setRepeatMode(ValueAnimator.RESTART);
}

10 、在onDraw()方法中调用一上方法。

这里的fraction的范围是[0,2],每个片段就用分数表示,最后它们的和刚好是2。


@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
if (changed) {
mWidth = right - left;
mHeight = bottom - top;
}
}
}
@Override
protected void onDraw(Canvas canvas) {
//从画布上去除锯齿
canvas.setDrawFilter(drawFilter);
canvas.translate(mWidth / 2, mHeight / 2);
if (fraction == -1||!val.isRunning())
first(canvas);
//从底部开始画一个在运动的圆,运动时间为0-3/4
if (0 < fraction && fraction < 0.75) {
drawCircle(canvas);
}
//画左眼
if (fraction > 1.0 * 3 / 8&&fraction<1.0*6/4) {
drawOneEye(canvas,0);
}
//画右眼
if(fraction>1.0*5/8&&fraction<1.0*6/4){
drawOneEye(canvas, 1);
}
//画脸
if(fraction>=0.75&&fraction<=5.0/4){
drawFace(canvas);
}
//把脸运动起来
if(fraction>=5.0/4&&fraction<=(5.0/4+1.0/4)){
rotateFace(canvas);
}
if(fraction>=6.0/4){
drawLastFact(canvas);
}
}

11、其它的方法和字段的定义



public int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
//字段
private final int blue = 0xff4aadff;
private int mWidth = 200;
private int mHeight = 200;
private int radius = 20;
private int lineWidth = 5;
private float eyeRadius;
Paint paint,eyePaint;
DrawFilter drawFilter;
Path path, pathCircle,pathCircle2;
PathMeasure pm,pm2;
float length;// 圆周长
float fraction = -1;
long duration = 2000;
int repeaCount = 8;
float x = 0, y = 0;
ValueAnimator val;

11、自定义控件的使用


//在布局中的设置
<com.example.test22.view.SmileView 
Android:id="@+id/smile"
android:layout_width="match_parent"
android:layout_height="100dp"/>

在Activity中,


SmileView smile;
smile = (SmileView)findViewById(R.id.smile);
//设置动画执行时间,重复的次数。
smile.setDuration(2000);
smile.setRepeaCount(8);
//执行动画
smile.performAnim();
//停止动画
smile.cancelAnim();

三、总结

我觉得难点在于运动中圆弧的一边增长的同时,另一边在缩短的控制,计算的不好就很容易出现从一个片段到另外一个片段时候跳跃十分明显,在这里我用到两个路径的圆,一个圆的起点在最右边,一个圆起点在底部,这样在处理最后那部分,片段的终点需要回到底部时候比较方便。重点在于PathMeasure类的getSegment()方法的运用,同时会改变默认路径的起点。

以上所述是小编给大家介绍的Android仿支付宝笑脸刷新加载动画的实现代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程网网站的支持!

您可能感兴趣的文章:Android自定义渐变式炫酷ListView下拉刷新动画Android开发中MJRefresh自定义刷新动画效果Android 模仿iPhone列表数据View刷新动画详解超好看的下拉刷新动画Android代码实现一个简单的Android圆弧刷新动画


--结束END--

本文标题: Android仿支付宝笑脸刷新加载动画的实现代码

本文链接: https://www.lsjlt.com/news/23136.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android实现笑脸进度加载动画
    目录一、默认状态1、画嘴巴2、画眼睛二、合并状态1、嘴巴的旋转2、眼睛的旋转三、自转状态1、开启动画2、重新绘制四、分离状态最后附上完整代码最近看到豆瓣的笑脸loading很有意思,...
    99+
    2024-04-02
  • 怎么在Android中实现一个笑脸进度加载动画
    怎么在Android中实现一个笑脸进度加载动画?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Android是什么Android是一种基于Linux内核的自由及开放源代码的操作系...
    99+
    2023-06-14
  • Android实现人脸支付的示例代码
    目录效果展示功能实现人脸支付密码框输入支付尾言效果展示 人脸支付效果视频 密码框输入支付效果视频 因为密码支付时会调起系统安全键盘,开启自动保护功能,防止泄露,会导致输入密码时录屏...
    99+
    2024-04-02
  • Android 实现仿支付宝的密码均分输入框
    Android 仿支付宝的密码均分输入框此为安卓项目,通过重绘edittext进行文字的均分排布。直接贴上代码:package com.xxx.xxx;import android.content.Context;import androi...
    99+
    2023-05-31
    android 支付宝 密码
  • 用CSS3实现的加载动画效果代码分享
    这篇文章主要讲解了“用CSS3实现的加载动画效果代码分享”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“用CSS3实现的加载动画效果代码分享”吧!很棒的loa...
    99+
    2024-04-02
  • vue基于vant实现上拉加载下拉刷新的示例代码
    前言 普遍存在于各种app中的上拉加载下拉刷新功能大家都不陌生吧,一般来说,在数据量比较大的情况下,为了更快的渲染和给用户更好的观感体验,我们会将数据做分页处理,让其批量加载,这样一...
    99+
    2024-04-02
  • uniapp实现下拉刷新与上拉触底加载功能的示例代码
    目录下拉刷新上拉触底加载 完整demo 效果 下拉刷新 这个用于监听该页面用户下拉刷新事件。 首先在pages.json中需要下拉刷新的页面,在styl...
    99+
    2023-05-16
    uniapp实现下拉刷新 uniapp实现上拉触底加载 uniapp下拉刷新 uniapp上拉加载
  • 微信小程序实现触底加载与下拉刷新的示例代码
    目录触底加载loader函数思考loader函数实现触底加载动画触底加载的优点下拉刷新最后在最近做小程序的时候有这么一个很常见的需求,加载一个信息列表,要求需要触底加载和下拉刷新,我...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作