網(wǎng)站首頁 編程語言 正文
Android中實(shí)現(xiàn)進(jìn)度條有很多種方式,自定義進(jìn)度條一般是繼承progressBar或繼承view來實(shí)現(xiàn),本篇中講解的是第二種方式。
先上效果圖:
實(shí)現(xiàn)圓形進(jìn)度條總體來說并不難,還是跟往常一樣繼承view,初始化畫筆,按下面的步驟一步步來就好了。對(duì)初學(xué)者來說動(dòng)畫效果可能比較陌生,我們可以使用屬性動(dòng)畫中的valueAnimator來實(shí)現(xiàn)動(dòng)畫效果。
實(shí)現(xiàn)步驟:
1、畫出一個(gè)灰色的圓環(huán)作為背景。
2、畫出上層的圓環(huán)覆蓋下方的圓環(huán)。
3、加入動(dòng)畫效果
值得注意的是怎么設(shè)置圓環(huán)和文字的位置。
畫出矩形只需要傳入矩形對(duì)角線的坐標(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ì)算進(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è)置動(dòng)畫效果
? ? ?*/
? ? 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());
? ? }
}
最后就是動(dòng)畫效果了,使用valueanimator,傳入開始和結(jié)束的進(jìn)度以及執(zhí)行時(shí)間。然后每次進(jìn)度發(fā)生變化時(shí)做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()}
? ? }
原文鏈接:https://blog.csdn.net/daydayup05/article/details/122150161
相關(guān)推薦
- 2022-11-04 Android實(shí)現(xiàn)簡(jiǎn)易秒表功能_Android
- 2024-02-29 UNI-APP項(xiàng)目在引用官方提供的Uni-App-Demo實(shí)例中的組件時(shí)應(yīng)該注意的問題
- 2022-07-08 android?studio集成unity導(dǎo)出工程的實(shí)現(xiàn)_Android
- 2022-04-11 Android中圖片圓角三種實(shí)現(xiàn)方法_Android
- 2022-08-01 Oracle停止數(shù)據(jù)泵導(dǎo)入數(shù)據(jù)的方法詳解_oracle
- 2023-05-07 oracle中如何保留兩位小數(shù)_oracle
- 2023-04-24 Python?語法錯(cuò)誤:"SyntaxError:?invalid?character?in?ide
- 2021-12-10 Oracle數(shù)據(jù)庫備份還原詳解_oracle
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支