android倒计时 是在原有TextView的基础上进行二次开发的自定义View

效果图

这个主要是结合了android的CountDownTimer,这个一般就是发送短信的倒计时。

包含功能

倒计时时间超过一个小时显示 时:分:秒

时间小于一小时显示:分 :秒:毫秒

支持时间带有边框

实现思路

倒计时实现上可以通过Android的CountDownTimer进行时间上的倒计时功能

倒计时要有背景框,实现思路上有3个TextView设置,这个比较麻烦对于CountDownTimer回调回来的时间需要切割,怪麻烦的,还有一种就是 设计整个一个TextView,在TextView的onDraw()方法中,对它进行二次绘制,这样就可以了

这里采用对就是一个TextView,对它的onDraw()进行二次绘制。

直接上代码

package xx.xx.xx.widget;

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.os.CountDownTimer;

import android.os.Parcel;

import android.os.Parcelable;

import android.support.annotation.Nullable;

import android.support.v7.widget.AppCompatTextView;

import android.util.AttributeSet;

import xx.xx.xx.R;

/**

* Created by odvl on 2016/12/5.

*/

public class CountDownTimeTextView extends AppCompatTextView {

private static final String SPLIT = " : ";

private static final String BLANK = " ";

private static final int RADIUS = 4;

static final long MS_IN_A_DAY = 1000 * 60 * 60 * 24;

static final long MS_IN_AN_HOUR = 1000 * 60 * 60;

static final long MS_IN_A_MINUTE = 1000 * 60;

static final long MS_IN_A_SECOND = 1000;

public static final String DEFAULT_TIME = " 00 : 00 : 00 ";

private String simTime = "";

private CountDownTimer timer;

private Paint borderPaint;

private boolean border = false;

public CountDownTimeTextView(Context context) {

super(context);

init(context, null);

}

public CountDownTimeTextView(Context context, @Nullable AttributeSet attrs) {

super(context, attrs);

init(context, attrs);

}

public CountDownTimeTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init(context, attrs);

}

private void init(Context context, AttributeSet attrs) {

if (attrs != null) {

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CountDownTimeTextView);

if (ta.hasValue(R.styleable.CountDownTimeTextView_border)) {

border = ta.getBoolean(R.styleable.CountDownTimeTextView_border, false);

borderPaint = new Paint();

borderPaint.setDither(true);

borderPaint.setAntiAlias(true);

borderPaint.setStyle(Paint.Style.STROKE);

borderPaint.setStrokeWidth(1f);

borderPaint.setColor(Color.parseColor("#999999"));

}

}

}

@Override

public Parcelable onSaveInstanceState() {

Parcelable parcelable = super.onSaveInstanceState();

SaveState ss = new SaveState(parcelable);

ss.text = simTime;

return ss;

}

@Override

public void onRestoreInstanceState(Parcelable state) {

SaveState ss = (SaveState) state;

super.onRestoreInstanceState(ss.getSuperState());

setText(ss.text);

}

static class SaveState extends BaseSavedState {

private String text;

public SaveState(Parcel source) {

super(source);

text = (String) source.readString();

}

public SaveState(Parcelable superState) {

super(superState);

}

@Override

public void writeToParcel(Parcel out, int flags) {

super.writeToParcel(out, flags);

out.writeString(text);

}

public static final Parcelable.Creator CREATOR = new Creator() {

@Override

public SaveState createFromParcel(Parcel source) {

return new SaveState(source);

}

@Override

public SaveState[] newArray(int size) {

return new SaveState[size];

}

};

}

public void setTime(long time, final OnFinishListener listener) {

if (timer != null) {

timer.cancel();

}

setText(DEFAULT_TIME);

timer = new CountDownTimer(time, 1) {

@Override

public void onTick(long l) {

if (l >= 1 * 60 * 60 * 1000) { //超过1小时

simTime = getTimeFromLong(l);

} else {

simTime = getMillisecondsTimes(l);

}

setText(simTime);

}

@Override

public void onFinish() {

setText(DEFAULT_TIME);

listener.onFinish();

}

};

}

