Android中模仿抖音加載框之兩顆小球轉動效果
安卓版抖音v2.5加載框:
效果圖如下所示:

本控件效果圖:

使用方法
1、xml引用:
<com.douyinloadingview.DYLoadingView android:id="@+id/dy3" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#000000" app:color1="#FF00EEEE" app:color2="#FFFF4040" app:....(其他可選屬性) />
2、java使用:
@BindView(R.id.dy1)
DYLoadingView dy1;
@OnClick(R.id.b1)
void start() {
dy1.setXXXXX; //設置屬性(可選)
dy1.start(); //開始動畫
}
@OnClick(R.id.b2)
void stop() {
dy1.stop(); //停止動畫
}
就醬。
可用屬性
| 名稱 | 對應xml屬性 | 對應java方法 | 默認值 |
|---|---|---|---|
| 球1半徑 | radius1 | setRadius() | 6dp |
| 球2半徑 | radius2 | setRadius() | 6dp |
| 兩球間隔 | gap | setRadius() | 0.8dp |
| 球1顏色 | color1 | setColors() | 0XFFFF4040 |
| 球2顏色 | color2 | setColors() | 0XFF00EEEE |
| 疊加色 | mixColor | setColors() | 0XFF000000 |
| 從右往左移動時小球最大縮放倍數(shù) | rtlScale | setScales() | 0.7f |
| 從左往右移動時小球最大縮放倍數(shù) | ltrScale | setScales() | 1.3f |
| 一次移動動畫時長 | duration | setDuration() | 350ms |
| 一次移動動畫后停頓時長 | pauseDuration | setDuration() | 80ms |
| 動畫進度在[0,scaleStartFraction]期間,小球大小逐漸縮放 | scaleStartFraction | setStartEndFraction() | 0.2f |
| 動畫進度在[scaleEndFraction,1]期間,小球大小逐漸恢復 | scaleEndFraction | setStartEndFraction() | 0.8f |
(rtl = right to left, ltr = left to right)
部分屬性說明:
•color格式為32位ARGB
•scaleStartFraction范圍[0,0.5];scaleEndFraction范圍[0.5,1]
•假設ltrScale = 1.3,scaleStartFraction = 0.2,scaleEndFraction = 0.8;那么實際效果就是一顆小球從左邊開始向右移動
期間,進度在0%~20%時半徑逐漸從1倍放大到1.3倍,在20%~80%期間大小保持1.3倍,在80%~100%時半徑逐漸從1.3倍恢復至1倍
實現(xiàn)思路
要讓小球動,當然要有一個動畫,通過動畫來獲得一個進度百分比fraction,然后小球在動畫過程中的坐標、大小就可以通過這個值來計算:
private void initAnim() {
fraction = 0.0f;
stop();
anim = ValueAnimator.ofFloat(0.0f, 1.0f);
anim.setDuration(duration);
if (pauseDuration > 0) {
anim.setStartDelay(pauseDuration);
anim.setInterpolator(new AccelerateDecelerateInterpolator());
} else {
anim.setRepeatCount(ValueAnimator.INFINITE);
anim.setRepeatMode(ValueAnimator.RESTART);
anim.setInterpolator(new LinearInterpolator());
}
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
fraction = animation.getAnimatedFraction();
invalidate();
}
});
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
isLtr = !isLtr;
}
@Override
public void onAnimationRepeat(Animator animation) {
isLtr = !isLtr;
}
@Override
public void onAnimationCancel(Animator animation) {
isAnimCanceled = true;
}
@Override
public void onAnimationEnd(Animator animation) {
if (!isAnimCanceled) {
anim.start();
}
}
});
}
代碼中看到,如果小球一次移動后不需要停頓(pauseDuration = 0),那么直接通過anim.setRepeatCount(ValueAnimator.INFINITE)讓動畫無限循環(huán),否則的話就要通過anim.setStartDelay(pauseDuration)來設置停頓時間,然后在監(jiān)聽的onAnimationEnd里重啟動畫,以此實現(xiàn)每一次移動后小球能停頓一定時間。在onAnimationUpdate里,我們記錄了當前動畫百分比fraction,然后通過invalidate()重繪,在之后的onDraw里將通過該值畫出小球。另外,每次動畫開始時(或是重復時),會將isLtr取反,這個標志位的作用是標明當前哪顆球在【從左往右】移動,因為兩顆球的顏色、初始半徑是不一樣的嘛,onDraw里畫小球時是需要這個標志位協(xié)助的。
有了動畫進度fraction和標志位isLtr后,就可以在onDraw里畫出小球了。
**首先要計算小球當前的坐標**。y坐標永遠是固定的,不談,x坐標隨著`fraction`的變化而變化。兩顆球之間最遠距離為球1半徑+球2半徑+兩球間隔,即`distance = gap + radius1 + radius2;`,這個值就是兩顆球的移動范圍,由此可計算出,當前【從左往右】移動的小球的x坐標和當前【從右往左】移動的小球x坐標分別為:
float ltrX = getMeasuredWidth() / 2.0f - distance / 2.0f; ltrX = ltrX + (distance * fraction); float rtlX = getMeasuredWidth() / 2.0f + distance / 2.0f; rtlX = rtlX - (distance * fraction);
**接下來要計算小球當前的大小**。小球的大小也是隨著動畫進度變化的,上面已經(jīng)說明了`scaleStartFraction`和`scaleEndFraction`屬性的含義。 以當前小球【從左往右】移動為例,當動畫進度為0時,小球大小為初始1倍大??;當動畫進度到scaleStartFraction時,小球大小將縮放到`ltrScale`倍,當動畫進度為[scaleStartFraction,scaleEndFraction]范圍時,小球大小保持`ltrScale`倍,當動畫進度到[scaleEndFraction,1]范圍時,小球則從`ltrScale`倍逐漸恢復至1倍。 為了便于計算,首先將`[0,scaleStartFraction]`轉換為`[0,1.0]`的真實百分比,根據(jù)`y = kx + b`(就這么個入門公式。。我都要在紙上算一遍T-T),可以得出:`float scaleFraction = 1.0f / scaleStartFraction * fraction; `,有了這個真實百分比,那么該區(qū)間里小球當前半徑就好計算了:
ltrBallRadius = ltrInitRadius * (1 + (ltrScale - 1) * scaleFraction); rtlBallRadius = rtlInitRadius * (1 + (rtlScale - 1) * scaleFraction);
應該好懂的吧。另外[scaleEndFraction,1]區(qū)間里小球當前半徑計算思路是一樣的,不談。
最后就是要畫出小球。這里主要是如何畫出實現(xiàn)兩球疊加的部分的顏色。
思路1:通過xfermode方式實現(xiàn):

