android自定义控件实现带百分比显示进度条,可自定义颜色

lankton lankton     2022-12-06     493

关键词:

介绍

前天做了一个带百分比显示的条形进度条,效果如下:

实现

这个自定义进度条, 看起来简单, 做起来。。。其实也很简单: 主要通过继承View类, 并重写其onDraw方法实现。
思路分为3步:
1. 画进图条背景(图中灰色部分
2. 根据进度画出进度条(图中绿色部分
3. 绘制进度百分比(图中白色文本

前面2个步骤非常简单, 通过drawRoundRect方法进行绘制即可, 第3步也不难, 重点在于定位好绘制文本的位置。文本的水平位置很容易确认, 因为Paint对象提供了measureText方法, 可以获得到文本的长度。用绿色进度条的长度和它做一个减法, 就能得出绘制文本的水平坐标。
竖直坐标, 就有些复杂了。先看下图(图片来源:http://www.xyczero.com/blog/article/20/):

在Canvas对象的drawText方法中, y坐标参数指的是baseline线的y坐标参数。我们所要做的, 就是求出, 当文本垂直居中显示时, 该y坐标的值。
求值, 需要用到Paint的内部类:FontMetrics。

public static class FontMetrics 
        /**
         * The maximum distance above the baseline for the tallest glyph in
         * the font at a given text size.
         */
        public float   top;
        /**
         * The recommended distance above the baseline for singled spaced text.
         */
        public float   ascent;
        /**
         * The recommended distance below the baseline for singled spaced text.
         */
        public float   descent;
        /**
         * The maximum distance below the baseline for the lowest glyph in
         * the font at a given text size.
         */
        public float   bottom;
        /**
         * The recommended additional space to add between lines of text.
         */
        public float   leading;
    

由源码可以看到该类对象提供的几个值的含义。其中:
ascent 代表的就是上图中ascent线的y坐标减去baseline线的y坐标, 所以该值为负数
descent 代表的就是上图中的descent线的y坐标减去baseline的y坐标, 所以该值为正数
由此,可知: 文本的高度为2个距离之和, 即2个数字之差:
height = descent - ascent; (1)
又:设空间高度为Height
baseline y坐标 baseY = 1/2 Height + (1/ 2 height - descent); (2)

由(1) (2)式可得:
baseY = 1/2 Height - 1/2 ascent - 1/2 descent;

由此, 需要的数据都被求出来了。
同时, 在values/attrs.xml中添加自定义参数, 使三种颜色可以在布局文件中被配置:

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>


    <declare-styleable name="RoundedRectProgressBar">
        <attr name="backColor" format="color" />
        <attr name="barColor" format="color" />
        <attr name="textColor" format="color" />
    </declare-styleable>

</resources>

自定义进度条RoundedRectProgressBar.java:

package com.landemo.rectprogressbar;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by lankton on 16/1/8.
 */
public class RoundedRectProgressBar extends View 

    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private int barColor;
    private int backColor;
    private int textColor;
    private float radius;

    int progress = 0;

    public RoundedRectProgressBar(Context context, AttributeSet attrs, int defStyle) 
        super(context, attrs, defStyle);
        /*获取自定义参数的颜色值*/
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.RoundedRectProgressBar, defStyle, 0);
        int n = a.getIndexCount();
        for (int i = 0; i < n; i++)
        
            int attr = a.getIndex(i);
            switch (attr)
            
                case R.styleable.RoundedRectProgressBar_backColor:
                    backColor = a.getColor(attr, Color.GRAY);
                    break;
                case R.styleable.RoundedRectProgressBar_barColor:
                    barColor = a.getColor(attr, Color.GREEN);
                    break;
                case R.styleable.RoundedRectProgressBar_textColor:
                                        textColor = a.getColor(attr, Color.WHITE);
                    break;

            

        
        a.recycle();
    

    public RoundedRectProgressBar(Context context, AttributeSet attrs) 
        this(context, attrs, 0);
    

    public RoundedRectProgressBar(Context context) 
        this(context, null);
    

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        radius = this.getMeasuredHeight() / 5;
    

    @Override
    protected void onDraw(Canvas canvas) 
        super.onDraw(canvas);
        //背景
        mPaint.setColor(backColor);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawRoundRect(new RectF(0, 0, this.getMeasuredWidth(), this.getMeasuredHeight()), radius, radius, mPaint);
        //进度条
        mPaint.setColor(barColor);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawRoundRect(new RectF(0, 0, this.getMeasuredWidth() * progress / 100f, this.getMeasuredHeight()), radius, radius, mPaint);
        //进度
        mPaint.setColor(textColor);
        mPaint.setTextSize(this.getMeasuredHeight() / 1.2f);
        String text = "" + progress + "%";
        float x = this.getMeasuredWidth() * progress / 100 - mPaint.measureText(text) - 10;
        float y = this.getMeasuredHeight() / 2f - mPaint.getFontMetrics().ascent / 2f - mPaint.getFontMetrics().descent / 2f;
        canvas.drawText(text, x, y, mPaint);
    

    /*设置进度条进度, 外部调用*/
    public void setProgress(int progress) 
        if (progress > 100) 
            this.progress = 100;
         else if (progress < 0) 
            this.progress = 0;
         else 
            this.progress = progress;
        
        postInvalidate();
    

然后在MainActivity里添加方法, 调用RoundedRectProgressBar的setProgress方法, 重绘进度条。 这里用Timer对象模拟进度的不断变化。
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:background="@android:color/white"
    tools:context="com.souche.rectprogressbar.MainActivity">

    <com.souche.rectprogressbar.RoundedRectProgressBar
        android:id="@+id/bar"
        android:layout_width="match_parent"
        android:layout_height="24dp"
        android:layout_marginTop="100dp"
        app:backColor="#E6E6E6"
        app:barColor="#33CC99"
        app:textColor="#FFFFFF"/>

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="reset"
        android:layout_centerInParent="true"/>
</RelativeLayout>

MainActivity.java

package com.landemo.rectprogressbar;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends Activity 

    private RoundedRectProgressBar bar;
    private Button btn;
    private int progress;
    private Timer timer;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bar = (RoundedRectProgressBar) findViewById(R.id.bar);
        btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                reset();
            
        );

    

    /**
     * 进度条从头到尾跑一次
     */
    private void reset() 
        progress = 0;
        timer = new Timer();
        timer.schedule(new TimerTask() 
            @Override
            public void run() 
                bar.setProgress(progress);
                progress ++;
                if (progress > 100) 
                    timer.cancel();
                
            
        , 0, 30);
    

自绘cprogressctrl进度条控件,支持自定义显示文本和进程百分比信息

 [cpp] viewplain copy // CXProgressCtrl 头文件    #pragma once    // CXProgressCtrl    class CXPro 查看详情

qt编写自定义控件13-多态进度条(代码片段)

...条,顾名思义,有多重状态,其实本控件主要是用来表示百分比进度的,由于之前已经存在了百分比进度条控件,名字被霸占了,按照先来先得原则,只好另外取个别名叫做多态进度条,应用场景是,某种任务有三种状态,比如... 查看详情

如何使用逆时针动画显示自定义圆形进度条?

...形进度条,该进度条基于正确答案除以总问题并乘以100的百分比值。并以百分比形式获取结果值,然后将结果值除以100以获得浮点值,因为进度动画值 查看详情

android自定义ratingbar(星级评分控件)

...Bar实现的效果图:   看着自定义的样式远远比Android自带的样式好看多了,用户体验度远远提升,下面我们就来实现该控件: 定义根据图片自定一个RatingBar的背景条,和图片放到同一个目录下面   five_rat... 查看详情

酷炫进度条自定义seekbar(代码片段)

...c;是这样子的:需求:1、看了ui图可以知道这类似android自带的seekbar控件,2、一个水平进度条和一个圆形进度条;3、圆形进度条显示环形刻度和当前进度值;4、并且圆形进度可滑动操作;最终实现效果ÿ... 查看详情

android自定义进度值可拖动的seekbar(代码片段)

最近忙找实习,加上实验室在推新项目,需要学习新知识。所以很长一段时间没去整理了官博客了,github也蛮久没更新,很惭愧。接下来还是要坚持写。今天就简单的写一下我在项目中用到的算自定义seekbar的博客... 查看详情

android自定义圆弧进度条(半圆进度条)圆弧渐变色进度条带指示圆弧宽高可自由修改(代码片段)

首先我们来看下效果图圆弧高度可以自定义,说明,只有高度设置为宽度的二分之一时,才是半圆,否则就是半圆的一部分,即圆弧。不只是圆弧是自定的,图中的文字“2”的控件也是自定义的,下面... 查看详情

两个进度条,加上百分比显示(用wpf实现)

...栏的当前位置,用Value值获取进度条的当前值,用来显示百分比参考技术Ahttp://download.microsoft.com/download/f/6/e/f6e32974-726e-4054-96af-9c747bf89a6e/ProgressBar.exe以上是微软WPF进度条控件的一个例子,很容易,不是很长,不贴过来了,下载了... 查看详情

安卓通过自定义view实现水波进度条控件

...s属性为初始的进度<com.yhongm.wave_progress_view.WaveProgressViewandroid:id="@+id/wave_progress_view"android:layout_width="300dp"android:layout_height="300dp"android:layout_centerInParent="true"app:circleColor="#e38854"app... 查看详情

android自定义水平进度条控件

参考技术AAHorizontalProgressBarthatiscustomizedeasily.Github传送门:https://github.com/zhouzhuo810/ZzHorizontalProgressBar功能简介:1.支持自定义进度颜色;2.支持自定义背景颜色;3.支持自定义背景与进度之间的内间距大小;4.支持自定义最大值和默... 查看详情

android基础知识4-3.7progressbar(进度条)详解

...常实用的组件,通常用于向用户像是某个耗时操作完成的百分比。进度条可动态地显示进度,因此避免长时间地执行某个操作时,让用户感觉程序失去了响应,从而更好地提高用户界面的友好性。也是为数不多的直接继承于View... 查看详情

为啥自定义进度条在android中没有动画?

】为啥自定义进度条在android中没有动画?【英文标题】:WhyCustomprogressbarisnotanimatinginandroid?为什么自定义进度条在android中没有动画?【发布时间】:2017-07-2100:57:20【问题描述】:在可能的应用程序中,我实现了自定义进度条,... 查看详情

h5移动端自定义video播放控件controls(带播放暂停,进度条拖拽)

参考技术A说明:video不支持本地视频的进度拖动,会出现拖动就重头播放的情况,视频链接是网上随便找的,可能会出现请求不成功的情况。参考api:http://www.w3school.com.cn/tags/html_ref_audio_video_dom.asp 查看详情

android之自定义圆形进度条

    在Android开发中,对于进度条想必大家不会陌生。例如,应用在执行一个耗时操作时,会通过展示一个进度条来显示“加载中...”的动画作为友好页面以提高用户体验。对于这样的进度条,最简单的实现方式... 查看详情

android自定义控件篇圆形进度条(代码片段)

一、效果图二、代码逻辑/***funcation:圆形进度条控件*/publicclassCircleProgressViewextendsViewprivatePaintmBackPaint,mProgPaint;//绘制画笔privateRectFmRectF;//绘制区域privateint[]mColorArray;//圆环渐变色privateintmProgress;//圆环进度(0-100)publicCircleProgressView(Co... 查看详情

ycprogress自定义百分比进度条(代码片段)

目录介绍1.本库优势亮点2.使用介绍2.1圆环百分比进度条2.2直线百分比进度条2.3仿杀毒类型百分比进度条3.注意要点4.效果展示5.其他介绍1.本库优势亮点圆环百分比进度条简便且小巧,支持设置多种属性。可以设置内圆和外圆的颜... 查看详情

自定义控件——圆形圆点进度条(仿安全卫士中的一键加速)

...觉得有点意思,可以研究一下,再说也有一段时间没写自定义控件了,正好复习复习(说实话,一段时间没写,思路有,但就是不知道从哪开始)。昨天花了一天的时间才把它搞定,先看效果图:3种显示模式:模拟进度动画效... 查看详情

python无依赖实现一个带百分比的简单进度条

使用sys.stdout或sys.stderr就可以输出一个简单的进度条:importtimeimportsysdefreport_progress(progress,total,lbar_prefix='',rbar_prefix=''):percent=round(progress/float(total)*100)buf& 查看详情