Android中怎么實(shí)現(xiàn)兩顆小球轉(zhuǎn)動(dòng)效果

今天小編給大家分享一下Android中怎么實(shí)現(xiàn)兩顆小球轉(zhuǎn)動(dòng)效果的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來(lái)了解一下吧。

創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司一直秉承“誠(chéng)信做人,踏實(shí)做事”的原則,不欺瞞客戶,是我們最起碼的底線! 以服務(wù)為基礎(chǔ),以質(zhì)量求生存,以技術(shù)求發(fā)展,成交一個(gè)客戶多一個(gè)朋友!專注中小微企業(yè)官網(wǎng)定制,成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè),塑造企業(yè)網(wǎng)絡(luò)形象打造互聯(lián)網(wǎng)企業(yè)效應(yīng)。

效果圖如下所示:

Android中怎么實(shí)現(xiàn)兩顆小球轉(zhuǎn)動(dòng)效果

本控件效果圖:

Android中怎么實(shí)現(xiàn)兩顆小球轉(zhuǎn)動(dòng)效果

使用方法

源碼地址:Android仿抖音加載框之兩顆小球轉(zhuǎn)動(dòng)控件

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; //設(shè)置屬性(可選)
 dy1.start(); //開(kāi)始動(dòng)畫(huà)
 }
 @OnClick(R.id.b2)
 void stop() {
 dy1.stop(); //停止動(dòng)畫(huà)
 }

就醬。

可用屬性

名稱對(duì)應(yīng)xml屬性對(duì)應(yīng)java方法默認(rèn)值
球1半徑radius1setRadius()6dp
球2半徑radius2setRadius()6dp
兩球間隔gapsetRadius()0.8dp
球1顏色color1setColors()0XFFFF4040
球2顏色color2setColors()0XFF00EEEE
疊加色mixColorsetColors()0XFF000000
從右往左移動(dòng)時(shí)小球最大縮放倍數(shù)rtlScalesetScales()0.7f
從左往右移動(dòng)時(shí)小球最大縮放倍數(shù)ltrScalesetScales()1.3f
一次移動(dòng)動(dòng)畫(huà)時(shí)長(zhǎng)durationsetDuration()350ms
一次移動(dòng)動(dòng)畫(huà)后停頓時(shí)長(zhǎng)pauseDurationsetDuration()80ms
動(dòng)畫(huà)進(jìn)度在[0,scaleStartFraction]期間,小球大小逐漸縮放scaleStartFractionsetStartEndFraction()0.2f
動(dòng)畫(huà)進(jìn)度在[scaleEndFraction,1]期間,小球大小逐漸恢復(fù)scaleEndFractionsetStartEndFraction()0.8f

(rtl = right to left, ltr = left to right)

部分屬性說(shuō)明:

?color格式為32位ARGB
?scaleStartFraction范圍[0,0.5];scaleEndFraction范圍[0.5,1]
?假設(shè)ltrScale = 1.3,scaleStartFraction = 0.2,scaleEndFraction = 0.8;那么實(shí)際效果就是一顆小球從左邊開(kāi)始向右移動(dòng)

期間,進(jìn)度在0%~20%時(shí)半徑逐漸從1倍放大到1.3倍,在20%~80%期間大小保持1.3倍,在80%~100%時(shí)半徑逐漸從1.3倍恢復(fù)至1倍

實(shí)現(xiàn)思路

要讓小球動(dòng),當(dāng)然要有一個(gè)動(dòng)畫(huà),通過(guò)動(dòng)畫(huà)來(lái)獲得一個(gè)進(jìn)度百分比f(wàn)raction,然后小球在動(dòng)畫(huà)過(guò)程中的坐標(biāo)、大小就可以通過(guò)這個(gè)值來(lái)計(jì)算:

 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();
  }
  }
 });
 }

代碼中看到,如果小球一次移動(dòng)后不需要停頓(pauseDuration = 0),那么直接通過(guò)anim.setRepeatCount(ValueAnimator.INFINITE)讓動(dòng)畫(huà)無(wú)限循環(huán),否則的話就要通過(guò)anim.setStartDelay(pauseDuration)來(lái)設(shè)置停頓時(shí)間,然后在監(jiān)聽(tīng)的onAnimationEnd里重啟動(dòng)畫(huà),以此實(shí)現(xiàn)每一次移動(dòng)后小球能停頓一定時(shí)間。在onAnimationUpdate里,我們記錄了當(dāng)前動(dòng)畫(huà)百分比f(wàn)raction,然后通過(guò)invalidate()重繪,在之后的onDraw里將通過(guò)該值畫(huà)出小球。另外,每次動(dòng)畫(huà)開(kāi)始時(shí)(或是重復(fù)時(shí)),會(huì)將isLtr取反,這個(gè)標(biāo)志位的作用是標(biāo)明當(dāng)前哪顆球在【從左往右】移動(dòng),因?yàn)閮深w球的顏色、初始半徑是不一樣的嘛,onDraw里畫(huà)小球時(shí)是需要這個(gè)標(biāo)志位協(xié)助的。

有了動(dòng)畫(huà)進(jìn)度f(wàn)raction和標(biāo)志位isLtr后,就可以在onDraw里畫(huà)出小球了。

**首先要計(jì)算小球當(dāng)前的坐標(biāo)**。y坐標(biāo)永遠(yuǎn)是固定的,不談,x坐標(biāo)隨著`fraction`的變化而變化。兩顆球之間最遠(yuǎn)距離為球1半徑+球2半徑+兩球間隔,即`distance = gap + radius1 + radius2;`,這個(gè)值就是兩顆球的移動(dòng)范圍,由此可計(jì)算出,當(dāng)前【從左往右】移動(dòng)的小球的x坐標(biāo)和當(dāng)前【從右往左】移動(dòng)的小球x坐標(biāo)分別為:

float ltrX = getMeasuredWidth() / 2.0f - distance / 2.0f;
ltrX = ltrX + (distance * fraction);
float rtlX = getMeasuredWidth() / 2.0f + distance / 2.0f;
rtlX = rtlX - (distance * fraction);

**接下來(lái)要計(jì)算小球當(dāng)前的大小**。小球的大小也是隨著動(dòng)畫(huà)進(jìn)度變化的,上面已經(jīng)說(shuō)明了`scaleStartFraction`和`scaleEndFraction`屬性的含義。 以當(dāng)前小球【從左往右】移動(dòng)為例,當(dāng)動(dòng)畫(huà)進(jìn)度為0時(shí),小球大小為初始1倍大小;當(dāng)動(dòng)畫(huà)進(jìn)度到scaleStartFraction時(shí),小球大小將縮放到`ltrScale`倍,當(dāng)動(dòng)畫(huà)進(jìn)度為[scaleStartFraction,scaleEndFraction]范圍時(shí),小球大小保持`ltrScale`倍,當(dāng)動(dòng)畫(huà)進(jìn)度到[scaleEndFraction,1]范圍時(shí),小球則從`ltrScale`倍逐漸恢復(fù)至1倍。 為了便于計(jì)算,首先將`[0,scaleStartFraction]`轉(zhuǎn)換為`[0,1.0]`的真實(shí)百分比,根據(jù)`y = kx + b`(就這么個(gè)入門公式。。我都要在紙上算一遍T-T),可以得出:`float scaleFraction = 1.0f / scaleStartFraction * fraction; `,有了這個(gè)真實(shí)百分比,那么該區(qū)間里小球當(dāng)前半徑就好計(jì)算了:

ltrBallRadius = ltrInitRadius * (1 + (ltrScale - 1) * scaleFraction);
rtlBallRadius = rtlInitRadius * (1 + (rtlScale - 1) * scaleFraction);

應(yīng)該好懂的吧。另外[scaleEndFraction,1]區(qū)間里小球當(dāng)前半徑計(jì)算思路是一樣的,不談。

最后就是要畫(huà)出小球。這里主要是如何畫(huà)出實(shí)現(xiàn)兩球疊加的部分的顏色。

 思路1:通過(guò)xfermode方式實(shí)現(xiàn):

Android中怎么實(shí)現(xiàn)兩顆小球轉(zhuǎn)動(dòng)效果

從上圖可以看出用Darken、Lighten、Screen模式可以做到讓疊加處上色,但是顏色不能自定義。

 思路2:通過(guò)path的OP操作實(shí)現(xiàn)(API19):

Android中怎么實(shí)現(xiàn)兩顆小球轉(zhuǎn)動(dòng)效果

(圖片摘自http://www.gcssloop.com/customview/Path_Over)

 因此,可以先構(gòu)造兩個(gè)小球的Path,然后再將這兩個(gè)Path進(jìn)行INTERSECT操作,即可獲得疊加處的Path,這樣就可以做到自定義疊加處的顏色了。

onDraw完整代碼:

@Override
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 float centerY = getMeasuredHeight() / 2.0f;
 float ltrInitRadius, rtlInitRadius;
 Paint ltrPaint, rtlPaint;
 //確定當(dāng)前【從左往右】移動(dòng)的是哪顆小球
 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);//當(dāng)前從左往右的球的X坐標(biāo)
 float rtlX = getMeasuredWidth() / 2.0f + distance / 2.0f;
 rtlX = rtlX - (distance * fraction);//當(dāng)前從右往左的球的X坐標(biāo)
 //計(jì)算小球移動(dòng)過(guò)程中的大小變化
 float ltrBallRadius, rtlBallRadius;
 if (fraction <= scaleStartFraction) { //動(dòng)畫(huà)進(jìn)度[0,scaleStartFraction]時(shí),球大小由1倍逐漸縮放至ltrScale/rtlScale倍
  float scaleFraction = 1.0f / scaleStartFraction * fraction; //百分比轉(zhuǎn)換 [0,scaleStartFraction]] -> [0,1]
  ltrBallRadius = ltrInitRadius * (1 + (ltrScale - 1) * scaleFraction);
  rtlBallRadius = rtlInitRadius * (1 + (rtlScale - 1) * scaleFraction);
 } else if (fraction >= scaleEndFraction) { //動(dòng)畫(huà)進(jìn)度[scaleEndFraction,1],球大小由ltrScale/rtlScale倍逐漸恢復(fù)至1倍
  float scaleFraction = (fraction - 1) / (scaleEndFraction - 1); //百分比轉(zhuǎn)換,[scaleEndFraction,1] -> [1,0]
  ltrBallRadius = ltrInitRadius * (1 + (ltrScale - 1) * scaleFraction);
  rtlBallRadius = rtlInitRadius * (1 + (rtlScale - 1) * scaleFraction);
 } else { //動(dòng)畫(huà)進(jìn)度[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中怎么實(shí)現(xiàn)兩顆小球轉(zhuǎn)動(dòng)效果”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

網(wǎng)站題目:Android中怎么實(shí)現(xiàn)兩顆小球轉(zhuǎn)動(dòng)效果
網(wǎng)頁(yè)地址:http://muchs.cn/article44/ipjche.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站、云服務(wù)器、品牌網(wǎng)站設(shè)計(jì)、網(wǎng)站設(shè)計(jì)動(dòng)態(tài)網(wǎng)站、用戶體驗(yàn)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

小程序開(kāi)發(fā)