CountDownDigitalClock:倒计时的TextView

[url]http://www.cnblogs.com/over140/archive/2010/08/27/1809873.html[/url]

改了一下,但是输出格式未能实现自定义,原因在于下面的代码中显示时间差不正确,我不知道什么原因。

[color=red]mFormat = "距离结束还有dd天kk小时mm分ss秒";//yyyy-MM-dd hh:mm:ss
mCalendar.setTimeInMillis(mTimeDistance);//为什么这样计算的时间不对???
setText(DateFormat.format(mFormat, mCalendar));[/color]

[img]http://dl.iteye.com/upload/attachment/0068/3081/36925a2f-4514-3125-9dee-01dc35fbbe65.png[/img]

我只能退一步,将就着了,源码是这样的:

import java.util.Calendar;

import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.SystemClock;
import android.provider.Settings;
import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.util.Log;

public class CountDownDigitalClock extends android.widget.DigitalClock {

Calendar mCalendar;
private final static String m12 = "h:mm aa";// h:mm:ss aa
private final static String m24 = "k:mm";// k:mm:ss
private FormatChangeObserver mFormatChangeObserver;

private Runnable mTicker;
private Handler mHandler;

private boolean mTickerStopped = false;

String mFormat;

private long mDeadTime;
private OnCountDownListener onCountDownListener;

public CountDownDigitalClock(Context context) {
super(context);
initClock(context);
}

public CountDownDigitalClock(Context context, AttributeSet attrs) {
super(context, attrs);
initClock(context);
}

private void initClock(Context context) {

if (mCalendar == null) {
mCalendar = Calendar.getInstance();
}

mFormatChangeObserver = new FormatChangeObserver();
getContext().getContentResolver().registerContentObserver(
Settings.System.CONTENT_URI, true, mFormatChangeObserver);

setFormat();
}

@Override
protected void onAttachedToWindow() {
mTickerStopped = false;
super.onAttachedToWindow();
mHandler = new Handler();

/**
* requests a tick on the next hard-second boundary
*/
mTicker = new Runnable() {
public void run() {
if (mTickerStopped)
return;
long mCurrentTime = System.currentTimeMillis();
if (mCurrentTime >= mDeadTime) {
if (onCountDownListener != null){
onCountDownListener.onFinish();
}
return;
}
long mTimeDistance = mDeadTime - mCurrentTime;
long between = mTimeDistance / 1000;// 转换成秒
long day = between / (24 * 3600);
long hour = between % (24 * 3600) / 3600;
long minute = between % (24 * 3600) % 3600 / 60;
long second = between % (24 * 3600) % 3600 % 60;
String deadTimeStr = "距离结束还有" + day + "天" + hour + "小时"
+ minute + "分" + second + "秒";
setText(deadTimeStr);

// mFormat = "距离结束还有dd天kk小时mm分ss秒";//yyyy-MM-dd hh:mm:ss
// mCalendar.setTimeInMillis(mTimeDistance);//为什么这样计算的时间不对???
// setText(DateFormat.format(mFormat, mCalendar));
if (onCountDownListener != null)
onCountDownListener.onTick();
invalidate();
long now = SystemClock.uptimeMillis();
long next = now + (1000 - now % 1000);
mHandler.postAtTime(mTicker, next);
}
};
mTicker.run();
}

@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mTickerStopped = true;
}

/**
* Pulls 12/24 mode from system settings
*/
private boolean get24HourMode() {
return android.text.format.DateFormat.is24HourFormat(getContext());
}

private void setFormat() {
if (get24HourMode()) {
mFormat = m24;
} else {
mFormat = m12;
}
}

private class FormatChangeObserver extends ContentObserver {
public FormatChangeObserver() {
super(new Handler());
}

@Override
public void onChange(boolean selfChange) {
setFormat();
}
}

/**
* set the dead time
*
* @param deadtime
*/
public void setDeadTime(long deadTime) {
this.mDeadTime = deadTime;
}

public interface OnCountDownListener {
public void onFinish();

public void onTick();
}

public void setOnCountDownListener(OnCountDownListener onCountDownListener) {
this.onCountDownListener = onCountDownListener;
}

}


用法:

