添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Android自定义控件之时间百分比显示

Android自定义控件之时间百分比显示

江水绵延流转,日夜不息。于是子在川上曰:“逝者如斯夫,不舍昼夜”。时间如流水,人们总是在不知名的忙碌中让时间从指尖流走,时常盯着60进制的时分秒而无感,每每入夜之时才猛然惊觉,哀怨又彷徨。所以我萌生一个想法,想要将时间换成百分比进度条的形式。想从另一个角度看待时间,努力抓住时间的衣角,努力不让它从茫然中走失、从迷惘中逝去。

时间百分比控件继承自View,准备工作诸如Paint、TextPaint、Rect、初始化、构造函数等便不再细说,尾部将附上源码。核心要点便是如何将年、月、周、日、时、分、秒转化成百分比。我通过倒计时器CountDownTimer搭配SimpleDateFormat("yyyyMMddHHmmss").format(new Date(System.currentTimeMillis()),可以拿到当前时间的格式化的时间字符串。经过字符串截取,再解析转成整型就能获取到年、月、日、时、分、秒。接下来从最小的秒开始计算。针对秒,直接除以60。针对分钟,需要加上已过的秒的部分后再除以60。举个例子,30秒的时候,秒显示50%,此时分钟应该显示30/60/60=0.008333即0.8333%。时、日、年同理。

year = Integer.parseInt(strDateTime.substring(0, 4));
month = Integer.parseInt(strDateTime.substring(4, 6));
day = Integer.parseInt(strDateTime.substring(6, 8));
hour = Integer.parseInt(strDateTime.substring(8, 10));
min = Integer.parseInt(strDateTime.substring(10, 12));
second = Integer.parseInt(strDateTime.substring(12, 14));
timeInt[5] = second / 60f;
timeInt[4] = (min + timeInt[5]) / 60f;
timeInt[3] = (hour + timeInt[4]) / 24f;
timeInt[2] = (getIndexOfWeek() + timeInt[3]) / 7f;
timeInt[1] = (day - 1 + timeInt[3]) / (float) getDaysInMonth(year, month);
timeInt[0] = (month - 1 + timeInt[1]) / 12f;

针对周,默认周一为一周的第一天,代码中的getIndexOfWeek()通过以下方法获取:

/**
 * 获取当前是一星期的第几天
 * @return 所求
private int getIndexOfWeek(){
    int [] weekDays = {6,0,1,2,3,4,5};
    Calendar cal = Calendar.getInstance();
    cal.setTime(new Date(System.currentTimeMillis()));
    int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
    if (w < 0) {
        w = 0;
    return weekDays[w];
}

针对月,一三五七八十腊,三十一天永不差。闰年二月29天,平年二月28天。剩下的都是30天。代码中的getDaysInMonth(year, month)通过一下方法获取:

/**
 * 返回某年某月的天数
 * @param year 年
 * @param month 月
 * @return 所求
privates int getDaysInMonth(int year, int month){
    int days;
    int febDay = 28;
    if(isLeap(year)){
        febDay = 29;
    switch (month){
        case 2:
            days = febDay;
            break;
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            days = 31;
            break;
        case 4:
        case 6:
        case 9:
        case 11:
            days = 30;
            break;
        default:
            days = 0;
    return days;
 * 是否是闰年
 * @param year 年
 * @return 所求
private boolean isLeap(int year){//能被100整除且能被400整除才是闰年,剩余的能被四整除且不能被100整除才是闰年。四年一闰,百年不闰,四百年再闰。 例如,2000年是闰年,1900年则是平年。
    return year % 400 == 0 || year % 100 != 0 && year % 4 == 0;
}

经过上面的代码后已经得到六个浮点数,显示的时候乘以100再在后面加上百分号就行了。绘制一个百分比的代码如下,其他五个依葫芦画瓢即可:

str = "分钟已过" + timeInt[5] * 100 + "%";
textPaint.getTextBounds(str, 0, str.length(), rect);
paint.setColor(Color.LTGRAY);
canvas.drawRoundRect((float) MARGIN_LEFT, 5 * LINE_HEIGHT + rect.height(), MARGIN_LEFT + (getWidth() - 2 * MARGIN_LEFT) * timeInt[5], 6 * (float) LINE_HEIGHT + rect.height(), ROUND_CORNER, ROUND_CORNER, paint);
canvas.drawText(str, MARGIN_LEFT, 6 * LINE_HEIGHT - (rect.top + rect.bottom) / 2f, textPaint);

画进度条用的是画圆角矩形的方法。都是基本操作就不赘述了。最后贴出自定义控件全部源码。

package com.wenlin.myproduction.widget;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.CountDownTimer;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import com.wenlin.myproduction.util.UIHelper;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
 * @author 召唤希尔
 * @Email 377979485@qq.com
 * @desc 显示时间百分比,而不是60进制的分秒
 * @time 2023-02-25 星期六 22:23
public class TimePercentView extends View {
    private static final int LINE_HEIGHT = 120;
    private static final int MARGIN_LEFT = 40;
    private static final float ROUND_CORNER = 8;
    private float[] timeInt = new float[6];
    private Paint paint;
    private TextPaint textPaint;
    private Rect rect;
    private SimpleDateFormat formatter;
    private CountDownTimer timer;
    private String strDateTime;
    private Date date;
    private int year;
    private int month;
    private int day;
    private int hour;
    private int min;
    private int second;
    private String str;
    public TimePercentView(Context context) {
        this(context, null);
    public TimePercentView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
     * 初始化
    @SuppressLint("SimpleDateFormat")
    private void init() {
        paint = new Paint();
        paint.setDither(true);
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);
        textPaint = new TextPaint();
        textPaint.setColor(Color.BLACK);
        textPaint.setTextSize(60);
        rect = new Rect();
        formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        timer = new CountDownTimer(Integer.MAX_VALUE, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                date = new Date(System.currentTimeMillis());
                strDateTime = formatter.format(date);
                date = null;
                year = Integer.parseInt(strDateTime.substring(0, 4));
                month = Integer.parseInt(strDateTime.substring(4, 6));
                day = Integer.parseInt(strDateTime.substring(6, 8));
                hour = Integer.parseInt(strDateTime.substring(8, 10));
                min = Integer.parseInt(strDateTime.substring(10, 12));
                second = Integer.parseInt(strDateTime.substring(12, 14));
                timeInt[5] = second / 60f;
                timeInt[4] = (min + timeInt[5]) / 60f;
                timeInt[3] = (hour + timeInt[4]) / 24f;
                timeInt[2] = (getTodayOfWeek() + timeInt[3]) / 7f;
                timeInt[1] = (day - 1 + timeInt[3]) / (float) getDaysInMonth(year, month);
                timeInt[0] = (month - 1 + timeInt[1]) / 12f;
                invalidate();
            @Override
            public void onFinish() {
        }.start();
     * 获取当前是一星期的第几天
     * @return 所求
    private int getTodayOfWeek(){
        int [] weekDays = {6,0,1,2,3,4,5};
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date(System.currentTimeMillis()));
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0) {
            w = 0;
        return weekDays[w];
     * 返回某年某月的天数
     * @param year 年
     * @param month 月
     * @return 所求
    private int getDaysInMonth(int year, int month){
        int days;
        int febDay = 28;
        if(isLeap(year)){
            febDay = 29;
        switch (month){
            case 2:
                days = febDay;
                break;
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                days = 31;
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                days = 30;
                break;
            default:
                days = 0;
        return days;
     * 是否是闰年
     * @param year 年
     * @return 所求
    private boolean isLeap(int year){//能被100整除且能被400整除才是闰年,剩余的能被四整除不能被100整除。四年一闰,百年不闰,四百年再闰。 例如,2000年是闰年,1900年则是平年。
        return year % 400 == 0 || year % 100 != 0 && year % 4 == 0;
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        paint.setColor(Color.parseColor("#90ffffff"));
        canvas.drawRoundRect(MARGIN_LEFT, 0, getWidth() - MARGIN_LEFT, 7 * (float) LINE_HEIGHT, ROUND_CORNER, ROUND_CORNER, paint);
        str = "今年已过" + timeInt[0] * 100 + "%";
        textPaint.getTextBounds(str, 0, str.length(), rect);
        paint.setColor(Color.BLUE);
        canvas.drawRoundRect((float) MARGIN_LEFT, rect.height(), MARGIN_LEFT + (getWidth() - 2 * MARGIN_LEFT) * timeInt[0], (float) LINE_HEIGHT + rect.height(), ROUND_CORNER, ROUND_CORNER, paint);
        canvas.drawText(str, MARGIN_LEFT, LINE_HEIGHT - (rect.top + rect.bottom) / 2f, textPaint);
        str = "本月已过" + timeInt[1] * 100 + "%";
        textPaint.getTextBounds(str, 0, str.length(), rect);
        paint.setColor(Color.RED);
        canvas.drawRoundRect((float) MARGIN_LEFT, LINE_HEIGHT + rect.height(), MARGIN_LEFT + (getWidth() - 2 * MARGIN_LEFT) * timeInt[1], 2 * (float) LINE_HEIGHT + rect.height(), ROUND_CORNER, ROUND_CORNER, paint);
        canvas.drawText(str, MARGIN_LEFT, 2 * LINE_HEIGHT - (rect.top + rect.bottom) / 2f, textPaint);
        str = "本周已过" + timeInt[2] * 100 + "%";
        textPaint.getTextBounds(str, 0, str.length(), rect);
        paint.setColor(Color.GREEN);
        canvas.drawRoundRect((float) MARGIN_LEFT, 2 * LINE_HEIGHT + rect.height(), MARGIN_LEFT + (getWidth() - 2 * MARGIN_LEFT) * timeInt[2], 3 * (float) LINE_HEIGHT + rect.height(), ROUND_CORNER, ROUND_CORNER, paint);
        canvas.drawText(str, MARGIN_LEFT, 3 * LINE_HEIGHT - (rect.top + rect.bottom) / 2f, textPaint);
        str = "今天已过" + timeInt[3] * 100 + "%";
        textPaint.getTextBounds(str, 0, str.length(), rect);
        paint.setColor(Color.YELLOW);
        canvas.drawRoundRect((float) MARGIN_LEFT, 3 * LINE_HEIGHT + rect.height(), MARGIN_LEFT + (getWidth() - 2 * MARGIN_LEFT) * timeInt[3], 4 * (float) LINE_HEIGHT + rect.height(), ROUND_CORNER, ROUND_CORNER, paint);
        canvas.drawText(str, MARGIN_LEFT, 4 * LINE_HEIGHT - (rect.top + rect.bottom) / 2f, textPaint);
        str = "小时已过" + timeInt[4] * 100 + "%";
        textPaint.getTextBounds(str, 0, str.length(), rect);
        paint.setColor(Color.CYAN);
        canvas.drawRoundRect((float) MARGIN_LEFT, 4 * LINE_HEIGHT + rect.height(), MARGIN_LEFT + (getWidth() - 2 * MARGIN_LEFT) * timeInt[4], 5 * (float) LINE_HEIGHT + rect.height(), ROUND_CORNER, ROUND_CORNER, paint);
        canvas.drawText(str, MARGIN_LEFT, 5 * LINE_HEIGHT - (rect.top + rect.bottom) / 2f, textPaint);
        str = "分钟已过" + timeInt[5] * 100 + "%";
        textPaint.getTextBounds(str, 0, str.length(), rect);
        paint.setColor(Color.LTGRAY);
        canvas.drawRoundRect((float) MARGIN_LEFT, 5 * LINE_HEIGHT + rect.height(), MARGIN_LEFT + (getWidth() - 2 * MARGIN_LEFT) * timeInt[5], 6 * (float) LINE_HEIGHT + rect.height(), ROUND_CORNER, ROUND_CORNER, paint);
        canvas.drawText(str, MARGIN_LEFT, 6 * LINE_HEIGHT - (rect.top + rect.bottom) / 2f, textPaint);
        str = "时间:" + strDateTime;
        textPaint.getTextBounds(str, 0, str.length(), rect);
        canvas.drawText(str, MARGIN_LEFT, 8 * LINE_HEIGHT - (rect.top + rect.bottom) / 2f, textPaint);
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();