private String getMillisecondsTimes(long l) {

l = l % MS_IN_AN_HOUR;

long minutes = l / MS_IN_A_MINUTE; //分

l = l % MS_IN_A_MINUTE;

long seconds = l / MS_IN_A_SECOND; //秒

l = l % MS_IN_A_SECOND;

long milliseconds = l / 10; //毫秒

StringBuffer sb = new StringBuffer();

if (minutes >= 10) {

sb.append(BLANK + String.valueOf(minutes) + SPLIT);

} else {

sb.append(BLANK + "0" + String.valueOf(minutes) + SPLIT);

}

if (seconds >= 10) {

sb.append(String.valueOf(seconds) + SPLIT);

} else {

sb.append("0" + String.valueOf(seconds) + SPLIT);

}

if (milliseconds >= 10) {

sb.append(String.valueOf(milliseconds) + BLANK);

} else {

sb.append("0" + String.valueOf(milliseconds) + BLANK);

}

String result = sb.toString();

return result;

}

public String getTimeFromLong(long diff) {

diff = diff % MS_IN_A_DAY;

long numHours = diff / MS_IN_AN_HOUR;

diff = diff % MS_IN_AN_HOUR;

long numMinutes = diff / MS_IN_A_MINUTE;

diff = diff % MS_IN_A_MINUTE;

long numSeconds = diff / MS_IN_A_SECOND;

StringBuffer buf = new StringBuffer();

if (numHours >= 10) { //hour

buf.append(BLANK + numHours + SPLIT);

} else if (numHours >= 0 && numHours < 10) {

buf.append(BLANK + "0" + numHours + SPLIT);

}

if (numMinutes >= 10) { //minutes

buf.append(numMinutes + SPLIT);

} else if (numMinutes >= 0 && numMinutes < 10) {

buf.append("0" + numMinutes + SPLIT);

}

if (numSeconds >= 10) { //seconds

buf.append(numSeconds + BLANK);

} else if (numSeconds >= 0 && numSeconds < 10) {

buf.append("0" + numSeconds + BLANK);

}

String result = buf.toString();

return result;

}

public void start() {

timer.start();

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

if (border) {

String text = getText().toString();

String[] result = text.split(":");

float[] length = new float[result.length];

float splitWidth = getPaint().measureText(":");

float blankWidth = getPaint().measureText(" ");

if (result.length > 0) {

float height = canvas.getHeight() - getPaddingBottom();

for (int i = 0; i < result.length; i++) {

float value = getPaint().measureText(result[i]);

length[i] = value;

}

if (result.length == 3) {

RectF r1 = new RectF((int) (getPaddingLeft() + blankWidth / 2), getPaddingTop(), (int) (getPaddingLeft() + length[0] - blankWidth / 2), (int) (getPaddingTop() + height));

RectF r2 = new RectF((int) (r1.right + blankWidth + splitWidth), getPaddingTop(), (int) (r1.right + splitWidth + length[1]), (int) (getPaddingTop() + height));

RectF r3 = new RectF((int) (r2.right + blankWidth + splitWidth), getPaddingTop(), (int) (r2.right + splitWidth + length[2]), (int) (getPaddingTop() + height));

canvas.drawRoundRect(r1, RADIUS, RADIUS, borderPaint);

canvas.drawRoundRect(r2, RADIUS, RADIUS, borderPaint);

canvas.drawRoundRect(r3, RADIUS, RADIUS, borderPaint);

} else {

return;

}

}

}

}

public interface OnFinishListener {

void onFinish();

}

}