mClock = (CountDownDigitalClock) findViewById(R.id.myClock);
mClock.setDeadTime(getDeadTimeFromServer());
mClock.setOnCountDownListener(new CountDownDigitalClock.OnCountDownListener() {

@Override
public void onFinish() {
// TODO Auto-generated method stub
showToast("倒计时结束!!!");
}

@Override
public void onTick() {
// TODO Auto-generated method stub
Log.i("tag", "执行了"+(count++)+"次");
}
});

private long getDeadTimeFromServer(){
Calendar mCalendar = Calendar.getInstance();
mCalendar.set(2012, 5-1, 18);//月份从0开始
mCalendar.set(Calendar.HOUR_OF_DAY, 13);//下午1点
mCalendar.set(Calendar.MINUTE, 0);
mCalendar.set(Calendar.SECOND, 0);
return mCalendar.getTimeInMillis();
}


[url]http://www.23code.com/circletimerview/[/url]


Android 倒计时控件,可以定义多种样式。
[url]http://www.jcodecraeer.com/a/opensource/2015/1016/3586.html[/url]

[img]http://dl2.iteye.com/upload/attachment/0112/3733/780ab4e7-3dea-3451-b323-3dda48d60bac.gif[/img]

CountdownView mCvCountdownViewTest1 = (CountdownView)findViewById(R.id.cv_countdownViewTest1);
mCvCountdownViewTest1.start(995550000); // 毫秒


<cn.iwgang.calendardemo.countdownview.CountdownView
android:id="@+id/cv_countdownViewTest4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
app:isHideTimeBackground="true"
app:isShowHour="true"
app:isShowMillisecond="true"
app:timeTextColor="#000000"
app:timeTextSize="25sp"
app:suffixTextColor="#000000"
app:suffixTextSize="15sp"
app:suffixHour=" 时 "
app:suffixMinute=" 分 "
app:suffixSecond=" 秒 "
app:suffixMillisecond=" 毫秒" />


import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.CountDownTimer;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;

/**
* 倒计时View
* Created by iWgang on 15/9/16.
*/
public class CountdownView extends View {
private Context mContext;
private int mDay, mHour, mMinute, mSecond, mMillisecond;
private OnCountdownEndListener mOnCountdownEndListener;
private CountDownTimer mCountDownTimer;

private boolean isShowDay;
private boolean isShowHour;
private boolean isShowMinute;
private boolean isShowMillisecond;
private boolean isHideTimeBackground;
private boolean isShowTimeBgDivisionLine;

private Paint mTimeTextPaint;
private Paint mSuffixTextPaint;
private Paint mTimeTextBgPaint;
private Paint mTimeTextBgDivisionLinePaint;

private RectF mDayBgRectF;
private RectF mHourBgRectF;
private RectF mMinuteBgRectF;
private RectF mSecondBgRectF;
private RectF mMillisecondBgRectF;

private float mTimeTextWidth;
private float mTimeTextHeight;
private float mTimeTextSize;
private float mTimeBgSize;
private int mTimeTextColor;
private int mTimeBgColor;
private float mTimeBgRadius;
private int mTimeBgDivisionLineColor;
private float mTimeTextBaseY;
private float mSuffixTextBaseY;
private int mTimeBgDivisionLineSize;

// 后缀
private boolean isHideLastSuffix;
private String mSuffix;
private String mSuffixDay;
private String mSuffixHour;
private String mSuffixMinute;
private String mSuffixSecond;
private String mSuffixMillisecond;
private int mSuffixTextColor;
private float mSuffixTextSize;
private float mSuffixDayTextWidth;
private float mSuffixHourTextWidth;
private float mSuffixMinuteTextWidth;
private float mSuffixSecondTextWidth;
private float mSuffixMillisecondTextWidth;
private int mSuffixGravity;

public CountdownView(Context context) {
this(context, null);
}

public CountdownView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public CountdownView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);

this.mContext = context;

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CountdownView);
mTimeBgColor = ta.getColor(R.styleable.CountdownView_timeBgColor, 0xFF444444);
mTimeBgRadius = ta.getDimension(R.styleable.CountdownView_timeBgRadius, 0);
isShowTimeBgDivisionLine = ta.getBoolean(R.styleable.CountdownView_isShowTimeBgDivisionLine, true);
mTimeBgDivisionLineColor = ta.getColor(R.styleable.CountdownView_timeBgDivisionLineColor, Color.parseColor("#30FFFFFF"));

