Android 心率動畫自定義控件實(shí)現(xiàn)
Android 心率動畫自定義控件實(shí)現(xiàn)
wild_eagle_
個人博文,此公眾號作為 https://www.chenwenguan.com/ 博客內(nèi)容的同步,只有自由行游記單獨(dú)發(fā)在公眾號。
Android心率曲線平移動畫自定義控件實(shí)現(xiàn)詳解,并附上GitHub完整實(shí)現(xiàn)倉庫資源。
項目上需要實(shí)現(xiàn)一個心率曲線波動的自定義動畫,網(wǎng)上找了很多開源控件,沒有想要的效果,綜合網(wǎng)上已有的實(shí)現(xiàn),改造實(shí)現(xiàn)了一個比較簡單的心率波動動畫,以下是實(shí)現(xiàn)的動畫效果GIF,實(shí)際運(yùn)行會平滑很多。
一、實(shí)現(xiàn)原理詳解
1. 心率曲線的繪制
如果是繪制折線,只需要把數(shù)據(jù)點(diǎn)使用Path對象lineTo方法把所有數(shù)據(jù)點(diǎn)連接繪制即可,繪制曲線則使用cubicTo方法繪制貝塞爾曲線,讓曲線連接點(diǎn)更平滑。每次繪制前重置Path對象,所有數(shù)據(jù)點(diǎn)連接完畢之后即可刷新繪制。
private
void generateNewPath(float offset) {
mPath.reset();
for
(int i = 0; i < mSourceData.size(); i++) {
//
x,y表示當(dāng)前點(diǎn) x4,y4表示下一個點(diǎn) x2,x3都是屬于中間的點(diǎn)
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. 平移動畫實(shí)現(xiàn)
在曲線還沒超過繪制控件寬度的時候,逐個繪制數(shù)據(jù)點(diǎn)連線,當(dāng)數(shù)據(jù)點(diǎn)超過控件寬度的時候,才進(jìn)行從右往左的X軸平移動畫。這邊平移的動畫使用屬性動畫的刷新,來更新曲線每個數(shù)據(jù)點(diǎn)的X軸坐標(biāo)來實(shí)現(xiàn)。
這邊需要注意的是:屬性函數(shù)回調(diào)參數(shù)的類型不能寫成Float,而是float,否則會導(dǎo)致setShiftXRatio沒執(zhí)行。
ObjectAnimator.ofFloat(
this
,
"shiftXRatio"
,
0f
,
1f
);
/**
* setShiftXRatio
*
* @param shiftRatio float
*/
public
void
setShiftXRatio
(
float
shiftRatio
)
{
invalidatePath(mHearRateItemMargin * shiftRatio);
}
同時設(shè)置屬性動畫為無限循環(huán),如果是配置屬性動畫只執(zhí)行一次,每新增一個數(shù)據(jù)點(diǎn)再啟動屬性動畫,會有大概一秒的延遲,導(dǎo)致實(shí)現(xiàn)的動畫效果不平滑,會有明顯的頓挫。
setRepeatCount
(
ValueAnimator
.INFINITE
)
在屬性動畫的執(zhí)行監(jiān)聽中,用onAnimationRepeat接口來觸發(fā)下一個數(shù)據(jù)點(diǎn)的平移動畫執(zhí)行,設(shè)置屬性動畫為無限循環(huán)之后,監(jiān)聽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. 渲染問題導(dǎo)致繪制異常
在MUMU虛擬機(jī)上運(yùn)行動畫,測試了幾分鐘之后繪制不出來畫面,報以下異常信息:
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 (
16391
x514,
max
=
16384
x16384)
在布局控件中配置software屬性解決。
android:layerType=
"software"
二、GitHub倉庫鏈接地址
https://github.com/wenguan0927/HeartRateAnimView
三、其他心率動畫開源資源參考
Snake View( https://github.com/txusballesteros/snake ) 也是心率動畫,只是動畫是蛇形變化。
LuckyEcgDemo ( https://github.com/SeekerFighter/LuckyEcgDemo ) 心電圖表格自定義控件實(shí)現(xiàn),正式的醫(yī)院心電圖效果。
擴(kuò)展閱讀:
美圖手機(jī)音樂Widget動畫實(shí)現(xiàn)
公眾號文章不支持外鏈,點(diǎn)擊【閱讀原文】可直接訪問,網(wǎng)站博客會不定時更新補(bǔ)充內(nèi)容。
-
2023年各省最新電價一覽!8省中午執(zhí)行谷段電價! 2023-01-03
-
PPT導(dǎo)出高分辨率圖片的四種方法 2022-09-22
-
全國消防救援總隊主官及簡歷(2023.2) 2023-02-10
-
盤點(diǎn) l 中國石油大慶油田現(xiàn)任領(lǐng)導(dǎo)班子 2023-02-28
-
我們的前輩!歷屆全國工程勘察設(shè)計大師完整名單! 2022-11-18
-
關(guān)于某送變電公司“4·22”人身死亡事故的快報 2022-04-26
