Android模擬實現華為系統升級進度條
前言
之前用華為Android系統的時候總是會想到這種虛線進度條是怎麼實現的,因為直接用canvas的drawArc方法畫出來的是實線,所以最近在網上搜瞭很多進度條相關的文章,也瞭解到瞭其中的原理,下面分享給大傢。下面這兩篇文章是我之前寫的Android進度條相關的文章,有興趣的朋友們可以看看:
Android實現絢麗的自定義進度條
詳解Android如何自定義view實現圓形進度條
下面開始講解虛線進度條的實現方法,首先看一張圖:
實現步驟
大傢可以先想想這種進度條是怎麼實現的?網上有各種各樣的方法,也有人用path的lineTo()方法實現瞭類似的效果。但是我個人覺得canvas的drawArc方法也是個不錯的選擇,適合自己的才是最好的。
canvas.drawArc(rectF, 0, process, false, mPaint);
閱讀瞭大量文章,最後發現改變paint的樣式是最簡單好用的方法。給paint設置一個effect就好瞭。
1.用DashPathEffect給paint加上虛線效果
DashPathEffect dashPathEffect = new DashPathEffect(new float[]{8, 6}, 0); mPaintBack.setPathEffect(dashPathEffect);
build一下項目,看到的結果是這樣的:
能實現這個效果就大功告成瞭,如果看過我前面兩篇文章的朋友們就知道,後面的步驟就簡單瞭,加個進度條和動畫效果就可以瞭。
private void drawBack(Canvas canvas) { RectF rectF = new RectF(strokeWidth, strokeWidth, getWidth() - strokeWidth, getHeight() - strokeWidth); PathEffect effects = new DashPathEffect(new float[]{8, 6}, 0); mPaintBack.setPathEffect(effects); canvas.drawArc(rectF, 0, 360, false, mPaintBack); }
2.畫出進度條
畫進度條和畫背景完全一樣,隻是畫筆顏色和小點個數不一樣。
代碼如下:
private void drawProgress(Canvas canvas) { RectF rectF = new RectF(strokeWidth, strokeWidth, getWidth() - strokeWidth, getHeight() - strokeWidth); PathEffect effects = new DashPathEffect(new float[]{8, 6}, 0); mPaint.setPathEffect(effects); canvas.drawArc(rectF, 0, process, false, mPaint); }
3.繪制文字
接下來是繪制文字,實現文字居中的效果。思路是計算出圓心,調用canvas.drawText的方法就能在canvas上面繪制文字瞭。這裡不需要更新進度文字,所以就更省事瞭。
EMUI 下面的10.0.0也是一樣的方法,隻是給Y坐標加一下55,往下移一點就好。
//繪制文字 private void drawText(Canvas canvas) { int mTxtWidth = getTextWidth(); int mTxtHeight = getTextHeight(); int x = getWidth() / 2 - mTxtWidth / 2; int y = getHeight() / 2 + mTxtHeight / 4; canvas.drawText(getResources().getString(R.string.defaultTextEmui), x, y, mPaintText); } //繪制下方文字 private void drawTextBlow(Canvas canvas) { int mTxtWidth = getTextWidthBlow(); int mTxtHeight = getTextHeight(); int x = getWidth() / 2 - mTxtWidth / 2; int y = getHeight() / 2 + mTxtHeight / 4 + 55; canvas.drawText(getResources().getString(R.string.defaultTextBelow), x, y, mPaintTextLevel); }
4.加入動畫效果
/** * 設置動畫效果 */ public void start() { ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 360); valueAnimator.setDuration(duration); valueAnimator.setInterpolator(new LinearInterpolator()); valueAnimator.addUpdateListener(animation -> { process = (int) animation.getAnimatedValue(); invalidate(); }); valueAnimator.start(); }
最終效果:
完整代碼
package com.example.floatingwindow.widget; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.DashPathEffect; import android.graphics.Paint; import android.graphics.PathEffect; import android.graphics.RectF; import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; import android.view.animation.LinearInterpolator; import androidx.annotation.Nullable; import com.example.floatingwindow.R; public class DottedLineProgressBar extends View { private Paint mPaint; private Paint mPaintBack; private Paint mPaintText; private Paint mPaintTextLevel; private int strokeWidth = 30; private int textSize = 22; private int textSizeBlow = 15; private long duration = 3500; private int process; public DottedLineProgressBar(Context context) { super(context); init(); } public DottedLineProgressBar(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } public DottedLineProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } public void setStrokeWidth(int width) { strokeWidth = width; } public void setTextSize(int textSize) { this.textSize = textSize; } public void setDuration(long duration) { this.duration = duration; } public void setTextSizeBlow(int textSizeBlow) { this.textSizeBlow = textSizeBlow; } //初始化畫筆 private void init() { mPaintBack = new Paint();//圓角矩形 mPaintBack.setColor(getResources().getColor(R.color.gray));//圓角矩形顏色 mPaintBack.setAntiAlias(true);// 抗鋸齒效果 mPaintBack.setStyle(Paint.Style.STROKE);//設置畫筆樣式 mPaintBack.setStrokeWidth(strokeWidth);//設置畫筆寬度 mPaint = new Paint(); mPaint.setColor(getResources().getColor(R.color.blue)); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(strokeWidth); mPaintText = new Paint(); mPaintText.setAntiAlias(true); mPaintText.setStyle(Paint.Style.FILL); mPaintText.setColor(getResources().getColor(R.color.blue)); mPaintText.setTextSize(sp2px(textSize)); mPaintTextLevel = new Paint(); mPaintTextLevel.setAntiAlias(true); mPaintTextLevel.setStyle(Paint.Style.FILL); mPaintTextLevel.setColor(getResources().getColor(R.color.gray)); mPaintTextLevel.setTextSize(sp2px(textSizeBlow)); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawBack(canvas); drawProgress(canvas); drawText(canvas); drawTextBlow(canvas); } private void drawBack(Canvas canvas) { RectF rectF = new RectF(strokeWidth, strokeWidth, getWidth() - strokeWidth, getHeight() - strokeWidth); PathEffect effects = new DashPathEffect(new float[]{8, 6}, 0); mPaintBack.setPathEffect(effects); canvas.drawArc(rectF, 0, 360, false, mPaintBack); } private void drawProgress(Canvas canvas) { RectF rectF = new RectF(strokeWidth, strokeWidth, getWidth() - strokeWidth, getHeight() - strokeWidth); PathEffect effects = new DashPathEffect(new float[]{8, 6}, 0); mPaint.setPathEffect(effects); canvas.drawArc(rectF, 0, process, false, mPaint); } //繪制文字 private void drawText(Canvas canvas) { int mTxtWidth = getTextWidth(); int mTxtHeight = getTextHeight(); int x = getWidth() / 2 - mTxtWidth / 2; int y = getHeight() / 2 + mTxtHeight / 4; canvas.drawText(getResources().getString(R.string.defaultTextEmui), x, y, mPaintText); } //繪制下方文字 private void drawTextBlow(Canvas canvas) { int mTxtWidth = getTextWidthBlow(); int mTxtHeight = getTextHeight(); int x = getWidth() / 2 - mTxtWidth / 2; int y = getHeight() / 2 + mTxtHeight / 4 + 55; canvas.drawText(getResources().getString(R.string.defaultTextBelow), x, y, mPaintTextLevel); } private int getTextWidth() { String text = getResources().getString(R.string.defaultTextEmui); return (int) mPaintText.measureText(text, 0, text.length()); } private int getTextWidthBlow() { String text = getResources().getString(R.string.defaultTextBelow); return (int) mPaintTextLevel.measureText(text, 0, text.length()); } private int getTextHeight() { Paint.FontMetrics fm = mPaintText.getFontMetrics(); return (int) Math.ceil(fm.descent - fm.ascent); } private int sp2px(int sp) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics()); } /** * 設置動畫效果 */ public void start() { ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 360); valueAnimator.setDuration(duration); valueAnimator.setInterpolator(new LinearInterpolator()); valueAnimator.addUpdateListener(animation -> { process = (int) animation.getAnimatedValue(); invalidate(); }); valueAnimator.start(); } }
kotlin調用:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) dottedLineProgressBar.post { dottedLineProgressBar.start() } } }
XML:
<com.example.floatingwindow.widget.DottedLineProgressBar android:id="@+id/dottedLineProgressBar" android:layout_width="200dp" android:layout_height="200dp" android:layout_gravity="center"> </com.example.floatingwindow.widget.DottedLineProgressBar>
以上就是完整的實現過程瞭。
項目源碼:https://gitee.com/tu_erhongjiang/android-progress-bar
到此這篇關於Android模擬實現華為系統升級進度條的文章就介紹到這瞭,更多相關Android進度條內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 詳解Android如何自定義view實現圓形進度條
- Android自定義view實現圓形進度條效果
- Android實現絢麗的自定義進度條
- android實現倒計時動態圈
- android自定義帶箭頭對話框