從上圖可以看出用Darken、Lighten、Screen模式可以做到讓疊加處上色,但是顏色不能自定義。
思路2:通過path的OP操作實現(xiàn)(API19):

(圖片摘自http://www.gcssloop.com/customview/Path_Over)
因此,可以先構造兩個小球的Path,然后再將這兩個Path進行INTERSECT操作,即可獲得疊加處的Path,這樣就可以做到自定義疊加處的顏色了。
onDraw完整代碼:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float centerY = getMeasuredHeight() / 2.0f;
float ltrInitRadius, rtlInitRadius;
Paint ltrPaint, rtlPaint;
//確定當前【從左往右】移動的是哪顆小球
if (isLtr) {
ltrInitRadius = radius1;
rtlInitRadius = radius2;
ltrPaint = paint1;
rtlPaint = paint2;
} else {
ltrInitRadius = radius2;
rtlInitRadius = radius1;
ltrPaint = paint2;
rtlPaint = paint1;
}
float ltrX = getMeasuredWidth() / 2.0f - distance / 2.0f;
ltrX = ltrX + (distance * fraction);//當前從左往右的球的X坐標
float rtlX = getMeasuredWidth() / 2.0f + distance / 2.0f;
rtlX = rtlX - (distance * fraction);//當前從右往左的球的X坐標
//計算小球移動過程中的大小變化
float ltrBallRadius, rtlBallRadius;
if (fraction <= scaleStartFraction) { //動畫進度[0,scaleStartFraction]時,球大小由1倍逐漸縮放至ltrScale/rtlScale倍
float scaleFraction = 1.0f / scaleStartFraction * fraction; //百分比轉換 [0,scaleStartFraction]] -> [0,1]
ltrBallRadius = ltrInitRadius * (1 + (ltrScale - 1) * scaleFraction);
rtlBallRadius = rtlInitRadius * (1 + (rtlScale - 1) * scaleFraction);
} else if (fraction >= scaleEndFraction) { //動畫進度[scaleEndFraction,1],球大小由ltrScale/rtlScale倍逐漸恢復至1倍
float scaleFraction = (fraction - 1) / (scaleEndFraction - 1); //百分比轉換,[scaleEndFraction,1] -> [1,0]
ltrBallRadius = ltrInitRadius * (1 + (ltrScale - 1) * scaleFraction);
rtlBallRadius = rtlInitRadius * (1 + (rtlScale - 1) * scaleFraction);
} else { //動畫進度[scaleStartFraction,scaleEndFraction],球保持縮放后的大小
ltrBallRadius = ltrInitRadius * ltrScale;
rtlBallRadius = rtlInitRadius * rtlScale;
}
ltrPath.reset();
ltrPath.addCircle(ltrX, centerY, ltrBallRadius, Path.Direction.CW);
rtlPath.reset();
rtlPath.addCircle(rtlX, centerY, rtlBallRadius, Path.Direction.CW);
mixPath.op(ltrPath, rtlPath, Path.Op.INTERSECT);
canvas.drawPath(ltrPath, ltrPaint);
canvas.drawPath(rtlPath, rtlPaint);
canvas.drawPath(mixPath, mixPaint);
}
總結
以上所述是小編給大家介紹的Android中模仿抖音加載框之兩顆小球轉動控件效果,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關文章
Android Flutter實戰(zhàn)之為照片添加顏色濾鏡
這篇文章我們將利用TweenAnimationBuilder來實現(xiàn)一個圖片調色的過渡動畫,從而實現(xiàn)為照片添加顏色濾鏡的效果,感興趣的可以了解一下2022-12-12
解決Eclipse啟動出錯:Failed to create the Java Virtual Machine
這篇文章主要介紹了解決Eclipse啟動出錯:Failed to create the Java Virtual Machine的相關資料,這里說明出錯原因及查找錯誤和解決辦法,需要的朋友可以參考下2017-07-07
使用RecyclerView實現(xiàn)Item點擊事件
這篇文章主要介紹了使用RecyclerView實現(xiàn)Item點擊事件,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08
Android Studio 安裝配置方法完整教程【小白秒懂】
這篇文章主要介紹了Android Studio 安裝配置方法完整教程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2020-03-03

