本文记录一下实现仿支付宝写五褔及回放的过程。

先看效果如下,没有找到相关的背景图,只能以田字格当作背景。

整个过程分为两部分,一部分是写字,一部份是回放。 该过程主要使用了path和pathmeasure类,在网上有很多写的非常好博文可以参考。
自定义view的源码见文末链接,此处只摘取部分代码记录,以便后续参考和温故。

首先,实现写的过程。

@Override
public boolean onTouchEvent(MotionEvent event) {int action = event.getAction();switch (action) {case MotionEvent.ACTION_DOWN:Log.i(TAG, "onTouchEvent: action down" + MotionEvent.ACTION_DOWN);mPath.moveTo(event.getX(), event.getY());lastX = event.getX();lastY = event.getY();long[] time = new long[2];time[0] = System.currentTimeMillis();mPathStartEndTime.put(mPathIndex, time);break;case MotionEvent.ACTION_MOVE:float tx = (lastX + event.getX()) / 2;float ty = (lastY + event.getY()) / 2;mPath.quadTo(lastX, lastY, tx, ty);lastX = event.getX();lastY = event.getY();break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:Log.i(TAG, "onTouchEvent: 当前path count is " + getPathCount(mPath));long[] t = mPathStartEndTime.get(mPathIndex);if (t != null && t.length == 2) {t[1] = System.currentTimeMillis();} else {Log.i(TAG, "onTouchEvent: data error!!!");}mPathIndex++;Log.i(TAG, "onTouchEvent: 当前path count is " + mPathIndex);break;}invalidate();return true;
}

通过触摸事件,将手势轨迹记录到path中。 在移动的过程中,使用的是path二阶贝塞尔曲线,防止轨迹过于生硬的问题。 然后通过invalidate触发绘制,将path绘制到画布上。

其次,实现写字过程的回放。
由于要模拟每个笔画的时长和停顿,在上面的触摸事件中记录了每个path轮廓的开始和结束时间,用于构建回放动画。
在这里使用的数据结构是 SparseArray。它是专为android设备设计的数据结构,可以节省内存,与hashmap有点类似,但它只能存储以int为key的键值对。

在这里定义了一个成员变量 mPathIndex 用来标识每个path轮廓,并以此用作key来记录轮廓的开始和结束时间。
显示回放时,先根据path轮廓时长信息构建相应的动画,如下:

/*** 获取每个笔画的动画* @return*/
private List<Animator> getAnimatorList() {long[] duration = new long[mPathIndex];long[] startOffset = new long[mPathIndex];// 计算每个轮廓的书写时长for (int i = 0; i < mPathIndex; i++) {long[] t = mPathStartEndTime.get(i);duration[i] = t[1] - t[0];if (i > 0) {long[] prev = mPathStartEndTime.get(i - 1);// 计算每个轮廓与前一个轮廓的间隔时间startOffset[i] = t[0] - prev[1];}}List<Animator> animatorList = new ArrayList<>();for (int i = 0; i < mPathIndex; i++) {animatorList.add(createAnimator(duration[i], startOffset[i]));}return animatorList;
}

其中,创建动画的过程每个轮廓都类似,故单独写一个方法如下

/*** 根据每个笔画时间和偏移来构建动画* @param duration* @param startOffset 与上一个动画的偏移* @return*/
private Animator createAnimator(long duration, long startOffset) {ValueAnimator va = ValueAnimator.ofFloat(0.f, 1.0f);va.setDuration(duration).setStartDelay(startOffset);va.addUpdateListener(animation -> {Log.i(TAG, "showResultPath: " + animation.getAnimatedFraction());float curVal = (float) animation.getAnimatedValue();mPathMeasure.getSegment(0, curVal * mPathMeasure.getLength(), mDstPath, true);invalidate();});va.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation);// 每次结束后跳到下一个轮廓上mPathMeasure.nextContour();}});return va;
}

需要注意的是,每个动画完成时需要将动画跳转到下一个轮廓上。
得到了所有的动画后,就可以开始播放了。这里使用的是AnimatorSet,由于每个动画的 setStartDelay 时间都是相对上一个动画的。
故需要使用 AnimatorSet 的 playSequentially 方法。 具体代码如下:

/*** 显示字迹动画*/
public void showResultPath() {// 如果path有变动,那么 mPathMeasure 需要重新调用setPath绑定一下。 mPathMeasure.setPath(mPath, false);mShowResult = true;mDstPath.reset();List<Animator> animatorList = getAnimatorList();AnimatorSet set = new AnimatorSet();// 依次播放。 set.playSequentially(animatorList);set.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationRepeat(Animator animation) {super.onAnimationRepeat(animation);}});set.start();
}

调用showResultPath就可以显示书写的轨迹了。 具体绘制的代码比较简单,如下:

@Override
protected void onDraw(Canvas canvas) {super.onDraw(canvas);if (!mShowResult) {canvas.drawPath(mPath, mPaint);} else {canvas.drawPath(mDstPath, mPaint);}
}

其中,使用一个 mShowResult 变量来控制显示书写的回放。

注意事项:
1、 Path 可以由多条曲线构成,但不论是 getLength()、 getSegment()还是其他函数, 都只会针对其中第一条线段进行计算。 而 nextContour()就是用于跳转到下一条曲线的函数。 如果跳转成功, 则返回 true;如果跳转失败, 则返回 false。
2、pathmeausre 被关联的Path必须是已经创建好的,如果关联之后Path内容进行了更改,则需要使用setPath方法重新关联。
3、在默认情况下,path会生成连贯的路径。但调用moveTo() 与addXXX类函数除外。
4、如果需要计算path的轮廓数,可以通过如下代码实现。

 /**
* 获取path中的轮廓数
* @param path
* @return
*/
private int getPathCount(Path path) {// Path copy = new Path(path);PathMeasure m = new PathMeasure(path, false);int count = 0;while (m.nextContour()) {count++;}return count;
}