mTimeTextSize = ta.getDimension(R.styleable.CountdownView_timeTextSize, sp2px(12));
mTimeTextColor = ta.getColor(R.styleable.CountdownView_timeTextColor, 0xFFFFFFFF);
isHideTimeBackground = ta.getBoolean(R.styleable.CountdownView_isHideTimeBackground, false);
isShowDay = ta.getBoolean(R.styleable.CountdownView_isShowDay, false);
isShowHour = ta.getBoolean(R.styleable.CountdownView_isShowHour, true);
isShowMinute = ta.getBoolean(R.styleable.CountdownView_isShowMinute, true);
isShowMillisecond = ta.getBoolean(R.styleable.CountdownView_isShowMillisecond, false);

mSuffixTextSize = ta.getDimension(R.styleable.CountdownView_suffixTextSize, sp2px(12));
mSuffixTextColor = ta.getColor(R.styleable.CountdownView_suffixTextColor, 0xFF000000);
mSuffix = ta.getString(R.styleable.CountdownView_suffix);
mSuffixDay = ta.getString(R.styleable.CountdownView_suffixDay);
mSuffixHour = ta.getString(R.styleable.CountdownView_suffixHour);
mSuffixMinute = ta.getString(R.styleable.CountdownView_suffixMinute);
mSuffixSecond = ta.getString(R.styleable.CountdownView_suffixSecond);
mSuffixMillisecond = ta.getString(R.styleable.CountdownView_suffixMillisecond);
mSuffixGravity = ta.getInt(R.styleable.CountdownView_suffixGravity, 1);
ta.recycle();

// 初始化画笔
initPaint();

// 初始化后缀
initSuffix();

// 测量时间文字高度
Rect rect = new Rect();
mTimeTextPaint.getTextBounds("00", 0, 2, rect);
mTimeTextWidth = rect.width();
mTimeTextHeight = rect.height();

mTimeBgSize = mTimeTextWidth + (dp2px(2) * 4);

// 初始化时间背景的RectF对象
initTimeBgRect();
}

/**
* 初始化画笔
*/
private void initPaint() {
// 初始化时间文字画笔
mTimeTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTimeTextPaint.setColor(mTimeTextColor);
mTimeTextPaint.setTextAlign(Paint.Align.CENTER);
mTimeTextPaint.setTextSize(mTimeTextSize);

// 初始化分割文字画笔
mSuffixTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mSuffixTextPaint.setColor(mSuffixTextColor);
mSuffixTextPaint.setTextSize(mSuffixTextSize);

// 初始化时间背景画笔
mTimeTextBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTimeTextBgPaint.setStyle(Paint.Style.FILL);
mTimeTextBgPaint.setColor(mTimeBgColor);

// 初始化时间背景中间的分割线画笔
mTimeTextBgDivisionLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTimeTextBgDivisionLinePaint.setColor(mTimeBgDivisionLineColor);
mTimeBgDivisionLineSize = dp2px(0.5f);
mTimeTextBgDivisionLinePaint.setStrokeWidth(mTimeBgDivisionLineSize);
}

