iOS 进度条动画、秒表计时器
2018-03-26 本文已影响77人
Guomingjian
前段时间公司项目要新增一个副卡录音功能,效果图包含秒表计时器,底部一个计时进度条的动画。现在跟大家分享,欢迎大家交流o( ̄︶ ̄)o
·效果展示:
新增录音.gif·大家有一卡多号需求的可以下载:和多号
·实现过程
1、HDHTimerView.xib
TimeViewXib.png
2、HDHTimerView.swift
定义计时完成block(假设自定义秒数seconds=10s,则当计数到10,进度条为100%)
typealias completeCallback = (_ seconds : Int) -> Void
class HDHTimerView: UIView {
//MARK:-
@IBOutlet weak private var minutesLabel: UILabel!
@IBOutlet weak private var secondsLabel: UILabel!
@IBOutlet weak private var msLabel: UILabel!
//MARK:-
fileprivate var countTimer : Timer?
fileprivate var minutes : Int = 0 //分
fileprivate var seconds : Int = 0 //秒
fileprivate var ms : Int = 0 //毫秒
//MARK:- 外部属性
var maxSeconds : Int = 10 { //计时器停止时间.(单位秒,默认10)
didSet {
if maxSeconds < 0 || maxSeconds > 3600 {
maxSeconds = 10
}
}
}
var timeCompleteBlock : completeCallback?
}
外部调用API(方法前加@objc 为了供OC文件调用,fileprivate关键字是本文件内才有权限访问)
//MARK:-
extension HDHTimerView
{
//MARK:- 外部方法
/// 计数器开始
func start ()
{
stop()
countTimer = Timer.init(timeInterval: 0.01, target: self, selector: #selector(self.timeRunning), userInfo: nil, repeats: true)
RunLoop.main.add(countTimer!, forMode: .commonModes)
}
/// 计数器暂停
func stop()
{
countTimer?.invalidate()
countTimer = nil
}
/// 计数器复位
func reset()
{
stop()
minutes = 0
seconds = 0
ms = 0
updateUI()
}
//MARK:-
//开始计数
@objc fileprivate func timeRunning()
{
ms += 1
if ms == 100 {
seconds += 1
ms = 0;
}
if seconds == 60 {
minutes += 1;
seconds = 0;
}
let totalTime = self.getTotalTime()
if (totalTime == maxSeconds * 100) {
if timeCompleteBlock != nil {
timeCompleteBlock!(maxSeconds)
self.stop()
}
}
if minutes == 60 {
self.reset()
}
self.updateUI()
}
//获取当前计时总时间(毫秒)
func getTotalTime() -> (Int) {
var totalTime = ms
totalTime += seconds * 100
totalTime += minutes * 60 * 100
return totalTime
}
//刷新UI
fileprivate func updateUI()
{
minutesLabel.text = String.init(format: "%02d", minutes)
secondsLabel.text = String.init(format: "%02d", seconds)
msLabel.text = String.init(format: "%02d", ms)
}
}
//MARK:- 从xib中快速创建的类方法
extension HDHTimerView
{
class func getTimerView() -> HDHTimerView
{
return Bundle.main.loadNibNamed("HDHTimerView", owner: nil, options: nil)?.first as! HDHTimerView
}
}
调用示例:
//定义懒加载
fileprivate lazy var hdhTimeView : HDHTimerView = {
let timeView = HDHTimerView.getTimerView()
timeView.maxSeconds = kMaxSeconds
// timeView.backgroundColor = UIColor.groupTableViewBackground
let x = (kScreenW - timeView.frame.size.width) / 2.0
let rect = CGRect.init(x: x, y: 100, width: timeView.frame.size.width, height: timeView.frame.size.height)
timeView.frame = rect
return timeView
}()
//调用
view.addSubview(hdhTimeView)
hdhTimeView.timeCompleteBlock = { (maxSeconds) in
//print("计时到了:\(maxSeconds)秒")
self.stateLabel.text = "录音完成"
}
3、HDHProgressBarView.xib
进度条View初始长度为0,通过计时所占目标时间的百分比从而改变长度。
HDHProgressBarView.xib
4、HDHProgressBarView.swift
class HDHProgressBarView: UIView {
//MARK:-
@IBOutlet weak private var contentView: UIView!
//MARK:- 外部属性
var progressBarBackgroundColor : UIColor = UIColor.green {
didSet {
contentView.backgroundColor = progressBarBackgroundColor
}
}
var finishedTime : Int = 10 { //进度条完成所需时间,默认10秒
didSet {
if finishedTime < 0 {
finishedTime = 10
}
}
}
var refreshFrequency : TimeInterval = 0.1 { //进度条刷新频率(秒)
didSet {
if refreshFrequency > 2 || refreshFrequency < 0.01 {
refreshFrequency = 0.1
}
}
}
//MARK:-
fileprivate var progressTimer : Timer?
fileprivate var currentRunTime : CGFloat = 0 //当前进度时间(秒)
fileprivate var percentage : CGFloat = 0 //进度百分比
}
外部API
//MARK:-
extension HDHProgressBarView
{
//MARK:- 外部方法
/// 进度条开始
func start ()
{
stop()
progressTimer = Timer.init(timeInterval: refreshFrequency, target: self, selector: #selector(self.timeRunning), userInfo: nil, repeats: true)
RunLoop.main.add(progressTimer!, forMode: .commonModes)
}
/// 进度条暂停
func stop()
{
progressTimer?.invalidate()
progressTimer = nil
}
/// 进度条复位
func reset()
{
stop()
currentRunTime = 0
percentage = 0
updateUI()
}
//MARK:-
//进度开始加载
@objc fileprivate func timeRunning()
{
currentRunTime += CGFloat(refreshFrequency)
if currentRunTime > CGFloat(finishedTime)
{
self.stop()
return
}
percentage = currentRunTime / CGFloat(finishedTime)
self.updateUI()
}
//刷新UI
fileprivate func updateUI()
{
UIView.animate(withDuration: refreshFrequency) {
var frame = self.contentView.frame
let width = self.percentage * CGFloat(self.frame.size.width)
frame.size.width = width
self.contentView.frame = frame
}
}
}
//MARK:- 从xib中快速创建的类方法
extension HDHProgressBarView
{
class func getProgressBarView() -> HDHProgressBarView
{
return Bundle.main.loadNibNamed("HDHProgressBarView", owner: nil, options: nil)?.first as! HDHProgressBarView
}
}
调用示例:
//懒加载
fileprivate lazy var hdhProgressBarView : HDHProgressBarView = {
let progressBarView = HDHProgressBarView.getProgressBarView()
progressBarView.frame = CGRect(x: 0, y: 250, width: kScreenW, height: progressBarView.frame.size.height)
progressBarView.finishedTime = kMaxSeconds
return progressBarView
}()
//调用
view.addSubview(hdhProgressBarView)