隨著工作壓力的增大,工作和休息不能平衡,導致效率下降.這個小Demo模仿了Tomate的核心理念和動畫.
在這個基礎上優化了核心代碼,減少了反復重繪圖片和計算,降低了CPU的使用率,使得擴展性增加,更好的適配不同的機型不同的系統.
雖然界面設計的很簡單,沒有給設置時間等,但是最合理的模式其實還是默認模式,也就是25(工作)+5(休息)模式的反復進行,把效率提高到最大.
原項目:Tomate
本項目:WorkTimer

下面給出設計的布局
iPhone5下的布局:

模擬器下的布局:

其中最主要的還是對核心動畫進行優化:
import UIKit
import QuartzCore
/**
* Update Timer UI
*/
public protocol TimerViewProtocol {
func updateTimer(durationInSeconds: CGFloat)
}
extension CGFloat {
func numberTimerFormate() -> String {
return String(format: "%02d", Int(self))
}
}
class TimerView: UIView, TimerViewProtocol {
var totalTimeInSeconds: CGFloat {
get{
return totalTime
}
set{
totalTime = newValue
initTimerState()
}
}
private var totalTime: CGFloat = 0.0
private var radius: CGFloat = 0.0
private var timerCenter: CGPoint = CGPoint(x: 0.0, y: 0.0)
private let startAngle: CGFloat = -CGFloat(M_PI) / 2
private let endAngle: CGFloat = 3 * CGFloat(M_PI) / 2
private var minutesRingPath: UIBezierPath!
private var secondsRingPath: UIBezierPath!
private var fullRingPath: UIBezierPath!
private var numberTimeLabel = UILabel()
private let minutesShapeLayer: CAShapeLayer = CAShapeLayer()
private let secondsShapeLayer: CAShapeLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
layer.addSublayer(minutesShapeLayer)
layer.addSublayer(secondsShapeLayer)
addSubview(numberTimeLabel)
addConstraints(settingNumberTimeLabelConstraint())
backgroundColor = UIColor.clearColor()
//backgroundColor = UIColor.redColor()///////////////////////////////////////////////////////////////////////////////////////////
print("init TimerView complete")
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func drawRect(rect: CGRect) {
timerCenter = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect))
radius = rect.width / 2 - 10
settingMinuteStyle()
settingSecondStyle()
settingTimeLabelStyle()
drawRing()
initTimerState()
print("Timer View drawRect:\(rect)-timerCenter:\(timerCenter)-radius:\(radius)")
}
func updateTimer(durationInSeconds: CGFloat) {
minutesShapeLayer.strokeEnd = durationInSeconds / totalTime
secondsShapeLayer.strokeEnd = durationInSeconds % 60 / 60
numberTimeLabel.text = (durationInSeconds / 60).numberTimerFormate() + ":" + (durationInSeconds % 60).numberTimerFormate()
}
private func initTimerState() {
minutesShapeLayer.strokeEnd = 0.0
secondsShapeLayer.strokeEnd = 0.0
numberTimeLabel.text = CGFloat(0).numberTimerFormate() + ":" + CGFloat(0).numberTimerFormate()
let dashLength = 2 * radius * CGFloat(M_PI) / (totalTime / 60.0);
minutesShapeLayer.lineDashPattern = [dashLength - 2, 2]
print("init Time State complete")
}
private func settingMinuteStyle() {
minutesRingPath = UIBezierPath(arcCenter: timerCenter, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
minutesShapeLayer.path = minutesRingPath.CGPath
minutesShapeLayer.fillColor = UIColor.clearColor().CGColor
minutesShapeLayer.strokeColor = TimerStyleKit.timerColor.CGColor
minutesShapeLayer.lineWidth = 4.0
print("setting Minute Style")
}
private func settingSecondStyle() {
secondsRingPath = UIBezierPath(arcCenter: timerCenter, radius: radius - 4, startAngle: startAngle, endAngle: endAngle, clockwise: true)
secondsShapeLayer.path = secondsRingPath.CGPath
secondsShapeLayer.fillColor = UIColor.clearColor().CGColor
secondsShapeLayer.strokeColor = TimerStyleKit.timerColor.CGColor
secondsShapeLayer.lineWidth = 1.0
print("setting Second Style")
}
private func settingTimeLabelStyle() {
numberTimeLabel.textAlignment = .Center
numberTimeLabel.textColor = TimerStyleKit.timerColor
numberTimeLabel.font = UIFont(name: "HelveticaNeue-Thin", size: radius / 2 + 10)
//numberTimeLabel.font = UIFont(name: "HelveticaNeue-Thin", size: 80)
numberTimeLabel.adjustsFontSizeToFitWidth = true
numberTimeLabel.center = timerCenter
//numberTimeLabel.backgroundColor = UIColor.greenColor()///////////////////////////////////////////////////////////////////////////////////////////
print("setting TimeLabel Style")
}
private func drawRing() {
TimerStyleKit.timerColor.set()
fullRingPath = UIBezierPath(arcCenter: timerCenter, radius: radius + 4, startAngle: startAngle, endAngle: endAngle, clockwise: true)
fullRingPath.lineWidth = 1.0
fullRingPath.stroke()
}
private func settingNumberTimeLabelConstraint() -> [NSLayoutConstraint] {
numberTimeLabel.translatesAutoresizingMaskIntoConstraints = false
var constraints = [NSLayoutConstraint]()
if #available(iOS 9.0, *) {
constraints.append(numberTimeLabel.centerXAnchor.constraintEqualToAnchor(centerXAnchor))
constraints.append(numberTimeLabel.centerYAnchor.constraintEqualToAnchor(centerYAnchor))
} else {
// Fallback on earlier versions
let views = ["numberTimeLabel": numberTimeLabel]
constraints += NSLayoutConstraint.constraintsWithVisualFormat("H:|-40-[numberTimeLabel]-40-|", options: [], metrics: [:], views: views)
//constraints += NSLayoutConstraint.constraintsWithVisualFormat("V:|-40-[numberTimeLabel]-40-|", options: [], metrics: [:], views: views)
}
return constraints
}
}
原項目中反復重繪和計算固定不變的一些屬性,導致cpu占有率還是挺高的.
由於項目經驗不足,只能造輪子了.
經過這個小Demo的制作,也了解了很多UIView和代碼約束布局的相關知識.
其實我們做東西不僅僅只追求好看,而是應該合理的優化.
合理的設計模式和代碼優化,包括好的擴展性,才是我們應該追求的.