android 酷炫倒计时,android 好用的倒计时相关推荐

  1. Android 酷炫 倒计时的实现

    Android实现倒计时,出现在比如像一些跑步记录的App等等.使用TimerTask及Handler协作实现~~上效果图先~        采用自定义View(CircleTimerView)来完成 ...

  2. 酷炫的Android开源项目

    抽屉菜单 MaterialDrawer ★7337 - 安卓抽屉效果实现方案 Side-Menu.Android ★3865 - 创意边侧菜单 FlowingDrawer ★1744 - 向右滑动流动 ...

  3. 黄聪:Android酷炫实用的开源框架(UI框架)(转)

    Android酷炫实用的开源框架(UI框架) 前言 忙碌的工作终于可以停息一段时间了,最近突然有一个想法,就是自己写一个app,所以找了一些合适开源控件,这样更加省时,再此分享给大家,希望能对大家有帮 ...

  4. 提供 Android 酷炫的开屏动画 (awesome-opening-animation)

    FancyView 项目地址:wongzy/FancyView  简介:提供 Android 酷炫的开屏动画 (awesome-opening-animation) 更多:作者   提 Bug 标签: ...

  5. ym——Android酷炫实用的开源框架(UI框架)(终)

    转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103),谢谢支持! 前言 好久没写博文了,最近工作比较忙,剩下的一点点时间在做自己的项目,在Android ...

  6. android 酷炫编辑框_25个实用酷炫的Android开源UI框架

    最近找了一些合适开源控件,这样在日常工作中会更加省时,再此分享给大家,希望能对大家有帮助,此博文介绍的都是UI上面的框架,接下来会有其他的开源框架(如:HTTP框架.DB框架). 1.Side-Men ...

  7. 直播系统源码App中Android酷炫礼物动画直播平台源码搭建教程(上篇)

    直播系统源码App中Android酷炫礼物动画直播平台源码搭建教程(上篇) 在当下移动直播火爆的年代,如果你曾经使用过移动端直播应用,相信会被里面那令人惊叹的礼物动画效果迷住,比如像下面这样的效果. ...

  8. 酷炫的Android QQ 开源了吧!!

    酷炫的Android QQ 啥时候开源!?作为android的爱好者的我,总想近距离的去感受她的内在美: 自面世以来就受到各界热捧的Android,被誉为下一代无线设备系统的标杆."天生的互 ...

  9. 成品app直播源码中Android酷炫礼物动画实现方案(上篇)

    成品app直播源码中Android酷炫礼物动画实现方案(上篇) +在当下移动直播火爆的年代,如果你曾经使用过移动端直播应用,相信会被里面那令人惊叹的礼物动画效果迷住,比如像下面这样的效果. 从开发人员 ...

  10. 直播App中Android酷炫礼物动画如何通过直播程序源码实现方案

    直播App中Android酷炫礼物动画如何通过直播程序源码实现方案 这个动画,如果输出成GIF的话,要3MB,尺寸是750*750.在上一篇文章中已经介绍过几种被否掉的方法,这里再稍作补充说明,如果使 ...

最新文章

  1. 涉密文件检查工具_肇庆高要销毁资料文件公司粉碎销毁文件资料公司欢迎您
  2. Spring Boot 2.x基础教程:使用Flyway管理数据库版本
  3. 升技主板RAID磁盘阵列图解
  4. Python之pandas:对pandas中dataframe数据中的索引输出、修改、重命名等详细攻略
  5. Java面试总结系列之Collections.sort()
  6. java递归算法实现
  7. 深入理解ES6之迭代器与生成器
  8. android重新编译res,使用 gradle 在编译时动态设置 Android resValue / BuildConfig / Manifes中lt;meta-datagt;变量的值...
  9. 【NetWebApi】接口参数传递笔记
  10. 给fiddle 解密_fiddler学习笔记2 字段说明;移动设备、解密证书
  11. linux查看u盘的分区,在Linux下访问windows分区以及U盘
  12. 【BZOJ4205】卡牌配对
  13. 乐安全 支持x86_android-x86-4.4-r2运行程序总是停止运行怎么处理
  14. linux主机路由命令,linux查看路由命令
  15. (2)安装宝塔与docker及docker镜像下载加速
  16. 37.伪造参数错误的ICMP数据包
  17. 物业计算机管理系统论文,小区物业管理系统设计毕业论文
  18. 微信订阅号利用订阅号助手发布信息
  19. android - studio版本控制文件颜色代表意思
  20. openFOAM C++代码的一些特性

热门文章

  1. 检测Maven依赖中介
  2. GlassFish 4带来了Java EE 7
  3. 在Java Web应用程序中阻止CSRF
  4. 在Grails 2.0中使用Servlet 3.0异步功能
  5. Quartz Scheduler插件–隐藏的宝藏
  6. 线程故事:Web应用程序中的ThreadLocal
  7. 使用MVC模式制作游戏-教程和简介
  8. 一些定义–测试技术9
  9. 移动端设备标识码/设备唯一标识码/设备唯一性
  10. MacBook 如何通过命令终端进入 U 盘内的目录