控件效果如下图: 切换时会有动画效果。 原理,使用贝塞尔曲线做动画,参考 iOS开发:仿余额宝金额跳动效果。 代码如下:
UICTabView.swift:
import UIKit
@IBDesignable class UICTabView: UIView {
var delegate:UICTabViewDelegate?
//标记动画结束,没结束不响应事件
var animationFinish = true
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
//tab数量
@IBInspectable var tabCount:Int = 3 {
didSet {
setNeedsDisplay()
}
}
///字体大小
@IBInspectable var tabFontSize:CGFloat = 15 {
didSet {
setNeedsDisplay()
}
}
///tab文本颜色
@IBInspectable var textColor:UIColor = UIColor.whiteColor() {
didSet {
setNeedsDisplay()
}
}
///指示条的高度
@IBInspectable var indicatorHeight:CGFloat = 10 {
didSet {
setNeedsDisplay()
}
}
///选中项
@IBInspectable var selectedIndex:Int = 0 {
didSet {
if (selectedIndex > tabCount - 1) {
selectedIndex = tabCount - 1
}
indicatorViewContainer?.selectedIndex = selectedIndex
}
}
//tab上显示的文字
var tabTexts:\[String\] = \[\]
var tabWidth:CGFloat = 0
//指示器container
var indicatorViewContainer:UICTabIndicatorViewContainer!
override func drawRect(rect: CGRect) {
for view in self.subviews {
view.removeFromSuperview()
}
let width = self.frame.size.width
let height = self.frame.size.height
tabWidth = width / CGFloat(tabCount)
for i in 0..= pointNumber) {
indicator?.frame.origin.x = tabWidth * CGFloat(selectedIndex)
(self.superview as! UICTabView).animationFinish = true
}else{
let currentPoint: NSArray = allPoints.objectAtIndex(indexCurrent) as! NSArray
let value = currentPoint.objectAtIndex(1) as! Float
let currentTime = currentPoint.objectAtIndex(0) as! Float
++indexCurrent
lastTime = currentTime;
indicator?.frame.origin.x = CGFloat(value)
//延迟调用changeNumberBySelector方法,重新设string
let delay = durationPerFrame * Double(NSEC\_PER\_MSEC)
let time = dispatch\_time(DISPATCH\_TIME_NOW, Int64(delay))
//循环调用自己
dispatch\_after(time, dispatch\_get\_main\_queue(), {
NSThread.detachNewThreadSelector(Selector("smoothMove"), toTarget:self, withObject: nil)
})
}
}
}
}
//MARK: 委托协议
///tab切换事件
@objc protocol UICTabViewDelegate {
///tab点击
optional func tabView(tabView:UICTabView,selectedTabIndex:Int)
}
可在storyboard中设置tab数量,指示器颜色等,但tab内容需要在代码里设 ViewController中使用:
import UIKit
class HomeViewController: UIViewController,UICTabViewDelegate {
@IBOutlet weak var headerView: UIView!
@IBOutlet weak var tabView: UICTabView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
//定义渐变的颜色,多色渐变太魔性了,我们就用两种颜色
let topColor = UIColor(red: (206/255.0), green: (53/255.0), blue: (33/255.0), alpha: 1)
let buttomColor = UIColor(red: (215/255.0), green: (75/255.0), blue: (58/255.0), alpha: 1)
//将颜色和颜色的位置定义在数组内
let gradientColors: \[CGColor\] = \[topColor.CGColor, buttomColor.CGColor\]
let gradientLocations: \[CGFloat\] = \[0.0, 1.0\]
setGradientBackground(self.headerView, gradientColors: gradientColors, gradientLocations: gradientLocations)
tabView.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tabView(tabView:UICTabView,selectedTabIndex:Int) {
//tab切换
PLog.d("切到\\(selectedTabIndex)")
}
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return UIStatusBarStyle.LightContent
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}