Android模擬實(shí)現(xiàn)華為系統(tǒng)升級(jí)進(jìn)度條
前言
之前用華為Android系統(tǒng)的時(shí)候總是會(huì)想到這種虛線進(jìn)度條是怎么實(shí)現(xiàn)的,因?yàn)橹苯佑胏anvas的drawArc方法畫(huà)出來(lái)的是實(shí)線,所以最近在網(wǎng)上搜了很多進(jìn)度條相關(guān)的文章,也了解到了其中的原理,下面分享給大家。下面這兩篇文章是我之前寫(xiě)的Android進(jìn)度條相關(guān)的文章,有興趣的朋友們可以看看:
Android實(shí)現(xiàn)絢麗的自定義進(jìn)度條
詳解Android如何自定義view實(shí)現(xiàn)圓形進(jìn)度條
下面開(kāi)始講解虛線進(jìn)度條的實(shí)現(xiàn)方法,首先看一張圖:
實(shí)現(xiàn)步驟
大家可以先想想這種進(jìn)度條是怎么實(shí)現(xiàn)的?網(wǎng)上有各種各樣的方法,也有人用path的lineTo()方法實(shí)現(xiàn)了類(lèi)似的效果。但是我個(gè)人覺(jué)得canvas的drawArc方法也是個(gè)不錯(cuò)的選擇,適合自己的才是最好的。
canvas.drawArc(rectF, 0, process, false, mPaint);
閱讀了大量文章,最后發(fā)現(xiàn)改變paint的樣式是最簡(jiǎn)單好用的方法。給paint設(shè)置一個(gè)effect就好了。
1.用DashPathEffect給paint加上虛線效果
DashPathEffect dashPathEffect = new DashPathEffect(new float[]{8, 6}, 0); mPaintBack.setPathEffect(dashPathEffect);
build一下項(xiàng)目,看到的結(jié)果是這樣的:
能實(shí)現(xiàn)這個(gè)效果就大功告成了,如果看過(guò)我前面兩篇文章的朋友們就知道,后面的步驟就簡(jiǎn)單了,加個(gè)進(jìn)度條和動(dòng)畫(huà)效果就可以了。
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.畫(huà)出進(jìn)度條
畫(huà)進(jìn)度條和畫(huà)背景完全一樣,只是畫(huà)筆顏色和小點(diǎn)個(gè)數(shù)不一樣。
代碼如下:
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.繪制文字
接下來(lái)是繪制文字,實(shí)現(xiàn)文字居中的效果。思路是計(jì)算出圓心,調(diào)用canvas.drawText的方法就能在canvas上面繪制文字了。這里不需要更新進(jìn)度文字,所以就更省事了。
EMUI 下面的10.0.0也是一樣的方法,只是給Y坐標(biāo)加一下55,往下移一點(diǎn)就好。
//繪制文字 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.加入動(dòng)畫(huà)效果
/** * 設(shè)置動(dòng)畫(huà)效果 */ 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; } //初始化畫(huà)筆 private void init() { mPaintBack = new Paint();//圓角矩形 mPaintBack.setColor(getResources().getColor(R.color.gray));//圓角矩形顏色 mPaintBack.setAntiAlias(true);// 抗鋸齒效果 mPaintBack.setStyle(Paint.Style.STROKE);//設(shè)置畫(huà)筆樣式 mPaintBack.setStrokeWidth(strokeWidth);//設(shè)置畫(huà)筆寬度 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()); } /** * 設(shè)置動(dòng)畫(huà)效果 */ 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調(diào)用:
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>
以上就是完整的實(shí)現(xiàn)過(guò)程了。
項(xiàng)目源碼:https://gitee.com/tu_erhongjiang/android-progress-bar
到此這篇關(guān)于Android模擬實(shí)現(xiàn)華為系統(tǒng)升級(jí)進(jìn)度條的文章就介紹到這了,更多相關(guān)Android進(jìn)度條內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android 實(shí)現(xiàn)錨點(diǎn)定位思路詳解
本篇文章就使用tablayout、scrollview來(lái)實(shí)現(xiàn)android錨點(diǎn)定位的功能。通過(guò)<a href="#head" rel="external nofollow" > 去設(shè)置頁(yè)面內(nèi)錨點(diǎn)定位跳轉(zhuǎn)。具體實(shí)現(xiàn)思路大家跟隨腳本之家小編一起通過(guò)本文看下吧2018-07-07Android使用ListView實(shí)現(xiàn)下拉刷新及上拉顯示更多的方法
這篇文章主要介紹了Android使用ListView實(shí)現(xiàn)下拉刷新及上拉顯示更多的方法,結(jié)合實(shí)例形式分析了ListView滾動(dòng)刷新與加載的相關(guān)操作技巧,需要的朋友可以參考下2017-02-02淺析Android手機(jī)衛(wèi)士之抖動(dòng)輸入框和手機(jī)震動(dòng)
這篇文章主要介紹了淺析Android手機(jī)衛(wèi)士之輸入框抖動(dòng)和手機(jī)震動(dòng)的相關(guān)資料,需要的朋友可以參考下2016-04-04Flutter質(zhì)感設(shè)計(jì)之持久底部面板
這篇文章主要為大家詳細(xì)介紹了Flutter質(zhì)感設(shè)計(jì)之持久底部面板,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08Android開(kāi)發(fā)實(shí)現(xiàn)Files文件讀取解析功能示例
這篇文章主要介紹了Android開(kāi)發(fā)實(shí)現(xiàn)Files文件讀取解析功能,結(jié)合實(shí)例形式分析了Android針對(duì)txt文本文件的讀取、保存功能實(shí)現(xiàn)方法與布局操作技巧,需要的朋友可以參考下2017-09-09Android小程序?qū)崿F(xiàn)選項(xiàng)菜單
這篇文章主要為大家詳細(xì)介紹了Android小程序?qū)崿F(xiàn)選項(xiàng)菜單,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05Android流式布局實(shí)現(xiàn)歷史搜索記錄功能
最近在開(kāi)發(fā)項(xiàng)目的時(shí)候,有一個(gè)需求是展示歷史搜索記錄 ,展示的樣式是流式布局(就是根據(jù)內(nèi)容自動(dòng)換行)。接下來(lái)通過(guò)本文給大家分享android流式布局實(shí)現(xiàn)歷史搜索記錄功能,感興趣的的小伙伴參考下2017-05-05Flutter實(shí)現(xiàn)手勢(shì)識(shí)別功能詳解方法
在Flutter中使用GestureDetector可以來(lái)完成對(duì)手勢(shì)的識(shí)別,包括長(zhǎng)按、滑動(dòng)、雙擊等手勢(shì),這篇文章主要介紹了Flutter實(shí)現(xiàn)手勢(shì)識(shí)別功能2022-11-11