目录

前言

一、项目效果展示

二、自定义TextView

2.1 自定义属性

2.2 配置属性

三、实现计时器

3.1 技术选型

3.2 代码实现

四、具体使用

4.1 布局引用

4.2 API调用

附:控件源代码


前言

因为最近项目里面需要记录通话时长,那么就要用到计时器,想着去网上搜一个现成的直接拿过来用呢,结果百度搜到的都是自定义倒计时控件,偶尔有几个是正向计时的,但是看了他们的实现都不太符合我的要求,所以最后只能自己动手写一个了。基本思路就是封装一个自定义的TextView,把计时的功能做到里面去,在需要计时的地方直接在XML里面全类名引用一下这个控件,然后代码里调用几个API就能搞定。既然思路已经确定,那就照着做吧。

一、项目效果展示

没有效果图总感觉自己是在耍流氓,所以还是录了一个,让大家能够更直观的感受一下这个控件是个什么玩意,如下图所示:

二、自定义TextView

关于自定义View相关的知识,这里并不会多讲,一是我们的重点不在这里,二是我本身掌握的也不好,自定义View这块是通往安卓高级工程师的必备技能,所以我还在努力。因此这里也会使用最简单的自定义View来封装这个控件,这里选用的是继承自系统控件TextView,所以这里不用重写onMeasure()方法去测量宽高,系统已经为我们测量好了,这样就极大的减轻了我们的工作量,那么接下来就正式来处理这个自定义View吧(简单级别的)。

2.1 自定义属性

关于自定义属性这个需要根据你自己的业务去考虑需要哪些属性,我这里就简单的写了两个,具体步骤如下:

在values文件夹下面新建一个attrs.xml文件,然后就可以定义我们需要的属性了,我这里只定义了文字大小和颜色:

<declare-styleable name="DigitalTimer"><attr name="textColor" format="color" /><attr name="textSize" format="dimension" />
</declare-styleable>

2.2 配置属性

定义一个类DigitalTimer继承自TextView,重写单参(代码中new的时候使用)和双参(布局中引入使用)的构造方法,然后开始配置需要的相关属性,代码如下:

private static final float DEFAULT_TEXT_SIZE = 12;
private static final int DEFAULT_TEXT_COLOR = Color.WHITE;
private float textSize;
private int textColor;public DigitalTimer(Context context) {super(context);init();
}public DigitalTimer(Context context, @Nullable AttributeSet attrs) {super(context, attrs);TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DigitalTimer);textSize = a.getDimension(R.styleable.DigitalTimer_textSize, DEFAULT_TEXT_SIZE);textColor = a.getColor(R.styleable.DigitalTimer_textColor, DEFAULT_TEXT_COLOR);a.recycle();init();
}//初始化
private void init() {setTextSize(textSize);setTextColor(textColor);setGravity(Gravity.CENTER);setBackgroundColor(Color.TRANSPARENT);
}

三、实现计时器

3.1 技术选型

这里选用的是rxjava中的interval操作符去实现的,链式调用看着就很舒服,先来了解一下interval操作符:

3.2 代码实现

这里调用interval操作符,构造方法里面分别传入了1,1,TimeUnit.SECONDS,分别表示延时1秒之后,每隔1秒发送一次数据,我们定义一个变量mCurrentSecond,用来记录当前的秒数,初始值为0,之后每次递增1,然后按照时分秒的转换关系进行相应的转换处理,最后把值设置到TextView上面去,具体代码如下:

    //开始计时public void start() {mDisposable = Observable.interval(1, 1, TimeUnit.SECONDS).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Long>() {@Overridepublic void accept(Long aLong) throws Exception {mCurrentSecond++;int hour = mCurrentSecond / 3600;int minute = (mCurrentSecond % 3600) / 60;int second = mCurrentSecond % 60;if (second < 10) { //处理秒seconds = "0" + second;} else {seconds = String.valueOf(second);}if (minute < 10) { //处理分minutes = "0" + minute;} else {minutes = String.valueOf(minute);}if (hour < 10) { //处理小时hours = "0" + hour;} else {hours = String.valueOf(hour);}//设置数据setText(String.format("%s:%s:%s", hours, minutes, seconds));}}, new Consumer<Throwable>() {@Overridepublic void accept(Throwable throwable) throws Exception {LogUtil.e("自定义计时器数据异常------" + throwable.getMessage());}});}

