initial
This commit is contained in:
438
Pods/ESTabBarController-swift/Sources/ESTabBar.swift
generated
Normal file
438
Pods/ESTabBarController-swift/Sources/ESTabBar.swift
generated
Normal file
@@ -0,0 +1,438 @@
|
||||
//
|
||||
// ESTabBar.swift
|
||||
//
|
||||
// Created by Vincent Li on 2017/2/8.
|
||||
// Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
|
||||
/// 对原生的UITabBarItemPositioning进行扩展,通过UITabBarItemPositioning设置时,系统会自动添加insets,这使得添加背景样式的需求变得不可能实现。ESTabBarItemPositioning完全支持原有的item Position 类型,除此之外还支持完全fill模式。
|
||||
///
|
||||
/// - automatic: UITabBarItemPositioning.automatic
|
||||
/// - fill: UITabBarItemPositioning.fill
|
||||
/// - centered: UITabBarItemPositioning.centered
|
||||
/// - fillExcludeSeparator: 完全fill模式,布局不覆盖tabBar顶部分割线
|
||||
/// - fillIncludeSeparator: 完全fill模式,布局覆盖tabBar顶部分割线
|
||||
public enum ESTabBarItemPositioning : Int {
|
||||
|
||||
case automatic
|
||||
|
||||
case fill
|
||||
|
||||
case centered
|
||||
|
||||
case fillExcludeSeparator
|
||||
|
||||
case fillIncludeSeparator
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// 对UITabBarDelegate进行扩展,以支持UITabBarControllerDelegate的相关方法桥接
|
||||
internal protocol ESTabBarDelegate: NSObjectProtocol {
|
||||
|
||||
/// 当前item是否支持选中
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - tabBar: tabBar
|
||||
/// - item: 当前item
|
||||
/// - Returns: Bool
|
||||
func tabBar(_ tabBar: UITabBar, shouldSelect item: UITabBarItem) -> Bool
|
||||
|
||||
/// 当前item是否需要被劫持
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - tabBar: tabBar
|
||||
/// - item: 当前item
|
||||
/// - Returns: Bool
|
||||
func tabBar(_ tabBar: UITabBar, shouldHijack item: UITabBarItem) -> Bool
|
||||
|
||||
/// 当前item的点击被劫持
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - tabBar: tabBar
|
||||
/// - item: 当前item
|
||||
/// - Returns: Void
|
||||
func tabBar(_ tabBar: UITabBar, didHijack item: UITabBarItem)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// ESTabBar是高度自定义的UITabBar子类,通过添加UIControl的方式实现自定义tabBarItem的效果。目前支持tabBar的大部分属性的设置,例如delegate,items,selectedImge,itemPositioning,itemWidth,itemSpacing等,以后会更加细致的优化tabBar原有属性的设置效果。
|
||||
open class ESTabBar: UITabBar {
|
||||
|
||||
internal weak var customDelegate: ESTabBarDelegate?
|
||||
|
||||
/// tabBar中items布局偏移量
|
||||
public var itemEdgeInsets = UIEdgeInsets.zero
|
||||
/// 是否设置为自定义布局方式,默认为空。如果为空,则通过itemPositioning属性来设置。如果不为空则忽略itemPositioning,所以当tabBar的itemCustomPositioning属性不为空时,如果想改变布局规则,请设置此属性而非itemPositioning。
|
||||
public var itemCustomPositioning: ESTabBarItemPositioning? {
|
||||
didSet {
|
||||
if let itemCustomPositioning = itemCustomPositioning {
|
||||
switch itemCustomPositioning {
|
||||
case .fill:
|
||||
itemPositioning = .fill
|
||||
case .automatic:
|
||||
itemPositioning = .automatic
|
||||
case .centered:
|
||||
itemPositioning = .centered
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
self.reload()
|
||||
}
|
||||
}
|
||||
/// tabBar自定义item的容器view
|
||||
internal var containers = [ESTabBarItemContainer]()
|
||||
/// 缓存当前tabBarController用来判断是否存在"More"Tab
|
||||
internal weak var tabBarController: UITabBarController?
|
||||
/// 自定义'More'按钮样式,继承自ESTabBarItemContentView
|
||||
open var moreContentView: ESTabBarItemContentView? = ESTabBarItemMoreContentView.init() {
|
||||
didSet { self.reload() }
|
||||
}
|
||||
|
||||
open override var items: [UITabBarItem]? {
|
||||
didSet {
|
||||
self.reload()
|
||||
}
|
||||
}
|
||||
|
||||
open var isEditing: Bool = false {
|
||||
didSet {
|
||||
if oldValue != isEditing {
|
||||
self.updateLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open override func setItems(_ items: [UITabBarItem]?, animated: Bool) {
|
||||
super.setItems(items, animated: animated)
|
||||
self.reload()
|
||||
}
|
||||
|
||||
open override func beginCustomizingItems(_ items: [UITabBarItem]) {
|
||||
ESTabBarController.printError("beginCustomizingItems(_:) is unsupported in ESTabBar.")
|
||||
super.beginCustomizingItems(items)
|
||||
}
|
||||
|
||||
open override func endCustomizing(animated: Bool) -> Bool {
|
||||
ESTabBarController.printError("endCustomizing(_:) is unsupported in ESTabBar.")
|
||||
return super.endCustomizing(animated: animated)
|
||||
}
|
||||
|
||||
open override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
self.updateLayout()
|
||||
}
|
||||
|
||||
open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
|
||||
var b = super.point(inside: point, with: event)
|
||||
if !b {
|
||||
for container in containers {
|
||||
if container.point(inside: CGPoint.init(x: point.x - container.frame.origin.x, y: point.y - container.frame.origin.y), with: event) {
|
||||
b = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal extension ESTabBar /* Layout */ {
|
||||
|
||||
func updateLayout() {
|
||||
guard let tabBarItems = self.items else {
|
||||
ESTabBarController.printError("empty items")
|
||||
return
|
||||
}
|
||||
|
||||
let tabBarButtons = subviews.filter { subview -> Bool in
|
||||
if let cls = NSClassFromString("UITabBarButton") {
|
||||
return subview.isKind(of: cls)
|
||||
}
|
||||
return false
|
||||
} .sorted { (subview1, subview2) -> Bool in
|
||||
return subview1.frame.origin.x < subview2.frame.origin.x
|
||||
}
|
||||
|
||||
if isCustomizing {
|
||||
for (idx, _) in tabBarItems.enumerated() {
|
||||
tabBarButtons[idx].isHidden = false
|
||||
moreContentView?.isHidden = true
|
||||
}
|
||||
for (_, container) in containers.enumerated(){
|
||||
container.isHidden = true
|
||||
}
|
||||
} else {
|
||||
for (idx, item) in tabBarItems.enumerated() {
|
||||
if let _ = item as? ESTabBarItem {
|
||||
tabBarButtons[idx].isHidden = true
|
||||
} else {
|
||||
tabBarButtons[idx].isHidden = false
|
||||
}
|
||||
if isMoreItem(idx), let _ = moreContentView {
|
||||
tabBarButtons[idx].isHidden = true
|
||||
}
|
||||
}
|
||||
for (_, container) in containers.enumerated(){
|
||||
container.isHidden = false
|
||||
}
|
||||
}
|
||||
|
||||
var layoutBaseSystem = true
|
||||
if let itemCustomPositioning = itemCustomPositioning {
|
||||
switch itemCustomPositioning {
|
||||
case .fill, .automatic, .centered:
|
||||
break
|
||||
case .fillIncludeSeparator, .fillExcludeSeparator:
|
||||
layoutBaseSystem = false
|
||||
}
|
||||
}
|
||||
|
||||
if layoutBaseSystem {
|
||||
// System itemPositioning
|
||||
for (idx, container) in containers.enumerated(){
|
||||
if !tabBarButtons[idx].frame.isEmpty {
|
||||
container.frame = tabBarButtons[idx].frame
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Custom itemPositioning
|
||||
var x: CGFloat = itemEdgeInsets.left
|
||||
var y: CGFloat = itemEdgeInsets.top
|
||||
switch itemCustomPositioning! {
|
||||
case .fillExcludeSeparator:
|
||||
if y <= 0.0 {
|
||||
y += 1.0
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
let width = bounds.size.width - itemEdgeInsets.left - itemEdgeInsets.right
|
||||
let height = bounds.size.height - y - itemEdgeInsets.bottom
|
||||
let eachWidth = itemWidth == 0.0 ? width / CGFloat(containers.count) : itemWidth
|
||||
let eachSpacing = itemSpacing == 0.0 ? 0.0 : itemSpacing
|
||||
|
||||
for container in containers {
|
||||
container.frame = CGRect.init(x: x, y: y, width: eachWidth, height: height)
|
||||
x += eachWidth
|
||||
x += eachSpacing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal extension ESTabBar /* Actions */ {
|
||||
|
||||
func isMoreItem(_ index: Int) -> Bool {
|
||||
return ESTabBarController.isShowingMore(tabBarController) && (index == (items?.count ?? 0) - 1)
|
||||
}
|
||||
|
||||
func removeAll() {
|
||||
for container in containers {
|
||||
container.removeFromSuperview()
|
||||
}
|
||||
containers.removeAll()
|
||||
}
|
||||
|
||||
func reload() {
|
||||
removeAll()
|
||||
guard let tabBarItems = self.items else {
|
||||
ESTabBarController.printError("empty items")
|
||||
return
|
||||
}
|
||||
for (idx, item) in tabBarItems.enumerated() {
|
||||
let container = ESTabBarItemContainer.init(self, tag: 1000 + idx)
|
||||
self.addSubview(container)
|
||||
self.containers.append(container)
|
||||
|
||||
if let item = item as? ESTabBarItem, let contentView = item.contentView {
|
||||
container.addSubview(contentView)
|
||||
}
|
||||
if self.isMoreItem(idx), let moreContentView = moreContentView {
|
||||
container.addSubview(moreContentView)
|
||||
}
|
||||
}
|
||||
|
||||
self.updateAccessibilityLabels()
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
|
||||
@objc func highlightAction(_ sender: AnyObject?) {
|
||||
guard let container = sender as? ESTabBarItemContainer else {
|
||||
return
|
||||
}
|
||||
let newIndex = max(0, container.tag - 1000)
|
||||
guard newIndex < items?.count ?? 0, let item = self.items?[newIndex], item.isEnabled == true else {
|
||||
return
|
||||
}
|
||||
|
||||
if (customDelegate?.tabBar(self, shouldSelect: item) ?? true) == false {
|
||||
return
|
||||
}
|
||||
|
||||
if let item = item as? ESTabBarItem {
|
||||
item.contentView?.highlight(animated: true, completion: nil)
|
||||
} else if self.isMoreItem(newIndex) {
|
||||
moreContentView?.highlight(animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func dehighlightAction(_ sender: AnyObject?) {
|
||||
guard let container = sender as? ESTabBarItemContainer else {
|
||||
return
|
||||
}
|
||||
let newIndex = max(0, container.tag - 1000)
|
||||
guard newIndex < items?.count ?? 0, let item = self.items?[newIndex], item.isEnabled == true else {
|
||||
return
|
||||
}
|
||||
|
||||
if (customDelegate?.tabBar(self, shouldSelect: item) ?? true) == false {
|
||||
return
|
||||
}
|
||||
|
||||
if let item = item as? ESTabBarItem {
|
||||
item.contentView?.dehighlight(animated: true, completion: nil)
|
||||
} else if self.isMoreItem(newIndex) {
|
||||
moreContentView?.dehighlight(animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func selectAction(_ sender: AnyObject?) {
|
||||
guard let container = sender as? ESTabBarItemContainer else {
|
||||
return
|
||||
}
|
||||
select(itemAtIndex: container.tag - 1000, animated: true)
|
||||
}
|
||||
|
||||
@objc func select(itemAtIndex idx: Int, animated: Bool) {
|
||||
let newIndex = max(0, idx)
|
||||
let currentIndex = (selectedItem != nil) ? (items?.firstIndex(of: selectedItem!) ?? -1) : -1
|
||||
guard newIndex < items?.count ?? 0, let item = self.items?[newIndex], item.isEnabled == true else {
|
||||
return
|
||||
}
|
||||
|
||||
if (customDelegate?.tabBar(self, shouldSelect: item) ?? true) == false {
|
||||
return
|
||||
}
|
||||
|
||||
if (customDelegate?.tabBar(self, shouldHijack: item) ?? false) == true {
|
||||
customDelegate?.tabBar(self, didHijack: item)
|
||||
if animated {
|
||||
if let item = item as? ESTabBarItem {
|
||||
item.contentView?.select(animated: animated, completion: {
|
||||
item.contentView?.deselect(animated: false, completion: nil)
|
||||
})
|
||||
} else if self.isMoreItem(newIndex) {
|
||||
moreContentView?.select(animated: animated, completion: {
|
||||
self.moreContentView?.deselect(animated: animated, completion: nil)
|
||||
})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if currentIndex != newIndex {
|
||||
if currentIndex != -1 && currentIndex < items?.count ?? 0{
|
||||
if let currentItem = items?[currentIndex] as? ESTabBarItem {
|
||||
currentItem.contentView?.deselect(animated: animated, completion: nil)
|
||||
} else if self.isMoreItem(currentIndex) {
|
||||
moreContentView?.deselect(animated: animated, completion: nil)
|
||||
}
|
||||
}
|
||||
if let item = item as? ESTabBarItem {
|
||||
item.contentView?.select(animated: animated, completion: nil)
|
||||
} else if self.isMoreItem(newIndex) {
|
||||
moreContentView?.select(animated: animated, completion: nil)
|
||||
}
|
||||
} else if currentIndex == newIndex {
|
||||
if let item = item as? ESTabBarItem {
|
||||
item.contentView?.reselect(animated: animated, completion: nil)
|
||||
} else if self.isMoreItem(newIndex) {
|
||||
moreContentView?.reselect(animated: animated, completion: nil)
|
||||
}
|
||||
|
||||
if let tabBarController = tabBarController {
|
||||
var navVC: UINavigationController?
|
||||
if let n = tabBarController.selectedViewController as? UINavigationController {
|
||||
navVC = n
|
||||
} else if let n = tabBarController.selectedViewController?.navigationController {
|
||||
navVC = n
|
||||
}
|
||||
|
||||
if let navVC = navVC {
|
||||
if navVC.viewControllers.contains(tabBarController) {
|
||||
if navVC.viewControllers.count > 1 && navVC.viewControllers.last != tabBarController {
|
||||
navVC.popToViewController(tabBarController, animated: true);
|
||||
}
|
||||
} else {
|
||||
if navVC.viewControllers.count > 1 {
|
||||
navVC.popToRootViewController(animated: animated)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
delegate?.tabBar?(self, didSelect: item)
|
||||
self.updateAccessibilityLabels()
|
||||
}
|
||||
|
||||
func updateAccessibilityLabels() {
|
||||
guard let tabBarItems = self.items, tabBarItems.count == self.containers.count else {
|
||||
return
|
||||
}
|
||||
|
||||
for (idx, item) in tabBarItems.enumerated() {
|
||||
let container = self.containers[idx]
|
||||
container.accessibilityIdentifier = item.accessibilityIdentifier
|
||||
container.accessibilityTraits = item.accessibilityTraits
|
||||
|
||||
if item == selectedItem {
|
||||
container.accessibilityTraits = container.accessibilityTraits.union(.selected)
|
||||
}
|
||||
|
||||
if let explicitLabel = item.accessibilityLabel {
|
||||
container.accessibilityLabel = explicitLabel
|
||||
container.accessibilityHint = item.accessibilityHint ?? container.accessibilityHint
|
||||
} else {
|
||||
var accessibilityTitle = ""
|
||||
if let item = item as? ESTabBarItem {
|
||||
accessibilityTitle = item.accessibilityLabel ?? item.title ?? ""
|
||||
}
|
||||
if self.isMoreItem(idx) {
|
||||
accessibilityTitle = NSLocalizedString("More_TabBarItem", bundle: Bundle(for:ESTabBarController.self), comment: "")
|
||||
}
|
||||
|
||||
let formatString = NSLocalizedString(item == selectedItem ? "TabBarItem_Selected_AccessibilityLabel" : "TabBarItem_AccessibilityLabel",
|
||||
bundle: Bundle(for: ESTabBarController.self),
|
||||
comment: "")
|
||||
container.accessibilityLabel = String(format: formatString, accessibilityTitle, idx + 1, tabBarItems.count)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
152
Pods/ESTabBarController-swift/Sources/ESTabBarController.swift
generated
Normal file
152
Pods/ESTabBarController-swift/Sources/ESTabBarController.swift
generated
Normal file
@@ -0,0 +1,152 @@
|
||||
//
|
||||
// ESTabBarController.swift
|
||||
//
|
||||
// Created by Vincent Li on 2017/2/8.
|
||||
// Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
/// 是否需要自定义点击事件回调类型
|
||||
public typealias ESTabBarControllerShouldHijackHandler = ((_ tabBarController: UITabBarController, _ viewController: UIViewController, _ index: Int) -> (Bool))
|
||||
/// 自定义点击事件回调类型
|
||||
public typealias ESTabBarControllerDidHijackHandler = ((_ tabBarController: UITabBarController, _ viewController: UIViewController, _ index: Int) -> (Void))
|
||||
|
||||
open class ESTabBarController: UITabBarController, ESTabBarDelegate {
|
||||
|
||||
/// 打印异常
|
||||
public static func printError(_ description: String) {
|
||||
#if DEBUG
|
||||
print("ERROR: ESTabBarController catch an error '\(description)' \n")
|
||||
#endif
|
||||
}
|
||||
|
||||
/// 当前tabBarController是否存在"More"tab
|
||||
public static func isShowingMore(_ tabBarController: UITabBarController?) -> Bool {
|
||||
return tabBarController?.moreNavigationController.parent != nil
|
||||
}
|
||||
|
||||
/// Ignore next selection or not.
|
||||
fileprivate var ignoreNextSelection = false
|
||||
|
||||
/// Should hijack select action or not.
|
||||
open var shouldHijackHandler: ESTabBarControllerShouldHijackHandler?
|
||||
/// Hijack select action.
|
||||
open var didHijackHandler: ESTabBarControllerDidHijackHandler?
|
||||
|
||||
/// Observer tabBarController's selectedViewController. change its selection when it will-set.
|
||||
open override var selectedViewController: UIViewController? {
|
||||
willSet {
|
||||
guard let newValue = newValue else {
|
||||
// if newValue == nil ...
|
||||
return
|
||||
}
|
||||
guard !ignoreNextSelection else {
|
||||
ignoreNextSelection = false
|
||||
return
|
||||
}
|
||||
guard let tabBar = self.tabBar as? ESTabBar, let items = tabBar.items, let index = viewControllers?.firstIndex(of: newValue) else {
|
||||
return
|
||||
}
|
||||
let value = (ESTabBarController.isShowingMore(self) && index > items.count - 1) ? items.count - 1 : index
|
||||
tabBar.select(itemAtIndex: value, animated: false)
|
||||
}
|
||||
}
|
||||
|
||||
/// Observer tabBarController's selectedIndex. change its selection when it will-set.
|
||||
open override var selectedIndex: Int {
|
||||
willSet {
|
||||
guard !ignoreNextSelection else {
|
||||
ignoreNextSelection = false
|
||||
return
|
||||
}
|
||||
guard let tabBar = self.tabBar as? ESTabBar, let items = tabBar.items else {
|
||||
return
|
||||
}
|
||||
let value = (ESTabBarController.isShowingMore(self) && newValue > items.count - 1) ? items.count - 1 : newValue
|
||||
tabBar.select(itemAtIndex: value, animated: false)
|
||||
}
|
||||
}
|
||||
|
||||
/// Customize set tabBar use KVC.
|
||||
open override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
let tabBar = { () -> ESTabBar in
|
||||
let tabBar = ESTabBar()
|
||||
tabBar.delegate = self
|
||||
tabBar.customDelegate = self
|
||||
tabBar.tabBarController = self
|
||||
return tabBar
|
||||
}()
|
||||
self.setValue(tabBar, forKey: "tabBar")
|
||||
}
|
||||
|
||||
// MARK: - UITabBar delegate
|
||||
open override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
|
||||
guard let idx = tabBar.items?.firstIndex(of: item) else {
|
||||
return;
|
||||
}
|
||||
if idx == tabBar.items!.count - 1, ESTabBarController.isShowingMore(self) {
|
||||
ignoreNextSelection = true
|
||||
selectedViewController = moreNavigationController
|
||||
return;
|
||||
}
|
||||
if let vc = viewControllers?[idx] {
|
||||
ignoreNextSelection = true
|
||||
selectedIndex = idx
|
||||
delegate?.tabBarController?(self, didSelect: vc)
|
||||
}
|
||||
}
|
||||
|
||||
open override func tabBar(_ tabBar: UITabBar, willBeginCustomizing items: [UITabBarItem]) {
|
||||
if let tabBar = tabBar as? ESTabBar {
|
||||
tabBar.updateLayout()
|
||||
}
|
||||
}
|
||||
|
||||
open override func tabBar(_ tabBar: UITabBar, didEndCustomizing items: [UITabBarItem], changed: Bool) {
|
||||
if let tabBar = tabBar as? ESTabBar {
|
||||
tabBar.updateLayout()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ESTabBar delegate
|
||||
internal func tabBar(_ tabBar: UITabBar, shouldSelect item: UITabBarItem) -> Bool {
|
||||
if let idx = tabBar.items?.firstIndex(of: item), let vc = viewControllers?[idx] {
|
||||
return delegate?.tabBarController?(self, shouldSelect: vc) ?? true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
internal func tabBar(_ tabBar: UITabBar, shouldHijack item: UITabBarItem) -> Bool {
|
||||
if let idx = tabBar.items?.firstIndex(of: item), let vc = viewControllers?[idx] {
|
||||
return shouldHijackHandler?(self, vc, idx) ?? false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
internal func tabBar(_ tabBar: UITabBar, didHijack item: UITabBarItem) {
|
||||
if let idx = tabBar.items?.firstIndex(of: item), let vc = viewControllers?[idx] {
|
||||
didHijackHandler?(self, vc, idx)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
107
Pods/ESTabBarController-swift/Sources/ESTabBarItem.swift
generated
Normal file
107
Pods/ESTabBarController-swift/Sources/ESTabBarItem.swift
generated
Normal file
@@ -0,0 +1,107 @@
|
||||
//
|
||||
// ESTabBarController.swift
|
||||
//
|
||||
// Created by Vincent Li on 2017/2/8.
|
||||
// Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
/*
|
||||
* ESTabBarItem继承自UITabBarItem,目的是为ESTabBarItemContentView提供UITabBarItem属性的设置。
|
||||
* 目前支持大多常用的属性,例如image, selectedImage, title, tag 等。
|
||||
*
|
||||
* Unsupport properties:
|
||||
* MARK: UIBarItem properties
|
||||
* 1. var isEnabled: Bool
|
||||
* 2. var landscapeImagePhone: UIImage?
|
||||
* 3. var imageInsets: UIEdgeInsets
|
||||
* 4. var landscapeImagePhoneInsets: UIEdgeInsets
|
||||
* 5. func setTitleTextAttributes(_ attributes: [String : Any]?, for state: UIControlState)
|
||||
* 6. func titleTextAttributes(for state: UIControlState) -> [String : Any]?
|
||||
* MARK: UITabBarItem properties
|
||||
* 7. var titlePositionAdjustment: UIOffset
|
||||
* 8. func setBadgeTextAttributes(_ textAttributes: [String : Any]?, for state: UIControlState)
|
||||
* 9. func badgeTextAttributes(for state: UIControlState) -> [String : Any]?
|
||||
*/
|
||||
@available(iOS 8.0, *)
|
||||
open class ESTabBarItem: UITabBarItem {
|
||||
|
||||
/// Customize content view
|
||||
open var contentView: ESTabBarItemContentView?
|
||||
|
||||
// MARK: UIBarItem properties
|
||||
open override var title: String? // default is nil
|
||||
{
|
||||
didSet { self.contentView?.title = title }
|
||||
}
|
||||
|
||||
open override var image: UIImage? // default is nil
|
||||
{
|
||||
didSet { self.contentView?.image = image }
|
||||
}
|
||||
|
||||
// MARK: UITabBarItem properties
|
||||
open override var selectedImage: UIImage? // default is nil
|
||||
{
|
||||
didSet { self.contentView?.selectedImage = selectedImage }
|
||||
}
|
||||
|
||||
open override var badgeValue: String? // default is nil
|
||||
{
|
||||
get { return contentView?.badgeValue }
|
||||
set(newValue) { contentView?.badgeValue = newValue }
|
||||
}
|
||||
|
||||
/// Override UITabBarItem.badgeColor, make it available for iOS8.0 and later.
|
||||
/// If this item displays a badge, this color will be used for the badge's background. If set to nil, the default background color will be used instead.
|
||||
@available(iOS 8.0, *)
|
||||
open override var badgeColor: UIColor? {
|
||||
get { return contentView?.badgeColor }
|
||||
set(newValue) { contentView?.badgeColor = newValue }
|
||||
}
|
||||
|
||||
open override var tag: Int // default is 0
|
||||
{
|
||||
didSet { self.contentView?.tag = tag }
|
||||
}
|
||||
|
||||
/* The unselected image is autogenerated from the image argument. The selected image
|
||||
is autogenerated from the selectedImage if provided and the image argument otherwise.
|
||||
To prevent system coloring, provide images with UIImageRenderingModeAlwaysOriginal (see UIImage.h)
|
||||
*/
|
||||
public init(_ contentView: ESTabBarItemContentView = ESTabBarItemContentView(), title: String? = nil, image: UIImage? = nil, selectedImage: UIImage? = nil, tag: Int = 0) {
|
||||
super.init()
|
||||
self.contentView = contentView
|
||||
self.setTitle(title, image: image, selectedImage: selectedImage, tag: tag)
|
||||
}
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
open func setTitle(_ title: String? = nil, image: UIImage? = nil, selectedImage: UIImage? = nil, tag: Int = 0) {
|
||||
self.title = title
|
||||
self.image = image
|
||||
self.selectedImage = selectedImage
|
||||
self.tag = tag
|
||||
}
|
||||
|
||||
}
|
||||
116
Pods/ESTabBarController-swift/Sources/ESTabBarItemBadgeView.swift
generated
Normal file
116
Pods/ESTabBarController-swift/Sources/ESTabBarItemBadgeView.swift
generated
Normal file
@@ -0,0 +1,116 @@
|
||||
//
|
||||
// ESTabBarItemBadgeView.swift
|
||||
//
|
||||
// Created by Vincent Li on 2017/2/8.
|
||||
// Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
/*
|
||||
* ESTabBarItemBadgeView
|
||||
* 这个类定义了item中使用的badge视图样式,默认为ESTabBarItemBadgeView类对象。
|
||||
* 你可以设置ESTabBarItemContentView的badgeView属性为自定义的ESTabBarItemBadgeView子类,这样就可以轻松实现 自定义通知样式了。
|
||||
*/
|
||||
open class ESTabBarItemBadgeView: UIView {
|
||||
|
||||
/// 默认颜色
|
||||
public static var defaultBadgeColor = UIColor(red: 255.0/255.0, green: 59.0/255.0, blue: 48.0/255.0, alpha: 1.0)
|
||||
|
||||
/// Badge color
|
||||
open var badgeColor: UIColor? = defaultBadgeColor {
|
||||
didSet {
|
||||
imageView.backgroundColor = badgeColor
|
||||
}
|
||||
}
|
||||
|
||||
/// Badge value, supprot nil, "", "1", "someText". Hidden when nil. Show Little dot style when "".
|
||||
open var badgeValue: String? {
|
||||
didSet {
|
||||
badgeLabel.text = badgeValue
|
||||
}
|
||||
}
|
||||
|
||||
/// Image view
|
||||
open var imageView: UIImageView = {
|
||||
let imageView = UIImageView.init(frame: CGRect.zero)
|
||||
imageView.backgroundColor = .clear
|
||||
return imageView
|
||||
}()
|
||||
|
||||
/// 显示badgeValue的Label
|
||||
open var badgeLabel: UILabel = {
|
||||
let badgeLabel = UILabel.init(frame: CGRect.zero)
|
||||
badgeLabel.backgroundColor = .clear
|
||||
badgeLabel.textColor = .white
|
||||
badgeLabel.font = UIFont.systemFont(ofSize: 13.0)
|
||||
badgeLabel.textAlignment = .center
|
||||
return badgeLabel
|
||||
}()
|
||||
|
||||
/// Initializer
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.addSubview(imageView)
|
||||
self.addSubview(badgeLabel)
|
||||
self.imageView.backgroundColor = badgeColor
|
||||
}
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
/*
|
||||
* 通过layoutSubviews()布局子视图,你可以通过重写此方法实现自定义布局。
|
||||
**/
|
||||
open override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
guard let badgeValue = badgeValue else {
|
||||
imageView.isHidden = true
|
||||
badgeLabel.isHidden = true
|
||||
return
|
||||
}
|
||||
|
||||
imageView.isHidden = false
|
||||
badgeLabel.isHidden = false
|
||||
|
||||
if badgeValue == "" {
|
||||
imageView.frame = CGRect.init(origin: CGPoint.init(x: (bounds.size.width - 8.0) / 2.0, y: (bounds.size.height - 8.0) / 2.0), size: CGSize.init(width: 8.0, height: 8.0))
|
||||
} else {
|
||||
imageView.frame = bounds
|
||||
}
|
||||
imageView.layer.cornerRadius = imageView.bounds.size.height / 2.0
|
||||
badgeLabel.sizeToFit()
|
||||
badgeLabel.center = imageView.center
|
||||
}
|
||||
|
||||
/*
|
||||
* 通过此方法计算badge视图需要占用父视图的frame大小,通过重写此方法可以自定义badge视图的大小。
|
||||
* 如果你需要自定义badge视图在Content中的位置,可以设置Content的badgeOffset属性。
|
||||
*/
|
||||
open override func sizeThatFits(_ size: CGSize) -> CGSize {
|
||||
guard let _ = badgeValue else {
|
||||
return CGSize.init(width: 18.0, height: 18.0)
|
||||
}
|
||||
let textSize = badgeLabel.sizeThatFits(CGSize.init(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude))
|
||||
return CGSize.init(width: max(18.0, textSize.width + 10.0), height: 18.0)
|
||||
}
|
||||
|
||||
}
|
||||
67
Pods/ESTabBarController-swift/Sources/ESTabBarItemContainer.swift
generated
Normal file
67
Pods/ESTabBarController-swift/Sources/ESTabBarItemContainer.swift
generated
Normal file
@@ -0,0 +1,67 @@
|
||||
//
|
||||
// ESTabBarItemContainer.swift
|
||||
//
|
||||
// Created by Vincent Li on 2017/2/8.
|
||||
// Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
internal class ESTabBarItemContainer: UIControl {
|
||||
|
||||
internal init(_ target: AnyObject?, tag: Int) {
|
||||
super.init(frame: CGRect.zero)
|
||||
self.tag = tag
|
||||
self.addTarget(target, action: #selector(ESTabBar.selectAction(_:)), for: .touchUpInside)
|
||||
self.addTarget(target, action: #selector(ESTabBar.highlightAction(_:)), for: .touchDown)
|
||||
self.addTarget(target, action: #selector(ESTabBar.highlightAction(_:)), for: .touchDragEnter)
|
||||
self.addTarget(target, action: #selector(ESTabBar.dehighlightAction(_:)), for: .touchDragExit)
|
||||
self.backgroundColor = .clear
|
||||
self.isAccessibilityElement = true
|
||||
}
|
||||
|
||||
internal required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
internal override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
for subview in self.subviews {
|
||||
if let subview = subview as? ESTabBarItemContentView {
|
||||
subview.frame = CGRect.init(x: subview.insets.left, y: subview.insets.top, width: bounds.size.width - subview.insets.left - subview.insets.right, height: bounds.size.height - subview.insets.top - subview.insets.bottom)
|
||||
subview.updateLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
|
||||
var b = super.point(inside: point, with: event)
|
||||
if !b {
|
||||
for subview in self.subviews {
|
||||
if subview.point(inside: CGPoint.init(x: point.x - subview.frame.origin.x, y: point.y - subview.frame.origin.y), with: event) {
|
||||
b = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
}
|
||||
394
Pods/ESTabBarController-swift/Sources/ESTabBarItemContentView.swift
generated
Normal file
394
Pods/ESTabBarController-swift/Sources/ESTabBarItemContentView.swift
generated
Normal file
@@ -0,0 +1,394 @@
|
||||
//
|
||||
// ESTabBarContentView.swift
|
||||
//
|
||||
// Created by Vincent Li on 2017/2/8.
|
||||
// Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
public enum ESTabBarItemContentMode : Int {
|
||||
|
||||
case alwaysOriginal // Always set the original image size
|
||||
|
||||
case alwaysTemplate // Always set the image as a template image size
|
||||
}
|
||||
|
||||
|
||||
open class ESTabBarItemContentView: UIView {
|
||||
|
||||
// MARK: - PROPERTY SETTING
|
||||
|
||||
/// 设置contentView的偏移
|
||||
open var insets = UIEdgeInsets.zero
|
||||
|
||||
/// 是否被选中
|
||||
open var selected = false
|
||||
|
||||
/// 是否处于高亮状态
|
||||
open var highlighted = false
|
||||
|
||||
/// 是否支持高亮
|
||||
open var highlightEnabled = true
|
||||
|
||||
/// 文字颜色
|
||||
open var textColor = UIColor(white: 0.57254902, alpha: 1.0) {
|
||||
didSet {
|
||||
if !selected { titleLabel.textColor = textColor }
|
||||
}
|
||||
}
|
||||
|
||||
/// 高亮时文字颜色
|
||||
open var highlightTextColor = UIColor(red: 0.0, green: 0.47843137, blue: 1.0, alpha: 1.0) {
|
||||
didSet {
|
||||
if selected { titleLabel.textColor = highlightIconColor }
|
||||
}
|
||||
}
|
||||
|
||||
/// icon颜色
|
||||
open var iconColor = UIColor(white: 0.57254902, alpha: 1.0) {
|
||||
didSet {
|
||||
if !selected { imageView.tintColor = iconColor }
|
||||
}
|
||||
}
|
||||
|
||||
/// 高亮时icon颜色
|
||||
open var highlightIconColor = UIColor(red: 0.0, green: 0.47843137, blue: 1.0, alpha: 1.0) {
|
||||
didSet {
|
||||
if selected { imageView.tintColor = highlightIconColor }
|
||||
}
|
||||
}
|
||||
|
||||
/// 背景颜色
|
||||
open var backdropColor = UIColor.clear {
|
||||
didSet {
|
||||
if !selected { backgroundColor = backdropColor }
|
||||
}
|
||||
}
|
||||
|
||||
/// 高亮时背景颜色
|
||||
open var highlightBackdropColor = UIColor.clear {
|
||||
didSet {
|
||||
if selected { backgroundColor = highlightBackdropColor }
|
||||
}
|
||||
}
|
||||
|
||||
open var title: String? {
|
||||
didSet {
|
||||
self.titleLabel.text = title
|
||||
self.updateLayout()
|
||||
}
|
||||
}
|
||||
|
||||
/// Icon imageView renderingMode, default is .alwaysTemplate like UITabBarItem
|
||||
open var renderingMode: UIImage.RenderingMode = .alwaysTemplate {
|
||||
didSet {
|
||||
self.updateDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
/// Item content mode, default is .alwaysTemplate like UITabBarItem
|
||||
open var itemContentMode: ESTabBarItemContentMode = .alwaysTemplate {
|
||||
didSet {
|
||||
self.updateDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
/// Icon imageView's image
|
||||
open var image: UIImage? {
|
||||
didSet {
|
||||
if !selected { self.updateDisplay() }
|
||||
}
|
||||
}
|
||||
|
||||
open var selectedImage: UIImage? {
|
||||
didSet {
|
||||
if selected { self.updateDisplay() }
|
||||
}
|
||||
}
|
||||
|
||||
open var imageView: UIImageView = {
|
||||
let imageView = UIImageView.init(frame: CGRect.zero)
|
||||
imageView.backgroundColor = .clear
|
||||
return imageView
|
||||
}()
|
||||
|
||||
open var titleLabel: UILabel = {
|
||||
let titleLabel = UILabel.init(frame: CGRect.zero)
|
||||
titleLabel.backgroundColor = .clear
|
||||
titleLabel.textColor = .clear
|
||||
titleLabel.textAlignment = .center
|
||||
return titleLabel
|
||||
}()
|
||||
|
||||
|
||||
/// Badge value
|
||||
open var badgeValue: String? {
|
||||
didSet {
|
||||
if let _ = badgeValue {
|
||||
self.badgeView.badgeValue = badgeValue
|
||||
self.addSubview(badgeView)
|
||||
self.updateLayout()
|
||||
} else {
|
||||
// Remove when nil.
|
||||
self.badgeView.removeFromSuperview()
|
||||
}
|
||||
badgeChanged(animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
open var badgeColor: UIColor? {
|
||||
didSet {
|
||||
if let _ = badgeColor {
|
||||
self.badgeView.badgeColor = badgeColor
|
||||
} else {
|
||||
self.badgeView.badgeColor = ESTabBarItemBadgeView.defaultBadgeColor
|
||||
}
|
||||
}
|
||||
}
|
||||
open var badgeView: ESTabBarItemBadgeView = ESTabBarItemBadgeView() {
|
||||
willSet {
|
||||
if let _ = badgeView.superview {
|
||||
badgeView.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
didSet {
|
||||
if let _ = badgeView.superview {
|
||||
self.updateLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
open var badgeOffset: UIOffset = UIOffset.init(horizontal: 6.0, vertical: -22.0) {
|
||||
didSet {
|
||||
if badgeOffset != oldValue {
|
||||
self.updateLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.isUserInteractionEnabled = false
|
||||
|
||||
addSubview(imageView)
|
||||
addSubview(titleLabel)
|
||||
|
||||
titleLabel.textColor = textColor
|
||||
imageView.tintColor = iconColor
|
||||
backgroundColor = backdropColor
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
open func updateDisplay() {
|
||||
imageView.image = (selected ? (selectedImage ?? image) : image)?.withRenderingMode(renderingMode)
|
||||
imageView.tintColor = selected ? highlightIconColor : iconColor
|
||||
titleLabel.textColor = selected ? highlightTextColor : textColor
|
||||
backgroundColor = selected ? highlightBackdropColor : backdropColor
|
||||
}
|
||||
|
||||
open func updateLayout() {
|
||||
let w = self.bounds.size.width
|
||||
let h = self.bounds.size.height
|
||||
|
||||
imageView.isHidden = (imageView.image == nil)
|
||||
titleLabel.isHidden = (titleLabel.text == nil)
|
||||
|
||||
if self.itemContentMode == .alwaysTemplate {
|
||||
var s: CGFloat = 0.0 // image size
|
||||
var f: CGFloat = 0.0 // font
|
||||
var isLandscape = false
|
||||
if let keyWindow = UIApplication.shared.keyWindow {
|
||||
isLandscape = keyWindow.bounds.width > keyWindow.bounds.height
|
||||
}
|
||||
let isWide = isLandscape || traitCollection.horizontalSizeClass == .regular // is landscape or regular
|
||||
if #available(iOS 11.0, *), isWide {
|
||||
s = UIScreen.main.scale == 3.0 ? 23.0 : 20.0
|
||||
f = UIScreen.main.scale == 3.0 ? 13.0 : 12.0
|
||||
} else {
|
||||
s = 23.0
|
||||
f = 10.0
|
||||
}
|
||||
|
||||
if !imageView.isHidden && !titleLabel.isHidden {
|
||||
titleLabel.font = UIFont.systemFont(ofSize: f)
|
||||
titleLabel.sizeToFit()
|
||||
if #available(iOS 11.0, *), isWide {
|
||||
titleLabel.frame = CGRect.init(x: (w - titleLabel.bounds.size.width) / 2.0 + (UIScreen.main.scale == 3.0 ? 14.25 : 12.25),
|
||||
y: (h - titleLabel.bounds.size.height) / 2.0,
|
||||
width: titleLabel.bounds.size.width,
|
||||
height: titleLabel.bounds.size.height)
|
||||
imageView.frame = CGRect.init(x: titleLabel.frame.origin.x - s - (UIScreen.main.scale == 3.0 ? 6.0 : 5.0),
|
||||
y: (h - s) / 2.0,
|
||||
width: s,
|
||||
height: s)
|
||||
} else {
|
||||
titleLabel.frame = CGRect.init(x: (w - titleLabel.bounds.size.width) / 2.0,
|
||||
y: h - titleLabel.bounds.size.height - 1.0,
|
||||
width: titleLabel.bounds.size.width,
|
||||
height: titleLabel.bounds.size.height)
|
||||
imageView.frame = CGRect.init(x: (w - s) / 2.0,
|
||||
y: (h - s) / 2.0 - 6.0,
|
||||
width: s,
|
||||
height: s)
|
||||
}
|
||||
} else if !imageView.isHidden {
|
||||
imageView.frame = CGRect.init(x: (w - s) / 2.0,
|
||||
y: (h - s) / 2.0,
|
||||
width: s,
|
||||
height: s)
|
||||
} else if !titleLabel.isHidden {
|
||||
titleLabel.font = UIFont.systemFont(ofSize: f)
|
||||
titleLabel.sizeToFit()
|
||||
titleLabel.frame = CGRect.init(x: (w - titleLabel.bounds.size.width) / 2.0,
|
||||
y: (h - titleLabel.bounds.size.height) / 2.0,
|
||||
width: titleLabel.bounds.size.width,
|
||||
height: titleLabel.bounds.size.height)
|
||||
}
|
||||
|
||||
if let _ = badgeView.superview {
|
||||
let size = badgeView.sizeThatFits(self.frame.size)
|
||||
if #available(iOS 11.0, *), isWide {
|
||||
badgeView.frame = CGRect.init(origin: CGPoint.init(x: imageView.frame.midX - 3 + badgeOffset.horizontal, y: imageView.frame.midY + 3 + badgeOffset.vertical), size: size)
|
||||
} else {
|
||||
badgeView.frame = CGRect.init(origin: CGPoint.init(x: w / 2.0 + badgeOffset.horizontal, y: h / 2.0 + badgeOffset.vertical), size: size)
|
||||
}
|
||||
badgeView.setNeedsLayout()
|
||||
}
|
||||
|
||||
} else {
|
||||
if !imageView.isHidden && !titleLabel.isHidden {
|
||||
titleLabel.sizeToFit()
|
||||
imageView.sizeToFit()
|
||||
titleLabel.frame = CGRect.init(x: (w - titleLabel.bounds.size.width) / 2.0,
|
||||
y: h - titleLabel.bounds.size.height - 1.0,
|
||||
width: titleLabel.bounds.size.width,
|
||||
height: titleLabel.bounds.size.height)
|
||||
imageView.frame = CGRect.init(x: (w - imageView.bounds.size.width) / 2.0,
|
||||
y: (h - imageView.bounds.size.height) / 2.0 - 6.0,
|
||||
width: imageView.bounds.size.width,
|
||||
height: imageView.bounds.size.height)
|
||||
} else if !imageView.isHidden {
|
||||
imageView.sizeToFit()
|
||||
imageView.center = CGPoint.init(x: w / 2.0, y: h / 2.0)
|
||||
} else if !titleLabel.isHidden {
|
||||
titleLabel.sizeToFit()
|
||||
titleLabel.center = CGPoint.init(x: w / 2.0, y: h / 2.0)
|
||||
}
|
||||
|
||||
if let _ = badgeView.superview {
|
||||
let size = badgeView.sizeThatFits(self.frame.size)
|
||||
badgeView.frame = CGRect.init(origin: CGPoint.init(x: w / 2.0 + badgeOffset.horizontal, y: h / 2.0 + badgeOffset.vertical), size: size)
|
||||
badgeView.setNeedsLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - INTERNAL METHODS
|
||||
internal final func select(animated: Bool, completion: (() -> ())?) {
|
||||
selected = true
|
||||
if highlightEnabled && highlighted {
|
||||
highlighted = false
|
||||
dehighlightAnimation(animated: animated, completion: { [weak self] in
|
||||
self?.updateDisplay()
|
||||
self?.selectAnimation(animated: animated, completion: completion)
|
||||
})
|
||||
} else {
|
||||
updateDisplay()
|
||||
selectAnimation(animated: animated, completion: completion)
|
||||
}
|
||||
}
|
||||
|
||||
internal final func deselect(animated: Bool, completion: (() -> ())?) {
|
||||
selected = false
|
||||
updateDisplay()
|
||||
self.deselectAnimation(animated: animated, completion: completion)
|
||||
}
|
||||
|
||||
internal final func reselect(animated: Bool, completion: (() -> ())?) {
|
||||
if selected == false {
|
||||
select(animated: animated, completion: completion)
|
||||
} else {
|
||||
if highlightEnabled && highlighted {
|
||||
highlighted = false
|
||||
dehighlightAnimation(animated: animated, completion: { [weak self] in
|
||||
self?.reselectAnimation(animated: animated, completion: completion)
|
||||
})
|
||||
} else {
|
||||
reselectAnimation(animated: animated, completion: completion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal final func highlight(animated: Bool, completion: (() -> ())?) {
|
||||
if !highlightEnabled {
|
||||
return
|
||||
}
|
||||
if highlighted == true {
|
||||
return
|
||||
}
|
||||
highlighted = true
|
||||
self.highlightAnimation(animated: animated, completion: completion)
|
||||
}
|
||||
|
||||
internal final func dehighlight(animated: Bool, completion: (() -> ())?) {
|
||||
if !highlightEnabled {
|
||||
return
|
||||
}
|
||||
if !highlighted {
|
||||
return
|
||||
}
|
||||
highlighted = false
|
||||
self.dehighlightAnimation(animated: animated, completion: completion)
|
||||
}
|
||||
|
||||
internal func badgeChanged(animated: Bool, completion: (() -> ())?) {
|
||||
self.badgeChangedAnimation(animated: animated, completion: completion)
|
||||
}
|
||||
|
||||
// MARK: - ANIMATION METHODS
|
||||
open func selectAnimation(animated: Bool, completion: (() -> ())?) {
|
||||
completion?()
|
||||
}
|
||||
|
||||
open func deselectAnimation(animated: Bool, completion: (() -> ())?) {
|
||||
completion?()
|
||||
}
|
||||
|
||||
open func reselectAnimation(animated: Bool, completion: (() -> ())?) {
|
||||
completion?()
|
||||
}
|
||||
|
||||
open func highlightAnimation(animated: Bool, completion: (() -> ())?) {
|
||||
completion?()
|
||||
}
|
||||
|
||||
open func dehighlightAnimation(animated: Bool, completion: (() -> ())?) {
|
||||
completion?()
|
||||
}
|
||||
|
||||
open func badgeChangedAnimation(animated: Bool, completion: (() -> ())?) {
|
||||
completion?()
|
||||
}
|
||||
|
||||
}
|
||||
71
Pods/ESTabBarController-swift/Sources/ESTabBarItemMoreContentView.swift
generated
Normal file
71
Pods/ESTabBarController-swift/Sources/ESTabBarItemMoreContentView.swift
generated
Normal file
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// ESTabBarItemMoreContentView.swift
|
||||
//
|
||||
// Created by Vincent Li on 2017/2/8.
|
||||
// Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
open class ESTabBarItemMoreContentView: ESTabBarItemContentView {
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.title = NSLocalizedString("More_TabBarItem", bundle: Bundle(for:ESTabBarController.self), comment: "")
|
||||
self.image = systemMore(highlighted: false)
|
||||
self.selectedImage = systemMore(highlighted: true)
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func systemMore(highlighted isHighlighted: Bool) -> UIImage? {
|
||||
let image = UIImage.init()
|
||||
let circleDiameter = isHighlighted ? 5.0 : 4.0
|
||||
let scale = UIScreen.main.scale
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(CGSize.init(width: 32, height: 32), false, scale)
|
||||
|
||||
if let context = UIGraphicsGetCurrentContext() {
|
||||
context.setLineWidth(1.0)
|
||||
for index in 0...2 {
|
||||
let tmpRect = CGRect.init(x: 5.0 + 9.0 * Double(index), y: 14.0, width: circleDiameter, height: circleDiameter)
|
||||
context.addEllipse(in: tmpRect)
|
||||
image.draw(in: tmpRect)
|
||||
}
|
||||
|
||||
if isHighlighted {
|
||||
context.setFillColor(UIColor.blue.cgColor)
|
||||
context.fillPath()
|
||||
} else {
|
||||
context.strokePath()
|
||||
}
|
||||
|
||||
let newImage = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
return newImage
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
3
Pods/ESTabBarController-swift/Sources/en.lproj/Localizable.strings
generated
Normal file
3
Pods/ESTabBarController-swift/Sources/en.lproj/Localizable.strings
generated
Normal file
@@ -0,0 +1,3 @@
|
||||
"TabBarItem_AccessibilityLabel"="%1$@ - tab - %2$i of %3$i";
|
||||
"TabBarItem_Selected_AccessibilityLabel"="Selected - %1$@ - tab - %2$i of %3$i";
|
||||
"More_TabBarItem"="More";
|
||||
Reference in New Issue
Block a user