diff --git a/Example/Segmentio/ViewControllers/ExampleViewController.swift b/Example/Segmentio/ViewControllers/ExampleViewController.swift index 44b4090..999b897 100644 --- a/Example/Segmentio/ViewControllers/ExampleViewController.swift +++ b/Example/Segmentio/ViewControllers/ExampleViewController.swift @@ -48,6 +48,7 @@ class ExampleViewController: UIViewController { super.viewDidAppear(animated) setupSegmentioView() setupScrollView() + setupBadgeCountForIndex() } private func setupSegmentioView() { @@ -70,6 +71,10 @@ class ExampleViewController: UIViewController { } } + private func setupBadgeCountForIndex() { + segmentioView.setupBadgeAtIndex(1, count: 3, color: ColorPalette.WhiteSmokeColor) + } + private func segmentioContent() -> [SegmentioItem] { return [ SegmentioItem(title: "Tornado", image: UIImage(named: "tornado")), diff --git a/Segmentio.podspec b/Segmentio.podspec index f7d29b3..cedb202 100644 --- a/Segmentio.podspec +++ b/Segmentio.podspec @@ -16,6 +16,9 @@ Pod::Spec.new do |spec| spec.source = { :git => "https://github.com/Yalantis/Segmentio.git", :tag => spec.version } spec.source_files = 'Segmentio/Source/**/*.swift' + spec.source_files.resource_bundles = { + 'Segmentio' => ['Pod/**/*.{storyboard,xib,xcassets,json,imageset,png}'] + } spec.module_name = 'Segmentio' spec.requires_arc = true end diff --git a/Segmentio/Source/Badge/BadgeViewPresenter.swift b/Segmentio/Source/Badge/BadgeViewPresenter.swift new file mode 100644 index 0000000..bff151f --- /dev/null +++ b/Segmentio/Source/Badge/BadgeViewPresenter.swift @@ -0,0 +1,88 @@ +// +// BadgeViewPresenter.swift +// Pods +// +// Created by Eugene on 22.09.16. +// +// + +import UIKit + +class BadgeViewPresenter { + + func addBadgeForContainerView( + containerView: UIView, + counterValue: Int, + backgroundColor: UIColor = .redColor(), + badgeSize: CounterBadgeSize = .Standard + ) { + var badgeView: BadgeWithCounterView? + for view in containerView.subviews { + if view is BadgeWithCounterView { + badgeView = view as! BadgeWithCounterView + badgeView?.setBadgeBackgroundColor(backgroundColor) + badgeView?.setBadgeCounterValue(counterValue) + } + } + if badgeView == nil { + badgeView = badgeViewForCounterValue( + counterValue, + backgroundColor: backgroundColor, + size: badgeSize + ) + containerView.addSubview(badgeView!) + setupBadgeConstraints(containerView, badgeView: badgeView!) + } + + } + + func removeBadgeFromContainerView(containerView: UIView) { + for view in containerView.subviews { + if view is BadgeWithCounterView { + view.removeFromSuperview() + } + } + } + + + private func setupBadgeConstraints(containerView: UIView, badgeView: BadgeWithCounterView) { + + let segmentTitleLabelHorizontalCenterConstraint = + NSLayoutConstraint( + item: badgeView, + attribute: .Top, + relatedBy: .Equal, + toItem: containerView, + attribute: .Top, + multiplier: 1, + constant: 1.0 + ) + + let segmentTitleLabelVerticalCenterConstraint = + NSLayoutConstraint( + item: badgeView, + attribute: .Trailing, + relatedBy: .Equal, + toItem: containerView, + attribute: .Trailing, + multiplier: 1, + constant: 1.0 + ) + containerView.addConstraints([segmentTitleLabelHorizontalCenterConstraint, segmentTitleLabelVerticalCenterConstraint]) + + } + +} + +// MARK: Badges views creation + +extension BadgeViewPresenter { + + private func badgeViewForCounterValue(counter: Int, backgroundColor: UIColor, size: CounterBadgeSize) -> BadgeWithCounterView { + let view = BadgeWithCounterView.instanceFromNib(size: size) + view.setBadgeBackgroundColor(backgroundColor) + view.setBadgeCounterValue(counter) + return view + } + +} \ No newline at end of file diff --git a/Segmentio/Source/Badge/Views/BadgeWithCounterView.swift b/Segmentio/Source/Badge/Views/BadgeWithCounterView.swift new file mode 100644 index 0000000..1bf4bfa --- /dev/null +++ b/Segmentio/Source/Badge/Views/BadgeWithCounterView.swift @@ -0,0 +1,41 @@ +import Foundation + +private let BadgeCounterMaxValue = 99 +private let BadgeCounterOverMaxValueText = "99+" +private let standardSizedNibName = "BadgeWithCounterViewStandardSized" +private let bigSizedNibName = "BadgeWithCounterViewBigSized" + +enum CounterBadgeSize { + case Standard + case Big +} + +class BadgeWithCounterView: UIView { + + @IBOutlet private weak var counterValueLabel: UILabel! + @IBOutlet private weak var backgroundImageView: UIImageView! + + class func instanceFromNib(size size: CounterBadgeSize) -> BadgeWithCounterView { + let nibName = nibNameForSize(size) + return UINib(nibName: nibName, bundle: nil).instantiateWithOwner(nil, options: nil)[0] as! BadgeWithCounterView + } + + func setBadgeCounterValue(counterValue: Int) { + var counterText: String! + if counterValue > BadgeCounterMaxValue { + counterText = BadgeCounterOverMaxValueText + } else { + counterText = String(counterValue) + } + counterValueLabel.text = counterText + } + + func setBadgeBackgroundColor(color: UIColor) { + backgroundImageView.backgroundColor = color + } + + private class func nibNameForSize(size: CounterBadgeSize) -> String { + return (size == .Standard) ? standardSizedNibName : bigSizedNibName + } + +} \ No newline at end of file diff --git a/Segmentio/Source/Badge/Views/BadgeWithCounterViewBigSized.xib b/Segmentio/Source/Badge/Views/BadgeWithCounterViewBigSized.xib new file mode 100644 index 0000000..e6acd46 --- /dev/null +++ b/Segmentio/Source/Badge/Views/BadgeWithCounterViewBigSized.xib @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Segmentio/Source/Badge/Views/BadgeWithCounterViewStandardSized.xib b/Segmentio/Source/Badge/Views/BadgeWithCounterViewStandardSized.xib new file mode 100644 index 0000000..83de5af --- /dev/null +++ b/Segmentio/Source/Badge/Views/BadgeWithCounterViewStandardSized.xib @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Segmentio/Source/BadgeWithCounterView.swift b/Segmentio/Source/BadgeWithCounterView.swift new file mode 100644 index 0000000..1bf4bfa --- /dev/null +++ b/Segmentio/Source/BadgeWithCounterView.swift @@ -0,0 +1,41 @@ +import Foundation + +private let BadgeCounterMaxValue = 99 +private let BadgeCounterOverMaxValueText = "99+" +private let standardSizedNibName = "BadgeWithCounterViewStandardSized" +private let bigSizedNibName = "BadgeWithCounterViewBigSized" + +enum CounterBadgeSize { + case Standard + case Big +} + +class BadgeWithCounterView: UIView { + + @IBOutlet private weak var counterValueLabel: UILabel! + @IBOutlet private weak var backgroundImageView: UIImageView! + + class func instanceFromNib(size size: CounterBadgeSize) -> BadgeWithCounterView { + let nibName = nibNameForSize(size) + return UINib(nibName: nibName, bundle: nil).instantiateWithOwner(nil, options: nil)[0] as! BadgeWithCounterView + } + + func setBadgeCounterValue(counterValue: Int) { + var counterText: String! + if counterValue > BadgeCounterMaxValue { + counterText = BadgeCounterOverMaxValueText + } else { + counterText = String(counterValue) + } + counterValueLabel.text = counterText + } + + func setBadgeBackgroundColor(color: UIColor) { + backgroundImageView.backgroundColor = color + } + + private class func nibNameForSize(size: CounterBadgeSize) -> String { + return (size == .Standard) ? standardSizedNibName : bigSizedNibName + } + +} \ No newline at end of file diff --git a/Segmentio/Source/BadgeWithCounterViewBigSized.xib b/Segmentio/Source/BadgeWithCounterViewBigSized.xib new file mode 100644 index 0000000..14d506b --- /dev/null +++ b/Segmentio/Source/BadgeWithCounterViewBigSized.xib @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Segmentio/Source/BadgeWithCounterViewStandardSized.xib b/Segmentio/Source/BadgeWithCounterViewStandardSized.xib new file mode 100644 index 0000000..698642b --- /dev/null +++ b/Segmentio/Source/BadgeWithCounterViewStandardSized.xib @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Segmentio/Source/Cells/SegmentioCell.swift b/Segmentio/Source/Cells/SegmentioCell.swift index bbf31cd..8379860 100644 --- a/Segmentio/Source/Cells/SegmentioCell.swift +++ b/Segmentio/Source/Cells/SegmentioCell.swift @@ -25,6 +25,7 @@ class SegmentioCell: UICollectionViewCell { private var options = SegmentioOptions() private var style = SegmentioStyle.ImageOverLabel private let verticalSeparatorLayer = CAShapeLayer() + private let badgePresenter = BadgeViewPresenter() override var highlighted: Bool { get { @@ -71,7 +72,7 @@ class SegmentioCell: UICollectionViewCell { if let segmentTitleLabel = segmentTitleLabel, containerView = containerView { containerView.addSubview(segmentTitleLabel) } - + segmentImageView?.translatesAutoresizingMaskIntoConstraints = false segmentTitleLabel?.translatesAutoresizingMaskIntoConstraints = false containerView?.translatesAutoresizingMaskIntoConstraints = false @@ -80,7 +81,6 @@ class SegmentioCell: UICollectionViewCell { segmentTitleLabel?.font = UIFont.systemFontOfSize(UIFont.smallSystemFontSize()) setupConstraintsForSubviews() - setupContainerConstraints() addVerticalSeparator() } @@ -109,7 +109,6 @@ class SegmentioCell: UICollectionViewCell { self.options = options self.style = style setupContent(content: content) - if let indicatorOptions = self.options.indicatorOptions { setupConstraint(indicatorOptions: indicatorOptions) } @@ -133,13 +132,36 @@ class SegmentioCell: UICollectionViewCell { } } - func setupConstraintsForSubviews() { - return // implement in subclasses + func configurateBadgeWithCount(badgeCount: Int?, color: UIColor?) { + guard let badgeCount = badgeCount, color = color else { + return + } + + if style == .OnlyImage { + badgePresenter.addBadgeForContainerView( + segmentImageView!, + counterValue: badgeCount, + backgroundColor: color, + badgeSize: .Standard + ) + } else { + badgePresenter.addBadgeForContainerView( + containerView!, + counterValue: badgeCount, + backgroundColor: color, + badgeSize: .Standard + ) + } } + func setupConstraintsForSubviews() { + setupContainerConstraints() + return // implement in subclasses + } + // MARK: - Private functions - func setupContainerConstraints() { + private func setupContainerConstraints() { guard let segmentTitleLabel = segmentTitleLabel else { return } @@ -168,7 +190,6 @@ class SegmentioCell: UICollectionViewCell { multiplier: 1, constant: 0.0 ) - addConstraints([segmentTitleLabelHorizontalCenterConstraint, segmentTitleLabelVerticalCenterConstraint]) } @@ -185,7 +206,7 @@ class SegmentioCell: UICollectionViewCell { segmentTitleLabel?.font = defaultState.titleFont segmentTitleLabel?.text = content.title } - configurateBadgeWithCount(content.badgeCount) + configurateBadgeWithCount(content.badgeCount, color: content.badgeColor) } private func setupConstraint(indicatorOptions indicatorOptions: SegmentioIndicatorOptions) { @@ -196,13 +217,7 @@ class SegmentioCell: UICollectionViewCell { bottomConstraint?.constant = padding + indicatorOptions.height } } - - private func configurateBadgeWithCount(count: Int?) { - if let count = count { - - } - } - + // MARK: - Vertical separator private func addVerticalSeparator() { @@ -253,8 +268,10 @@ class SegmentioCell: UICollectionViewCell { let topConstraint = NSLayoutConstraint( item: verticalSeparatorView, - attribute: .Top, relatedBy: .Equal, - toItem: contentView, attribute: .Top, + attribute: .Top, + relatedBy: .Equal, + toItem: contentView, + attribute: .Top, multiplier: 1, constant: 0 ) diff --git a/Segmentio/Source/Cells/SegmentioCellWithImageAfterLabel.swift b/Segmentio/Source/Cells/SegmentioCellWithImageAfterLabel.swift index 6900761..26f7139 100644 --- a/Segmentio/Source/Cells/SegmentioCellWithImageAfterLabel.swift +++ b/Segmentio/Source/Cells/SegmentioCellWithImageAfterLabel.swift @@ -11,6 +11,7 @@ import UIKit final class SegmentioCellWithImageAfterLabel: SegmentioCell { override func setupConstraintsForSubviews() { + super.setupConstraintsForSubviews() guard let segmentImageView = segmentImageView else { return } diff --git a/Segmentio/Source/Cells/SegmentioCellWithImageBeforeLabel.swift b/Segmentio/Source/Cells/SegmentioCellWithImageBeforeLabel.swift index c09dd2f..0b75e2f 100644 --- a/Segmentio/Source/Cells/SegmentioCellWithImageBeforeLabel.swift +++ b/Segmentio/Source/Cells/SegmentioCellWithImageBeforeLabel.swift @@ -11,6 +11,7 @@ import UIKit class SegmentioCellWithImageBeforeLabel: SegmentioCell { override func setupConstraintsForSubviews() { + super.setupConstraintsForSubviews() guard let segmentImageView = segmentImageView else { return } diff --git a/Segmentio/Source/Cells/SegmentioCellWithImageOverLabel.swift b/Segmentio/Source/Cells/SegmentioCellWithImageOverLabel.swift index 43b85bd..9591184 100644 --- a/Segmentio/Source/Cells/SegmentioCellWithImageOverLabel.swift +++ b/Segmentio/Source/Cells/SegmentioCellWithImageOverLabel.swift @@ -11,6 +11,7 @@ import UIKit class SegmentioCellWithImageOverLabel: SegmentioCell { override func setupConstraintsForSubviews() { + super.setupConstraintsForSubviews() guard let segmentImageView = segmentImageView else { return } diff --git a/Segmentio/Source/Cells/SegmentioCellWithImageUnderLabel.swift b/Segmentio/Source/Cells/SegmentioCellWithImageUnderLabel.swift index 9f08481..2620a40 100644 --- a/Segmentio/Source/Cells/SegmentioCellWithImageUnderLabel.swift +++ b/Segmentio/Source/Cells/SegmentioCellWithImageUnderLabel.swift @@ -11,6 +11,7 @@ import UIKit class SegmentioCellWithImageUnderLabel: SegmentioCell { override func setupConstraintsForSubviews() { + super.setupConstraintsForSubviews() guard let segmentImageView = segmentImageView else { return } diff --git a/Segmentio/Source/Cells/SegmentioCellWithLabel.swift b/Segmentio/Source/Cells/SegmentioCellWithLabel.swift index 6ccda80..df2b2fa 100644 --- a/Segmentio/Source/Cells/SegmentioCellWithLabel.swift +++ b/Segmentio/Source/Cells/SegmentioCellWithLabel.swift @@ -11,10 +11,11 @@ import UIKit final class SegmentioCellWithLabel: SegmentioCell { override func setupConstraintsForSubviews() { + super.setupConstraintsForSubviews() + guard let segmentTitleLabel = segmentTitleLabel else { return } - guard let containerView = containerView else { return } diff --git a/Segmentio/Source/Extensions/RoundImageView.swift b/Segmentio/Source/Extensions/RoundImageView.swift new file mode 100644 index 0000000..bcee89f --- /dev/null +++ b/Segmentio/Source/Extensions/RoundImageView.swift @@ -0,0 +1,23 @@ +import Foundation + +@IBDesignable +class RoundImageView: UIImageView { + + override var bounds: CGRect { + didSet { + updateCornerRadiusValue() + } + } + + override func awakeFromNib() { + super.awakeFromNib() + + updateCornerRadiusValue() + } + + private func updateCornerRadiusValue() { + let cornerRadius = min(bounds.size.height, bounds.size.width) / 2 + layer.cornerRadius = cornerRadius + } + +} \ No newline at end of file diff --git a/Segmentio/Source/Segmentio.swift b/Segmentio/Source/Segmentio.swift index dbee146..0875fa9 100644 --- a/Segmentio/Source/Segmentio.swift +++ b/Segmentio/Source/Segmentio.swift @@ -203,7 +203,7 @@ public class Segmentio: UIView { setupHorizontalSeparatorIfPossible() } - public func setupBadgeAtIndex(index: Int, count: Int, image: UIImage) { + public func setupBadgeAtIndex(index: Int, count: Int, color: UIColor) { segmentioItems[index].setupBadgeWithCount(count) segmentioCollectionView?.reloadData() } diff --git a/Segmentio/Source/SegmentioOptions.swift b/Segmentio/Source/SegmentioOptions.swift index ccb48e5..f7c3a2d 100644 --- a/Segmentio/Source/SegmentioOptions.swift +++ b/Segmentio/Source/SegmentioOptions.swift @@ -14,14 +14,16 @@ public struct SegmentioItem { var title: String? var image: UIImage? var badgeCount: Int? + var badgeColor: UIColor? public init(title: String?, image: UIImage?) { self.title = title self.image = image } - public mutating func setupBadgeWithCount(count: Int) { + public mutating func setupBadgeWithCount(count: Int, color: UIColor = .redColor()) { self.badgeCount = count + self.badgeColor = color } }