private void initSuffix() {
boolean isSuffixNull = true;
float mSuffixTextWidth = 0;

if (!TextUtils.isEmpty(mSuffix)) {
isSuffixNull = false;
isHideLastSuffix = true;
mSuffixTextWidth = mSuffixTextPaint.measureText(mSuffix);
}

if (isShowDay) {
if (!TextUtils.isEmpty(mSuffixDay)) {
mSuffixDayTextWidth = mSuffixTextPaint.measureText(mSuffixDay);
} else {
if (!isSuffixNull) {
mSuffixDay = mSuffix;
mSuffixDayTextWidth = mSuffixTextWidth;
}
}
}

if (isShowHour) {
if (!TextUtils.isEmpty(mSuffixHour)) {
mSuffixHourTextWidth = mSuffixTextPaint.measureText(mSuffixHour);
} else {
if (!isSuffixNull) {
mSuffixHour = mSuffix;
mSuffixHourTextWidth = mSuffixTextWidth;
}
}
}

if (isShowMinute) {
if (!TextUtils.isEmpty(mSuffixMinute)) {
mSuffixMinuteTextWidth = mSuffixTextPaint.measureText(mSuffixMinute);
} else if (!isSuffixNull) {
mSuffixMinute = mSuffix;
mSuffixMinuteTextWidth = mSuffixTextWidth;
}
}

if (!TextUtils.isEmpty(mSuffixSecond)) {
mSuffixSecondTextWidth = mSuffixTextPaint.measureText(mSuffixSecond);
} else if (isShowMillisecond && !isSuffixNull) {
mSuffixSecond = mSuffix;
mSuffixSecondTextWidth = mSuffixTextWidth;
}

if (isShowMillisecond && isSuffixNull && !TextUtils.isEmpty(mSuffixMillisecond)) {
mSuffixMillisecondTextWidth = mSuffixTextPaint.measureText(mSuffixMillisecond);
}
}