相应的还封装了停止计时和数据清零的方法,如下所示:

    //停止计时public void stop() {LogUtil.e("当前计时时长----->" + getText().toString());if (mDisposable != null) {mDisposable.dispose();}}//重置数据@SuppressLint("SetTextI18n")public void reset() {mCurrentSecond = 0;setText("00:00:00");stop();}

四、具体使用

4.1 布局引用

首先在布局文件中引用这个控件:

<com.nari.yihui.widget.DigitalTimerandroid:id="@+id/timer"android:layout_width="wrap_content"android:layout_height="wrap_content"app:textSize="@dimen/font_size_18"app:textColor="@color/colorAccent"android:text="00:00:00"/>

4.2 API调用

然后在对应的界面中调用开始计时、停止计时的方法就OK了:

    @OnClick({R.id.button1, R.id.button2, R.id.button3})public void onClick(View view) {switch (view.getId()) {case R.id.button1:timer.start();break;case R.id.button2:timer.stop();break;case R.id.button3:timer.reset();break;}}

这样就完成了这个控件的封装,是不是还挺简单的,如果发现了什么问题,欢迎给我留言。

附:控件源代码

package com.nari.yihui.widget;import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.TextView;import com.nari.yihui.R;
import com.nari.yihui.utils.LogUtil;import java.util.concurrent.TimeUnit;import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;/*** 包名:com.nari.yihui.widget* 文件名:   DigitalTimer* 创建时间:   2018/7/25 11:29* 作者:     纪安奇* 作用:自定义计时器控件*/@SuppressWarnings({"RedundantThrows"})
@SuppressLint("AppCompatCustomView")
public class DigitalTimer extends TextView {private static final float DEFAULT_TEXT_SIZE = 12;private static final int DEFAULT_TEXT_COLOR = Color.WHITE;private float textSize;private int textColor;private int mCurrentSecond = 0; //当前秒private String hours, minutes, seconds; //展示的时分秒private Disposable mDisposable;public DigitalTimer(Context context) {super(context);init();}public DigitalTimer(Context context, @Nullable AttributeSet attrs) {super(context, attrs);TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DigitalTimer);textSize = a.getDimension(R.styleable.DigitalTimer_textSize, DEFAULT_TEXT_SIZE);textColor = a.getColor(R.styleable.DigitalTimer_textColor, DEFAULT_TEXT_COLOR);a.recycle();init();}//初始化private void init() {setTextSize(textSize);setTextColor(textColor);setGravity(Gravity.CENTER);setBackgroundColor(Color.TRANSPARENT);}//开始计时public void start() {mDisposable = Observable.interval(1, 1, TimeUnit.SECONDS).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Long>() {@Overridepublic void accept(Long aLong) throws Exception {mCurrentSecond++;int hour = mCurrentSecond / 3600;int minute = (mCurrentSecond % 3600) / 60;int second = mCurrentSecond % 60;if (second < 10) { //处理秒seconds = "0" + second;} else {seconds = String.valueOf(second);}if (minute < 10) { //处理分minutes = "0" + minute;} else {minutes = String.valueOf(minute);}if (hour < 10) { //处理小时hours = "0" + hour;} else {hours = String.valueOf(hour);}//设置数据setText(String.format("%s:%s:%s", hours, minutes, seconds));}}, new Consumer<Throwable>() {@Overridepublic void accept(Throwable throwable) throws Exception {LogUtil.e("自定义计时器数据异常------" + throwable.getMessage());}});}//停止计时public void stop() {LogUtil.e("当前计时时长----->" + getText().toString());if (mDisposable != null) {mDisposable.dispose();}}//重置数据@SuppressLint("SetTextI18n")public void reset() {mCurrentSecond = 0;setText("00:00:00");stop();}}

安卓自定义计时器控件相关推荐

  1. 安卓自定义日期控件(仿QQ,IOS7)

    还记得上篇:高大上的安卓日期时间选择器,本篇是根据上篇修改而来,先看下qq中日期选择的效果: 鉴于目前还没有相似的开源日期控件,因此本人花费了一些时间修改了下之前的日期控件,效果如图: 虽说相似度不是 ...

  2. 安卓自定义日期控件(仿QQ,IOS7)续

