diff --git a/Example/ViewController.swift b/Example/ViewController.swift index dfada2f..13bb78f 100644 --- a/Example/ViewController.swift +++ b/Example/ViewController.swift @@ -70,6 +70,10 @@ final class ViewController: SwipeMenuViewController { override func swipeMenuView(_ swipeMenuView: SwipeMenuView, titleForPageAt index: Int) -> String { return children[index].title ?? "" } + + override func swipeMenuView(_ swipeMenuView: SwipeMenuView, hasNotificationPageAt index: Int) -> Bool { + return index % 2 == 1 ? true : false + } override func swipeMenuView(_ swipeMenuView: SwipeMenuView, viewControllerForPageAt index: Int) -> UIViewController { let vc = children[index] diff --git a/Sources/Classes/SwipeMenuView.swift b/Sources/Classes/SwipeMenuView.swift index bfa4b19..cd178ca 100644 --- a/Sources/Classes/SwipeMenuView.swift +++ b/Sources/Classes/SwipeMenuView.swift @@ -35,6 +35,9 @@ public struct SwipeMenuViewOptions { /// ItemView selected textColor. Defaults to `.black`. public var selectedTextColor: UIColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0) + + /// ItemView notification badge color. Defaults to `.red`. + public var notificationBadgeColor: UIColor = UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0) } public struct AdditionView { @@ -178,6 +181,9 @@ public protocol SwipeMenuViewDataSource: class { /// Return strings to be displayed at the tab in `SwipeMenuView`. func swipeMenuView(_ swipeMenuView: SwipeMenuView, titleForPageAt index: Int) -> String + + /// Returns whether or not the tab in `SwipeMenuView` has notifications. + func swipeMenuView(_ swipeMenuView: SwipeMenuView, hasNotificationPageAt index: Int) -> Bool /// Return a ViewController to be displayed at the page in `SwipeMenuView`. func swipeMenuView(_ swipeMenuView: SwipeMenuView, viewControllerForPageAt index: Int) -> UIViewController @@ -399,6 +405,10 @@ extension SwipeMenuView: TabViewDelegate, TabViewDataSource { public func tabView(_ tabView: TabView, titleForItemAt index: Int) -> String? { return dataSource?.swipeMenuView(self, titleForPageAt: index) } + + public func tabView(_ tabView: TabView, hasNotificationForItemAt index: Int) -> Bool? { + return dataSource?.swipeMenuView(self, hasNotificationPageAt: index) + } } // MARK: - UIScrollViewDelegate diff --git a/Sources/Classes/SwipeMenuViewController.swift b/Sources/Classes/SwipeMenuViewController.swift index da6a3fc..9a17b64 100644 --- a/Sources/Classes/SwipeMenuViewController.swift +++ b/Sources/Classes/SwipeMenuViewController.swift @@ -1,7 +1,7 @@ import UIKit open class SwipeMenuViewController: UIViewController, SwipeMenuViewDelegate, SwipeMenuViewDataSource { - + open var swipeMenuView: SwipeMenuView! open override func viewDidLoad() { @@ -61,6 +61,10 @@ open class SwipeMenuViewController: UIViewController, SwipeMenuViewDelegate, Swi open func swipeMenuView(_ swipeMenuView: SwipeMenuView, titleForPageAt index: Int) -> String { return children[index].title ?? "" } + + open func swipeMenuView(_ swipeMenuView: SwipeMenuView, hasNotificationPageAt index: Int) -> Bool { + return false + } open func swipeMenuView(_ swipeMenuView: SwipeMenuView, viewControllerForPageAt index: Int) -> UIViewController { let vc = children[index] diff --git a/Sources/Classes/TabItemView.swift b/Sources/Classes/TabItemView.swift index 4b7d1ff..0d850f8 100644 --- a/Sources/Classes/TabItemView.swift +++ b/Sources/Classes/TabItemView.swift @@ -3,9 +3,12 @@ import UIKit final class TabItemView: UIView { private(set) var titleLabel: UILabel = UILabel() + private var notificationBadgeView: UIView = UIView() + let notificationBadgeViewSize: CGSize = CGSize(width: 6, height: 6) public var textColor: UIColor = UIColor(red: 140/255, green: 140/255, blue: 140/255, alpha: 1.0) public var selectedTextColor: UIColor = .white + public var notificationBadgeColor: UIColor = .red public var isSelected: Bool = false { didSet { @@ -16,11 +19,27 @@ final class TabItemView: UIView { } } } + public var notificationBadgeViewFrame: CGRect = .zero { + didSet { + notificationBadgeView.frame = notificationBadgeViewFrame + } + } + public var hasNotification: Bool = false { + didSet { + if hasNotification { + notificationBadgeView.backgroundColor = notificationBadgeColor + notificationBadgeView.isHidden = false + } else { + notificationBadgeView.isHidden = true + } + } + } public override init(frame: CGRect) { super.init(frame: frame) setupLabel() + setupNotificationBadgeView() } required public init?(coder aDecoder: NSCoder) { @@ -40,9 +59,17 @@ final class TabItemView: UIView { addSubview(titleLabel) layoutLabel() } - + + private func setupNotificationBadgeView() { + notificationBadgeView = UIView() + notificationBadgeView.isHidden = true + notificationBadgeView.layer.cornerRadius = notificationBadgeViewSize.height / 2 + notificationBadgeView.clipsToBounds = true + addSubview(notificationBadgeView) + } + private func layoutLabel() { - + titleLabel.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ titleLabel.topAnchor.constraint(equalTo: self.topAnchor), diff --git a/Sources/Classes/TabView.swift b/Sources/Classes/TabView.swift index 8b20a6e..c74537a 100644 --- a/Sources/Classes/TabView.swift +++ b/Sources/Classes/TabView.swift @@ -26,6 +26,9 @@ public protocol TabViewDataSource: class { /// Return strings to be displayed at the tab in `TabView`. func tabView(_ tabView: TabView, titleForItemAt index: Int) -> String? + + /// Returns whether or not the tab in `TabView` has notifications. + func tabView(_ tabView: TabView, hasNotificationForItemAt index: Int) -> Bool? } open class TabView: UIScrollView { @@ -220,6 +223,10 @@ open class TabView: UIScrollView { tabItemView.textColor = options.itemView.textColor tabItemView.selectedTextColor = options.itemView.selectedTextColor } + if let hasNotification = dataSource.tabView(self, hasNotificationForItemAt: index) { + tabItemView.notificationBadgeColor = options.itemView.notificationBadgeColor + tabItemView.hasNotification = hasNotification + } tabItemView.isSelected = index == currentIndex @@ -250,6 +257,17 @@ open class TabView: UIScrollView { adjustCellSize = CGSize(width: (frame.width - options.margin * 2) / CGFloat(itemCount), height: tabItemView.frame.size.height) } tabItemView.frame.size = adjustCellSize + + if let title = dataSource.tabView(self, titleForItemAt: index) { + let textFrame = (title as NSString).boundingRect(with: tabItemView.titleLabel.frame.size, + options: .usesLineFragmentOrigin, + attributes: [NSAttributedString.Key.font: options.itemView.font], + context: nil) + tabItemView.notificationBadgeViewFrame = .init(x: textFrame.width + (adjustCellSize.width - textFrame.width) / 2 + 6, + y: adjustCellSize.height / 2 - tabItemView.notificationBadgeViewSize.height, + width: tabItemView.notificationBadgeViewSize.width, + height: tabItemView.notificationBadgeViewSize.height) + } containerView.addArrangedSubview(tabItemView) }