詳解Android如何自定義view實(shí)現(xiàn)圓形進(jìn)度條
Android中實(shí)現(xiàn)進(jìn)度條有很多種方式,自定義進(jìn)度條一般是繼承progressBar或繼承view來實(shí)現(xiàn),本篇中講解的是第二種方式。
先上效果圖:

實(shí)現(xiàn)圓形進(jìn)度條總體來說并不難,還是跟往常一樣繼承view,初始化畫筆,按下面的步驟一步步來就好了。對初學(xué)者來說動畫效果可能比較陌生,我們可以使用屬性動畫中的valueAnimator來實(shí)現(xiàn)動畫效果。
實(shí)現(xiàn)步驟:
1、畫出一個灰色的圓環(huán)作為背景。
2、畫出上層的圓環(huán)覆蓋下方的圓環(huán)。
3、加入動畫效果
值得注意的是怎么設(shè)置圓環(huán)和文字的位置。
畫出矩形只需要傳入矩形對角線的坐標(biāo)即可,如果不加以處理的話畫出來的圓環(huán)的邊緣是不完整的,剛開始接觸自定義view的同學(xué)們一定要先好好看看Android坐標(biāo)系相關(guān)內(nèi)容,不然很難理解位置參數(shù)為什么這樣設(shè)置。
完整代碼:
package com.example.floatingwindow.widget;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import androidx.annotation.Nullable;
import com.example.floatingwindow.R;
public class ProgressBarView extends View {
private Paint mPaintBack;
private Paint mPaint;
private Paint mPaintText;
private float process;
private int strokeWidth = 15;
private int textSize = 20;
private long duration = 3000;
private float startDegree = 0;
private float endDegree = 360;
private String text = "完成";
private String defaultText = "0%";
public ProgressBarView(Context context) {
super(context);
init();
}
public ProgressBarView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ProgressBarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaintBack = new Paint();
mPaintBack.setColor(getResources().getColor(R.color.gray));
mPaintBack.setStyle(Paint.Style.STROKE);
mPaintBack.setAntiAlias(true);
mPaintBack.setStrokeCap(Paint.Cap.ROUND);
mPaintBack.setStrokeWidth(strokeWidth);
mPaint = new Paint();
mPaint.setColor(getResources().getColor(R.color.purple_200));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setAntiAlias(true);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(strokeWidth);
mPaintText = new Paint();
mPaintText.setAntiAlias(true);
mPaintText.setStyle(Paint.Style.STROKE);
mPaintText.setColor(Color.BLACK);
mPaintBack.setStrokeCap(Paint.Cap.ROUND);
mPaintText.setTextSize(sp2px(textSize));
}
public void setStrokeWidth(int width) {
strokeWidth = width;
}
public void setTextSize(int textSize) {
this.textSize = textSize;
}
public void setDuration(long duration) {
this.duration = duration;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//創(chuàng)建圓環(huán)矩形
RectF rectF = new RectF(strokeWidth, strokeWidth, getWidth() - strokeWidth, getHeight() - strokeWidth);
//畫出灰色進(jìn)度條作為背景
canvas.drawArc(rectF, 0, 360, false, mPaintBack);
//畫進(jìn)度條
canvas.drawArc(rectF, 0, process, false, mPaint);
//計算進(jìn)度
int percent = (int) (process / 360 * 100);
//設(shè)置文字在canvas中的位置
Paint.FontMetrics fm = mPaintText.getFontMetrics();
int mTxtWidth = (int) mPaintText.measureText(text, 0, defaultText.length());
int mTxtHeight = (int) Math.ceil(fm.descent - fm.ascent);
int x = getWidth() / 2 - mTxtWidth / 2;
int y = getHeight() / 2 + mTxtHeight / 4;
if (percent < 100) {
canvas.drawText(percent + "%", x, y, mPaintText);
} else {
canvas.drawText(text, x, y, mPaintText);
}
}
/**
* 設(shè)置動畫效果
*/
public void start() {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(startDegree, endDegree);
valueAnimator.setDuration(duration);
valueAnimator.setInterpolator(new DecelerateInterpolator());
valueAnimator.addUpdateListener(animation -> {
process = (float) animation.getAnimatedValue();
invalidate();
});
valueAnimator.start();
}
private int sp2px(int sp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
getResources().getDisplayMetrics());
}
}
最后就是動畫效果了,使用valueanimator,傳入開始和結(jié)束的進(jìn)度以及執(zhí)行時間。然后每次進(jìn)度發(fā)生變化時做UI刷新。
xml布局:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.example.floatingwindow.widget.ProgressBarView
android:id="@+id/progressBar"
android:layout_width="150dp"
android:layout_height="150dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
</com.example.floatingwindow.widget.ProgressBarView>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
progressBar.start()
progressBar.setOnClickListener { progressBar.start()}
}
以上就是詳解Android如何自定義view實(shí)現(xiàn)圓形進(jìn)度條的詳細(xì)內(nèi)容,更多關(guān)于Android圓形進(jìn)度條的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android自定義View展開菜單功能的實(shí)現(xiàn)
這篇文章主要介紹了Android自定義View展開菜單功能的實(shí)現(xiàn),需要的朋友可以參考下2017-06-06
Android 自定義LayoutManager實(shí)現(xiàn)花式表格
這篇文章主要介紹了Android 自定義LayoutManager實(shí)現(xiàn)花式表格,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2020-02-02
Android手機(jī)衛(wèi)士之確認(rèn)密碼對話框
這篇文章主要為大家詳細(xì)介紹了Android手機(jī)衛(wèi)士之確認(rèn)密碼對話框,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-10-10