/**
* 初始化时间背景的RectF对象
*/
private void initTimeBgRect() {
if (!isHideTimeBackground) {
float mHourLeft = 0;
float mMinuteLeft;
float mSecondLeft;

if (isShowDay) {
// 显示天
// 初始化小时背景RectF
mDayBgRectF = new RectF(0, 0, mTimeBgSize, mTimeBgSize);
// 计算分钟x轴
mHourLeft = mTimeBgSize + mSuffixHourTextWidth;
}

if (isShowHour) {
// 显示小时
// 初始化小时背景RectF
mHourBgRectF = new RectF(mHourLeft, 0, mTimeBgSize + mHourLeft, mTimeBgSize);
// 计算分钟x轴
mMinuteLeft = mHourLeft + mTimeBgSize + mSuffixHourTextWidth;
} else {
mMinuteLeft = mHourLeft;
}

if (isShowMinute) {
// 显示分钟
// 初始化分钟背景RectF
mMinuteBgRectF = new RectF(mMinuteLeft, 0, mTimeBgSize + mMinuteLeft, mTimeBgSize);
// 计算秒钟x轴
mSecondLeft = mMinuteLeft + mTimeBgSize + mSuffixMinuteTextWidth;
} else {
mSecondLeft = mMinuteLeft;
}

// 初始化秒钟背景RectF
mSecondBgRectF = new RectF(mSecondLeft, 0, mTimeBgSize + mSecondLeft, mTimeBgSize);

if (isShowMillisecond) {
// 计算毫秒x轴
float mMillisecondLeft = mTimeBgSize + mSuffixSecondTextWidth + mSecondLeft;

// 初始化毫秒背景RectF
mMillisecondBgRectF = new RectF(mMillisecondLeft, 0, mTimeBgSize + mMillisecondLeft, mTimeBgSize);
}

Paint.FontMetrics timeFontMetrics = mTimeTextPaint.getFontMetrics();
mTimeTextBaseY = mMinuteBgRectF.top + (mMinuteBgRectF.bottom - mMinuteBgRectF.top - timeFontMetrics.bottom + timeFontMetrics.top)/2 - timeFontMetrics.top;

Paint.FontMetrics suffixFontMetrics = mSuffixTextPaint.getFontMetrics();
mSuffixTextBaseY = mMinuteBgRectF.top + (mMinuteBgRectF.bottom - mMinuteBgRectF.top - suffixFontMetrics.bottom + suffixFontMetrics.top)/2 - suffixFontMetrics.top;
} else {
Paint.FontMetrics suffixFontMetrics = mSuffixTextPaint.getFontMetrics();
float suffixFontHeight = suffixFontMetrics.bottom - suffixFontMetrics.top;

switch (mSuffixGravity) {
case 0:
// top
mSuffixTextBaseY = suffixFontHeight - 12; // TODO 待优化
break;
case 1:
// center
mSuffixTextBaseY = mTimeTextHeight - (mTimeTextHeight - suffixFontHeight)/2 - suffixFontMetrics.bottom;
break;
case 2:
// bottom
mSuffixTextBaseY = mTimeTextHeight - (mTimeTextHeight - suffixFontHeight);
break;
}
}
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

float timeWidth = isHideTimeBackground ? mTimeTextWidth : mTimeBgSize;
float width = timeWidth;
width += (mSuffixDayTextWidth + mSuffixHourTextWidth + mSuffixMinuteTextWidth + mSuffixSecondTextWidth + mSuffixMillisecondTextWidth);

if (isShowDay) {
width += timeWidth;
}

if (isShowHour) {
width += timeWidth;
}

if (isShowMinute) {
width += timeWidth;
}

if (isShowMillisecond) {
width += timeWidth;
}

setMeasuredDimension((int) width, (isHideTimeBackground ? (int) mTimeTextHeight : (int) mTimeBgSize));
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

float mHourLeft = 0;
float mMinuteLeft;
float mSecondLeft;

// 背景分割线Y坐标
float mTimeBgDivisionLineYPos = mTimeBgSize/2 + mTimeBgDivisionLineSize/2;

if (isHideTimeBackground) {
// 无背景
float mTextYPos = mTimeTextHeight;

// 判断显示天
if (isShowDay) {
// 画天文字
canvas.drawText(formatNum(mDay), mTimeTextWidth/2, mTextYPos, mTimeTextPaint);
if (mSuffixDayTextWidth > 0) {
// 画天后缀
canvas.drawText(mSuffixDay, mTimeTextWidth, mSuffixTextBaseY, mSuffixTextPaint);
}

// 计算小时x轴
mHourLeft = mTimeTextWidth + mSuffixDayTextWidth;
}

// 判断显示小时
if (isShowHour) {
// 画小时文字
canvas.drawText(formatNum(mHour), mHourLeft + mTimeTextWidth/2, mTextYPos, mTimeTextPaint);
if (mSuffixHourTextWidth > 0) {
// 画小时后缀
canvas.drawText(mSuffixHour, mHourLeft + mTimeTextWidth, mSuffixTextBaseY, mSuffixTextPaint);
}

// 计算分钟x轴
mMinuteLeft = mHourLeft + mTimeTextWidth + mSuffixHourTextWidth;
} else {
mMinuteLeft = mHourLeft;
}

// 判断显示分钟
if (isShowMinute) {
// 画分钟文字
canvas.drawText(formatNum(mMinute), mMinuteLeft + mTimeTextWidth/2 , mTextYPos, mTimeTextPaint);
if (mSuffixMinuteTextWidth > 0) {
// 画分钟后缀
canvas.drawText(mSuffixMinute, mMinuteLeft + mTimeTextWidth, mSuffixTextBaseY, mSuffixTextPaint);
}

// 计算秒钟x轴
mSecondLeft = mMinuteLeft + mTimeTextWidth + mSuffixMinuteTextWidth;
} else {
mSecondLeft = mMinuteLeft;
}

// 画秒钟文字
canvas.drawText(formatNum(mSecond), mSecondLeft + mTimeTextWidth/2, mTextYPos, mTimeTextPaint);
if (mSuffixSecondTextWidth > 0) {
// 画秒钟后缀
canvas.drawText(mSuffixSecond, mSecondLeft + mTimeTextWidth, mSuffixTextBaseY, mSuffixTextPaint);
}

if (isShowMillisecond) {
// 计算毫秒x轴
float mMillisecondLeft = mSecondLeft + mTimeTextWidth + mSuffixSecondTextWidth;
// 画毫秒文字
canvas.drawText(formatMillisecond(), mMillisecondLeft + mTimeTextWidth / 2, mTextYPos, mTimeTextPaint);
if (mSuffixMillisecondTextWidth > 0) {
// 画毫秒后缀
canvas.drawText(mSuffixMillisecond, mMillisecondLeft + mTimeTextWidth, mSuffixTextBaseY, mSuffixTextPaint);
}
}
} else {
// 有背景

// 判断显示天
if (isShowDay) {
// 画天背景
canvas.drawRoundRect(mDayBgRectF, mTimeBgRadius, mTimeBgRadius, mTimeTextBgPaint);
if (isShowTimeBgDivisionLine) {
// 画天背景中间的横线
canvas.drawLine(0, mTimeBgDivisionLineYPos, mTimeBgSize, mTimeBgDivisionLineYPos, mTimeTextBgDivisionLinePaint);
}
// 画天文字
canvas.drawText(formatNum(mHour), mDayBgRectF.centerX(), mTimeTextBaseY, mTimeTextPaint);
if (mSuffixDayTextWidth > 0) {
// 画天后缀
canvas.drawText(mSuffixDay, mTimeBgSize, mSuffixTextBaseY, mSuffixTextPaint);
}

// 计算小时x轴
mHourLeft = mTimeBgSize + mSuffixDayTextWidth;
}

// 判断显示小时
if (isShowHour) {
// 画小时背景
canvas.drawRoundRect(mHourBgRectF, mTimeBgRadius, mTimeBgRadius, mTimeTextBgPaint);
if (isShowTimeBgDivisionLine) {
// 画小时背景中间的横线
canvas.drawLine(mHourLeft, mTimeBgDivisionLineYPos, mTimeBgSize + mHourLeft, mTimeBgDivisionLineYPos, mTimeTextBgDivisionLinePaint);
}
// 画小时文字
canvas.drawText(formatNum(mHour), mHourBgRectF.centerX(), mTimeTextBaseY, mTimeTextPaint);
if (mSuffixHourTextWidth > 0) {
// 画小时后缀
canvas.drawText(mSuffixHour, mHourLeft + mTimeBgSize, mSuffixTextBaseY, mSuffixTextPaint);
}

// 计算分钟x轴
mMinuteLeft = mHourLeft + mTimeBgSize + mSuffixHourTextWidth;
} else {
mMinuteLeft = mHourLeft;
}

// 判断显示分钟
if (isShowMinute) {
// 画分钟背景
canvas.drawRoundRect(mMinuteBgRectF, mTimeBgRadius, mTimeBgRadius, mTimeTextBgPaint);
if (isShowTimeBgDivisionLine) {
// 画分钟背景中间的横线
canvas.drawLine(mMinuteLeft, mTimeBgDivisionLineYPos, mTimeBgSize + mMinuteLeft, mTimeBgDivisionLineYPos, mTimeTextBgDivisionLinePaint);
}
// 画分钟文字
canvas.drawText(formatNum(mMinute), mMinuteBgRectF.centerX(), mTimeTextBaseY, mTimeTextPaint);
if (mSuffixMinuteTextWidth > 0) {
// 画分钟后缀
canvas.drawText(mSuffixMinute, mMinuteLeft + mTimeBgSize, mSuffixTextBaseY, mSuffixTextPaint);
}

// 计算秒钟x轴
mSecondLeft = mMinuteLeft + mTimeBgSize + mSuffixMinuteTextWidth;
} else {
mSecondLeft = mMinuteLeft;
}

// 画秒钟背景
canvas.drawRoundRect(mSecondBgRectF, mTimeBgRadius, mTimeBgRadius, mTimeTextBgPaint);
if (isShowTimeBgDivisionLine) {
// 画秒钟背景中间的横线
canvas.drawLine(mSecondLeft, mTimeBgDivisionLineYPos, mTimeBgSize + mSecondLeft, mTimeBgDivisionLineYPos, mTimeTextBgDivisionLinePaint);
}
// 画秒钟文字
canvas.drawText(formatNum(mSecond), mSecondBgRectF.centerX(), mTimeTextBaseY, mTimeTextPaint);
if (mSuffixSecondTextWidth > 0) {
// 画秒钟后缀
canvas.drawText(mSuffixSecond, mSecondLeft + mTimeBgSize, mSuffixTextBaseY, mSuffixTextPaint);
}

if (isShowMillisecond) {
// 计算毫秒x轴
float mMillisecondLeft = mTimeBgSize + mSuffixSecondTextWidth + mSecondLeft;
// 画毫秒背景
canvas.drawRoundRect(mMillisecondBgRectF, mTimeBgRadius, mTimeBgRadius, mTimeTextBgPaint);
if (isShowTimeBgDivisionLine) {
// 画毫秒背景中间的横线
canvas.drawLine(mMillisecondLeft, mTimeBgDivisionLineYPos, mTimeBgSize + mMillisecondLeft, mTimeBgDivisionLineYPos, mTimeTextBgDivisionLinePaint);
}
// 画毫秒文字
canvas.drawText(formatMillisecond(), mMillisecondBgRectF.centerX(), mTimeTextBaseY, mTimeTextPaint);
if (mSuffixMillisecondTextWidth > 0) {
// 画毫秒后缀
canvas.drawText(mSuffixMillisecond, mMillisecondLeft + mTimeBgSize, mSuffixTextBaseY, mSuffixTextPaint);
}
}
}
}