    本篇是在原来的基础上修改了界面效果,使其更加接近ios7,qq等日期选择控件,看图: 源码地址:http://download.csdn.net/detail/baiyuliang2013/87601 ...

  3. 一个自定义的安卓验证码输入框控件、银行卡归属类型查询

    一个自定义的安卓验证码输入框控件.银行卡归属类型查询. GitHub:https://github.com/longer96/VerifyCode Dependency Gradle dependen ...

  4. 安卓中自定义view控件代替radiogroup实现颜色渐变效果的写法

    利用自定义控件代替radiogroup,同时实现在使用viewpager进行翻页的时候,实现颜色渐变的效果. 一: 首先创建一个自定义view类继承自View类,所有的控件均用canvas绘制出来(包 ...

  5. android如何绑定事件,Android_安卓为按钮控件绑定事件的五种方式

    一.写在最前面 本次,来介绍一下安卓中为控件--Button绑定事件的五种方式. 二.具体的实现 第一种:直接绑定在Button控件上: 步骤1.在Button控件上设置android:onClick ...

  6. android 自定义ImageView控件实现圆形图片-适用于用户头像

    android开发中常常涉及到一种情况,就是将用户上传的图片以圆形样式显示,但是用户上传的图片可以有直角.圆角.正方形等多种不确定样式,这时就用到了自定义ImageView控件,在安卓客户端使接收到的 ...

  7. Android 手机卫士--自定义组合控件构件布局结构

    由于设置中心条目中的布局都很类似,所以可以考虑使用自定义组合控件来简化实现 本文地址:http://www.cnblogs.com/wuyudong/p/5909043.html,转载请注明源地址. ...

  8. Android View体系(十)自定义组合控件

    相关文章 Android View体系(一)视图坐标系 Android View体系(二)实现View滑动的六种方法 Android View体系(三)属性动画 Android View体系(四)从源 ...

  9. iOS自定义View 控件自动计算size能力

    iOS自定义View 控件自动计算size能力 背景 在使用 UILabel 和 UIImage 的时候,不用指定宽高约束,控件也不会报约束缺失,还可以根据内容自己确定适合的宽高,特别适合 Xib 和 ...

最新文章

  1. openssl aes加解密的使用
  2. Linux软件源apt,仓库,包的概念
  3. Java中的迭代与递归
  4. Android onKeyDown、onKeyUp、dispatchKeyEvent的区别
  5. [WORK]局数据系统
  6. 吴恩达CNN卷积神经网络第二周作业Keras Tutorial
  7. java变量中不属于复合类型的数据类型是_2006新版JAVA题解(JAVA简单数据类型)...
  8. cache相关命中率的运算_Linux cache命中率查看
  9. python求高阶导数_Pythorch中的高阶梯度
  10. win10开始菜单添加磁贴_Windows 10开始菜单磁贴美化教程
  11. landsat 8 卫星 波段介绍 及组合
  12. SolidWorks有限元分析流程
  13. php 数组json失败,php json转数组出错
  14. Win7手工查找notepad.exe的IAT
  15. 「计算机网络」五层因特网协议栈的简要介绍和分组名称
  16. 按键精灵 - 安卓版 - 罗盘 - 八向方位模拟 - 自动寻路
  17. mysql straight join_在MySQL中使用STRAIGHT_JOIN的教程
  18. php $_SERVER 学习详解
  19. 姚班普信男--一篇后人类观察田野笔记
  20. (资讯)华为员工利用Bug越权访问机密卖给第三方,获利1.6万元,被判有期徒刑一年

热门文章

  1. 关节空间阻抗控制器设计的个人理解
  2. 【学习笔记】大数据搜索与挖掘
  3. 记一次发现某餐饮企业二维码支付漏洞的经历
  4. Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.7.0:repackage (repackage)
  5. (加快设计)推荐一个SketchUp的3D模型库
  6. 红帽linux系统下载6,红帽linux系统下载|红帽linux(RHEL)下载 v6.5 beta 官方版_小皮网...
  7. 视觉SLAM十四讲 ch3 (三维空间刚体运动)笔记
  8. 什么是单工、半双工和双工通信(最详细)
  9. steamship 使用gpt-4
  10. (02)Cartographer源码无死角解析-(32) LocalTrajectoryBuilder2D::AddRangeData()→点云的体素滤波