一次比較懶的想法,不想自定義UITabBar,也不想用第三方框架,因而想嘗試修改蘋果私有類來達到部分效果git
在swift3及xcode8 beta2 環境下github
運行時遍歷出成員變量swift
var count:UInt32 = 0 let ivarlist = class_copyIvarList(NSClassFromString("UITabBarButton")!, &count) for index in 0..<numericCast(count) { let ivar = ivarlist![index] let ivarStr = String.init(utf8String: ivar_getName(ivar!)) print("\(ivarStr)") }
Optional("_hitRect") Optional("_info") Optional("_vibrancyEffectView") Optional("_label") Optional("_badge") Optional("_selectedIndicator") Optional("_selected") Optional("_infoInsets") Optional("_selectedInfoOffset") Optional("_infoOffset") Optional("_customSelectedIndicatorImage") Optional("_labelOffset") Optional("_buttonTintColorsForState") Optional("_contentTintColorsForState") Optional("_badgeColor") Optional("_badgeTextAttributesForState") Optional("_showsHighlightedState") Optional("_centerAllContents") Optional("_appearanceGuideClass") Optional("_tabBar")
其中 "_info" ,"_label" ,"_badge" 這三個是咱們須要的xcode
二、"_badge"是什麼呢?它真實類型是什麼,子控件及屬性名是什麼app
let tab = window?.rootViewController as! TabBarViewController for view in tab.tabBar.subviews { if view.isKind(of: NSClassFromString("UITabBarButton")! ) { let badgeView = view.value(forKeyPath: "_badge") print("1\(badgeView!.self)") let badge = badgeView as! UIView print("2\(badge.subviews)") } } }
1 <_UIBadgeView: 0x7fd671c336c0; frame = (33 2; 18 18); text = '1'; userInteractionEnabled = NO; layer = <CALayer: 0x608000031240>> 2 [<UIImageView: 0x7fd671c09570; frame = (0 0; 18 18); opaque = NO; userInteractionEnabled = NO; tintColor = UIExtendedSRGBColorSpace 1 0.231373 0.188235 1; layer = <CALayer: 0x60800002e9a0>>, <UILabel: 0x7fd671c33ba0; frame = (6 1; 6 16); text = '1'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x60800009c890>>]
var count:UInt32 = 0 let ivarlist = class_copyIvarList(NSClassFromString("_UIBadgeView")!, &count) for index in 0..<numericCast(count) { let ivar = ivarlist![index] let ivarStr = String.init(utf8String: ivar_getName(ivar!)) print("badge= \(ivarStr)") } badge= Optional("_label") badge= Optional("_background") badge= Optional("_mergedTextAttributes") badge= Optional("_text") badge= Optional("_textAttributes") badge= Optional("_backgroundColor")
自定義TabBarController裏,添加4個子控制器,其中第三個添加一個空的UIViewController,圖片爲UIImage(), 空的TabBarItem,只是讓這個系統生成的UITabBarButton佔好位置框架
自定義UIButton,添加到TabBar上,蓋住上述 空的UITabBarButton上ide
appDelegate成爲TabBarController的代理,監控tabBar的點擊學習
extension AppDelegate: UITabBarControllerDelegate { func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) { for view in tabBarController.tabBar.subviews { if view.isKind(of: NSClassFromString("UITabBarButton")! ) { // UITabBarButton是繼承UIControl的, 經過 按鈕的狀態 才判別是不是如今點擊的按鈕 let state = view.value(forKeyPath: "highlighted") let stateValue = state as! Int if stateValue == 1 { // 拿到當前點擊的 按鈕的imageView let imageView = view.value(forKeyPath: "_info") guard let temp = imageView else { return } let tabButtonImgView = temp as! UIImageView // 添加動畫 UIView.animate(withDuration: 0.2, animations: { tabButtonImgView.transform = CGAffineTransform(scaleX: 1.3, y: 1.3) }, completion: { (Bool) in tabButtonImgView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0) }) } } } } }
因爲UITabBarButton的子控件都是懶加載的,須要用控制器的tabBarItem 模型對UITabBarButton進行設置動畫
for button in tabBar.subviews { if button.isKind(of: NSClassFromString("UITabBarButton")! ) { let label = button.value(forKeyPath: "_label") as! UILabel // print("\(label.text)") if label.text == "" { // 經過label.text 肯定是購物車按鈕 那位置的 UITabBarButton let badgeButton = button.value(forKeyPath: "_badge") // print("\(badgeButton!.self)") guard let badgeView = badgeButton else { return } let badge = badgeView as! UIView // print("\(badge.subviews)") badge.frame.origin.x = 52 // 可根據須要計算 } } }
let tab = window?.rootViewController as! TabBarViewController for button in tab.tabBar.subviews { if button.isKind(of: NSClassFromString("UITabBarButton")! ) { let label = button.value(forKeyPath: "_label") as! UILabel // 外界經過 lable.text 區別出是咱們須要的 第三個UITabBarButton if label.text == "" { let badgeButton = button.value(forKeyPath: "_badge") guard let badgeView = badgeButton else { return } // 拿到 badge 控件 let badge = badgeView as! UIView // num變量爲 點擊加號按鈕, 商品個數 計量 let str:NSString = NSString.init(format: "%d", num) // kvc 設置屬性 badgeView.setValue(UIFont.systemFont(ofSize: 9), forKeyPath: "_label.font") badgeView.setValue(str, forKeyPath: "_label.text") let tabLabal = badgeView.value(forKeyPath: "_label") let label = tabLabal as! UILabel // 拿到lebel 計算label 的大小、尺寸 let size = str.size(attributes: [NSFontAttributeName : UIFont.systemFont(ofSize: 9)]) label.frame = CGRect(x: (badge.frame.size.width - size.width) * 0.5, y: (badge.frame.size.height - size.height) * 0.5, width: size.width, height: size.height) // 添加核心動畫 let scaleAni = CABasicAnimation() scaleAni.keyPath = "transform.scale" scaleAni.fromValue = 1.0 scaleAni.toValue = 1.2 scaleAni.autoreverses = true scaleAni.duration = 0.25 badge.layer.add(scaleAni, forKey: nil) } } }