@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
stop();
}

/**
* 启动倒计时
* @param millisecond 毫秒数
*/
public void start(long millisecond) {
if (millisecond <= 0) {
return ;
}

updateShow(millisecond);

if (null != mCountDownTimer) {
mCountDownTimer.cancel();
mCountDownTimer = null;
}

mCountDownTimer = new CountDownTimer(millisecond, 10) {
@Override
public void onFinish() {
// 倒计时结束
// 回调
if (null != mOnCountdownEndListener) {
mOnCountdownEndListener.onEnd();
}
}

@Override
public void onTick(long millisUntilFinished) {
updateShow(millisUntilFinished);
}
};
mCountDownTimer.start();
}

public void stop() {
if (null != mCountDownTimer) mCountDownTimer.cancel();
}

public void setShowHourView(boolean isShowHour) {
this.isShowHour = isShowHour;
invalidate();
}

public void setShowMillisecondView(boolean isShowMillisecond) {
this.isShowMillisecond = isShowMillisecond;
invalidate();
}

public void allShowZero() {
mHour = 0;
mMinute = 0;
mSecond = 0;
mMillisecond = 0;

invalidate();
}

public void setOnCountdownEndListener(OnCountdownEndListener onCountdownEndListener) {
this.mOnCountdownEndListener = onCountdownEndListener;
}

