• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

陈文管的博客

分享有价值的内容

  • Android
  • Affiliate
  • SEO
  • 前后端
  • 网站建设
  • 自动化
  • 开发资源
  • 关于

Android 心率动画自定义控件实现

2023年2月9日发布 | 最近更新于 2023年8月28日

Android心率曲线平移动画自定义控件实现详解,并附上GitHub完整实现仓库资源。

项目上需要实现一个心率曲线波动的自定义动画,网上找了很多开源控件,没有想要的效果,综合网上已有的实现,改造实现了一个比较简单的心率波动动画,每个点之间用贝塞尔曲线连接,从左到右逐个绘制,满屏之后开始平移心率波动动画,以下是实现效果截图,GitHub上有实现效果GIF。

Android自定义心率动画控件

一、实现原理详解

1. 心率曲线的绘制

如果是绘制折线,只需要把数据点使用Path对象lineTo方法把所有数据点连接绘制即可,绘制曲线则使用cubicTo方法绘制贝塞尔曲线,让曲线连接点更平滑。每次绘制前重置Path对象,所有数据点连接完毕之后即可刷新绘制。

private void generateNewPath(float offset) {
    mPath.reset();
    for (int i = 0; i < mSourceData.size(); i++) {
        // x,y表示当前点  x4,y4表示下一个点 x2,x3都是属于中间的点
        x = mMarginLeft + mHearRateItemMargin * i - offset;
        y = getHearRateValueToViewHeight(mSourceData.get(i));
        if (i == mSourceData.size() - 1) {
            x4 = x;
            y4 = y;
        } else {
            x4 = mMarginLeft + mHearRateItemMargin * (i + 1) - offset;
            y4 = getHearRateValueToViewHeight(mSourceData.get(i + 1));
        }
        x2 = x3 = (x + x4) / 2;
        y2 = y;
        y3 = y4;
        if (i == 0) {
            mPath.moveTo(x, y);
            mPath.lineTo(x, y);
        }
        if (i != mSourceData.size() - 1) {
            mPath.cubicTo(x2, y2, x3, y3, x4, y4);
        }
    }
}

2. 平移动画实现

在曲线还没超过绘制控件宽度的时候,逐个绘制数据点连线,当数据点超过控件宽度的时候,才进行从右往左的X轴平移动画。这边平移的动画使用属性动画的刷新,来更新曲线每个数据点的X轴坐标来实现。

这边需要注意的是:属性函数回调参数的类型不能写成Float,而是float,否则会导致setShiftXRatio没执行,放置自定义控件的地方也要加防混淆处理,混淆之后会导致找不到回调函数。

ObjectAnimator.ofFloat(this, "shiftXRatio", 0f, 1f);
/**
 * setShiftXRatio
 *
 * @param shiftRatio float
 */
public void setShiftXRatio(float shiftRatio) {
    invalidatePath(mHearRateItemMargin * shiftRatio);
}

同时设置属性动画为无限循环,如果是配置属性动画只执行一次,每新增一个数据点再启动属性动画,会有大概一秒的延迟,导致实现的动画效果不平滑,会有明显的顿挫。

setRepeatCount(ValueAnimator.INFINITE)

在属性动画的执行监听中,用onAnimationRepeat接口来触发下一个数据点的平移动画执行,设置属性动画为无限循环之后,监听onAnimationRepeat接口而不是onAnimationEnd接口。

private Animator.AnimatorListener mAnimListener = new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(@NonNull Animator animator) { }
    @Override
    public void onAnimationEnd(@NonNull Animator animator) { }
    @Override
    public void onAnimationCancel(@NonNull Animator animator) { }
    @Override
    public void onAnimationRepeat(@NonNull Animator animator) {
        startNextAnim();
    }
};

3. 渲染问题导致绘制异常

在MUMU虚拟机上运行动画,测试了几分钟之后绘制不出来画面,报以下异常信息:

E/EGL_emulation: tid 1442: eglSurfaceAttrib(1101): error 0x3009 (EGL_BAD_MATCH)
W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0x7f51eb168a40, error=EGL_BAD_MATCH 
W/OpenGLRenderer: Path too large to be rendered into a texture
W/OpenGLRenderer: Shape too large to be rendered into a texture (16391x514, max=16384x16384)

在布局控件中配置software属性解决。

android:layerType="software"

二、GitHub仓库链接地址

https://github.com/wenguan0927/HeartRateAnimView

三、其他心率动画开源资源参考

Snake View 也是心率动画,只是动画是蛇形变化。

LuckyEcgDemo 心电图表格自定义控件实现,正式的医院心电图效果。

扩展阅读:

美图手机音乐Widget动画实现

转载请注明出处:陈文管的博客 – Android 心率动画自定义控件实现

扫码或搜索:文呓

博客公众号

微信公众号 扫一扫关注

文章目录

  • 一、实现原理详解
    • 1. 心率曲线的绘制
    • 2. 平移动画实现
    • 3. 渲染问题导致绘制异常
  • 二、GitHub仓库链接地址
  • 三、其他心率动画开源资源参考
博客公众号

闽ICP备18001825号-1 · Copyright © 2025 · Powered by chenwenguan.com