在使用这种方法计算的时候在注意,nextContour会将path移动到最后一个轮廓上。 如果继续使用path,可能会造成绘制的问题。 最好是copy一个path来计算。

5、直接调用 mPathMeasure.nextContour ()会跳到第一条线段,但如果操作了mPathMeasure,如getLength,它会自动跳到第一条线段。

参考及源码:
1、pathmeasure的用法。
2、源码。

android 自定义view仿支付宝写五褔及播放相关推荐

  1. Android仿支付宝UI功能开发,Android 自定义view仿支付宝咻一咻功能

    支付宝上有一个咻一咻的功能,就是点击图片后四周有水波纹的这种效果,今天也写一个类似的功能. 效果如下所示: 思路: 就是几个圆的半径不断在变大,这个可以使用动画缩放实现,还有透明动画 还有就是这是好几 ...

  2. android wear支付宝6,Android自定义View仿支付宝输入六位密码功能

    跟选择银行卡界面类似,也是用一个PopupWindow,不过输入密码界面是一个自定义view,当输入六位密码完成后用回调在Activity中获取到输入的密码并以Toast显示密码.效果图如下: 自定义 ...

  3. android自定义表盘部件,Android自定义view仿支付宝芝麻信用表盘

    演示效果 实现步骤: 1.画不同宽度和半径的内外圆弧 2.通过循环旋转canvas,在固定位置绘制短线刻度,长线刻度,刻度文字 3.绘制view中心几个文本,并调整位置 4.实时更新当前旋转角度刷新小 ...

  4. android 自定义中文加盘,Android自定义View仿支付宝芝麻信用分仪表盘

    先看下iOS的芝麻信用分截图 这是我做的效果,还是有点差距的 支付宝9.9版本芝麻信用分的实现 首先初始化各种画笔,默认的size,padding,小圆点. (因为实在找不到原版芝麻信用的带点模糊效果 ...

  5. android 高仿 探探卡片滑动,Android自定义View仿探探卡片滑动效果

    Android自定义View仿探探卡片滑动这种效果网上有很多人已经讲解了实现思路,大多都用的是RecyclerView来实现的,但是我们今天来换一种实现思路,只用一个自定义的ViewGroup来搞定这 ...

  6. android的动态tab,Android自定义view仿QQ的Tab按钮动画效果(示例代码)

    话不多说 先上效果图 实现其实很简单,先用两张图 一张是背景的图,一张是笑脸的图片,笑脸的图片是白色,可能看不出来.实现思路:主要是再触摸view的时候同时移动这两个图片,但是移动的距离不一样,造成的 ...

  7. Android自定义View——仿ViVO X6 极速闪充动画效果

    一直都在看自定义View,经过一个星期的坚持,基本上能够写出一些比较实用的控件效果了,今天天气太热,就待在家里玩手机,然后手机没电了,在充电的时候,看到了手机的充电动画,觉得挺酷,然后自己我就仔细的分 ...

  8. oracle number型步数,Android自定义View仿QQ计步器

    自定义计步器 Android自定义View是Android开发中比较重要的一项,也是很多开发者比较怕的一个东西.其实只要认真去学习,自定义View其实没有那么可怕:相反的,我们还能从自定义View中找 ...

  9. android记账本折线图_Android自定义View - 仿支付宝月账单折线图

    前言 支付宝有个查看月账单的功能,最近一直在学习自定义View,于是就尝试着自己实现了一个类似的折线图. 下面是支付宝消费分析功能截图和自己实现的折线效果截图: 支付宝消费分析折线图.jpg 效果1. ...

最新文章

  1. android连接mysql查询表内记录_Android Room数据库多表查询的使用实例
  2. WebForm连接数据库实例
  3. linux操作系统之线程
  4. 新自然指数出炉,哪些高校表现突出?
  5. Java基础篇1——变量与数据类型
  6. word怎么调列宽_怎么给文件加密???
  7. Eureka获取注册信息
  8. NSNotificationCenter详解
  9. POJ 2923 Relocation ★(状态压缩+01背包)
  10. 涉密计算机终端安全防护,终端安全登录与文件保护系统保密认证设备
  11. [GW-CTF2019] babyvm
  12. HTML图片动画特效
  13. 卡贴机变无锁教程_有锁机变无锁教程 教你轻松设置去掉卡贴有锁机变无锁完美4G...
  14. Windows10系统 ADMUI3无法删除
  15. Axis1.4 远程命令执行(CVE-2019-0227)复现
  16. Android仿微信气泡聊天界面设计
  17. 战区与游戏服务器的连线已中断,使命召唤战区无法连接服务器如何解决?无法连接服务器解决方法介绍[多图]...
  18. 漫步者lollipods如何调节音量_漫步者LolliPods怎么配对双耳?如何切换单耳和双耳模式...
  19. 从零学习PyTorch(5)----整个天空都是灰蒙蒙的
  20. 永浆草莓采摘永安踏春好去处

热门文章

  1. 一文讲透低代码平台的商业模式
  2. 大四毕业生想要找实习程序员工作 ,我总结了三点分享给大家
  3. 梦幻仙缘剧情java_梦幻仙缘红包版
  4. 插画培训班学费一般是多少钱
  5. 合宙Air724UG Cat1(4G)CSDK 二次开发总结(DNS TCP)
  6. 合宙ESP32-C3精简版完全食用指南
  7. 华为SmartAX MA5620配置当交换机使用
  8. 全民小视频视频搬运伪原创
  9. 塔防游戏.BloonsTD5简评
  10. android p 华为p10,华为P10测评:市场上真心没有比华为更强劲的安卓机了