private void updateShow(long ms) {
mDay = (int)(ms / (1000 * 60 * 60 * 24));
mHour = (int)((ms % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
mMinute = (int)((ms % (1000 * 60 * 60)) / (1000 * 60));
mSecond = (int)((ms % (1000 * 60)) / 1000);
mMillisecond = (int)(ms % 1000);

invalidate();
}

private String formatNum(int time) {
return time < 10 ? "0"+time : String.valueOf(time);
}

private String formatMillisecond() {
String retMillisecondStr;

if (mMillisecond > 99) {
retMillisecondStr = String.valueOf(mMillisecond).substring(0, 2);
} else if (mMillisecond <= 9) {
retMillisecondStr = "0" + mMillisecond;
} else {
retMillisecondStr = String.valueOf(mMillisecond);
}

return retMillisecondStr;
}

public interface OnCountdownEndListener {
void onEnd();
}

public int dp2px(float dpValue) {
final float scale = mContext.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}

public float sp2px(float spValue) {
final float scale = mContext.getResources().getDisplayMetrics().scaledDensity;
return spValue * scale;
}

}



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

<declare-styleable name="CountdownView">
<attr name="timeBgColor" format="color" />
<attr name="timeBgRadius" format="dimension" />
<attr name="isShowTimeBgDivisionLine" format="boolean" />
<attr name="timeBgDivisionLineColor" format="color" />
<attr name="timeTextSize" format="dimension" />
<attr name="suffixTextSize" format="dimension" />
<attr name="timeTextColor" format="color" />
<attr name="suffixTextColor" format="color" />
<attr name="isHideTimeBackground" format="boolean" />
<attr name="isShowDay" format="boolean" />
<attr name="isShowHour" format="boolean" />
<attr name="isShowMinute" format="boolean" />
<attr name="isShowMillisecond" format="boolean" />
<attr name="suffix" format="string" />
<attr name="suffixDay" format="string" />
<attr name="suffixHour" format="string" />
<attr name="suffixMinute" format="string" />
<attr name="suffixSecond" format="string" />
<attr name="suffixMillisecond" format="string" />
<attr name="suffixGravity" >
<enum name="top" value="0" />
<enum name="center" value="1" />
<enum name="bottom" value="2" />
</attr>
</declare-styleable>

</resources>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值