From 07f7d884fc1a9b00e1de3ea510613bee00c4b3e6 Mon Sep 17 00:00:00 2001 From: Dmitriy Demchenko Date: Mon, 14 Nov 2016 13:07:54 +0200 Subject: [PATCH] [Add] SegmentioBuilder [Update] ExampleViewController: moved setup segmentioView logic to SegmentioBuilder [Fix] Autolayout issue using Segmentio programtically [Update] SegmentioItem, SegmentioCell: minor updates --- Example/Segmentio.xcodeproj/project.pbxproj | 12 ++ .../Segmentio/Builders/SegmentioBuilder.swift | 118 ++++++++++++++++ Example/Segmentio/Info.plist | 2 - .../ExampleViewController.swift | 131 +++++------------- Segmentio/Source/Cells/SegmentioCell.swift | 24 ++-- Segmentio/Source/Segmentio.swift | 15 +- Segmentio/Source/SegmentioOptions.swift | 4 +- 7 files changed, 187 insertions(+), 119 deletions(-) create mode 100644 Example/Segmentio/Builders/SegmentioBuilder.swift diff --git a/Example/Segmentio.xcodeproj/project.pbxproj b/Example/Segmentio.xcodeproj/project.pbxproj index d0948dd..c2c494b 100644 --- a/Example/Segmentio.xcodeproj/project.pbxproj +++ b/Example/Segmentio.xcodeproj/project.pbxproj @@ -24,6 +24,7 @@ 327AF5EA1D1ABEC100534355 /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 327AF5CB1D1ABEC100534355 /* HomeViewController.swift */; }; 327AF5EB1D1ABEC100534355 /* SideMenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 327AF5CC1D1ABEC100534355 /* SideMenuViewController.swift */; }; 327AF6041D1AC0FE00534355 /* ColorPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = 327AF6031D1AC0FE00534355 /* ColorPalette.swift */; }; + 32C3706C1DD9C4FA001A39CB /* SegmentioBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C3706B1DD9C4FA001A39CB /* SegmentioBuilder.swift */; }; 5B9491B14F42A77448746E9B /* Pods_Segmentio_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 74E8553D39ECFE4883F1D2CA /* Pods_Segmentio_Example.framework */; }; /* End PBXBuildFile section */ @@ -49,6 +50,7 @@ 327AF5CB1D1ABEC100534355 /* HomeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = ""; }; 327AF5CC1D1ABEC100534355 /* SideMenuViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SideMenuViewController.swift; sourceTree = ""; }; 327AF6031D1AC0FE00534355 /* ColorPalette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorPalette.swift; sourceTree = ""; }; + 32C3706B1DD9C4FA001A39CB /* SegmentioBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegmentioBuilder.swift; sourceTree = ""; }; 32C3A9241D2BB3B5004C0FC9 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 607FACD01AFB9204008FA782 /* Segmentio_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Segmentio_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -136,6 +138,14 @@ path = ViewControllers; sourceTree = ""; }; + 32C3706A1DD9C4EC001A39CB /* Builders */ = { + isa = PBXGroup; + children = ( + 32C3706B1DD9C4FA001A39CB /* SegmentioBuilder.swift */, + ); + path = Builders; + sourceTree = ""; + }; 45CA913E13914443DB2552B6 /* Pods */ = { isa = PBXGroup; children = ( @@ -169,6 +179,7 @@ 607FACD21AFB9204008FA782 /* Example for Segmentio */ = { isa = PBXGroup; children = ( + 32C3706A1DD9C4EC001A39CB /* Builders */, 327AF5A71D1ABEC100534355 /* Application */, 327AF5A91D1ABEC100534355 /* Extensions */, 327AF5AD1D1ABEC100534355 /* Helpers */, @@ -337,6 +348,7 @@ 327AF5CF1D1ABEC100534355 /* AppDelegate.swift in Sources */, 327AF5EB1D1ABEC100534355 /* SideMenuViewController.swift in Sources */, 327AF5E81D1ABEC100534355 /* EmbedContainerViewController.swift in Sources */, + 32C3706C1DD9C4FA001A39CB /* SegmentioBuilder.swift in Sources */, 327AF5D41D1ABEC100534355 /* Disaster.swift in Sources */, 327AF5D31D1ABEC100534355 /* AppearanceConfigurator.swift in Sources */, 327AF5EA1D1ABEC100534355 /* HomeViewController.swift in Sources */, diff --git a/Example/Segmentio/Builders/SegmentioBuilder.swift b/Example/Segmentio/Builders/SegmentioBuilder.swift new file mode 100644 index 0000000..4e4231e --- /dev/null +++ b/Example/Segmentio/Builders/SegmentioBuilder.swift @@ -0,0 +1,118 @@ +// +// SegmentioBuilder.swift +// Segmentio +// +// Created by Dmitriy Demchenko on 11/14/16. +// Copyright © 2016 CocoaPods. All rights reserved. +// + +import Segmentio +import UIKit + +struct SegmentioBuilder { + + static func setupBadgeCountForIndex(_ segmentioView: Segmentio, index: Int) { + segmentioView.addBadge( + at: index, + count: 10, + color: ColorPalette.coral + ) + } + + static func buildSegmentioView(segmentioView: Segmentio, segmentioStyle: SegmentioStyle) { + segmentioView.setup( + content: segmentioContent(), + style: segmentioStyle, + options: segmentioOptions(segmentioStyle: segmentioStyle) + ) + } + + private static func segmentioContent() -> [SegmentioItem] { + return [ + SegmentioItem(title: "Tornado", image: UIImage(named: "tornado")), + SegmentioItem(title: "Earthquakes", image: UIImage(named: "earthquakes")), + SegmentioItem(title: "Extreme heat", image: UIImage(named: "heat")), + SegmentioItem(title: "Eruption", image: UIImage(named: "eruption")), + SegmentioItem(title: "Floods", image: UIImage(named: "floods")), + SegmentioItem(title: "Wildfires", image: UIImage(named: "wildfires")) + ] + } + + private static func segmentioOptions(segmentioStyle: SegmentioStyle) -> SegmentioOptions { + var imageContentMode = UIViewContentMode.center + switch segmentioStyle { + case .imageBeforeLabel, .imageAfterLabel: + imageContentMode = .scaleAspectFit + default: + break + } + + return SegmentioOptions( + backgroundColor: ColorPalette.white, + maxVisibleItems: 3, + scrollEnabled: true, + indicatorOptions: segmentioIndicatorOptions(), + horizontalSeparatorOptions: segmentioHorizontalSeparatorOptions(), + verticalSeparatorOptions: segmentioVerticalSeparatorOptions(), + imageContentMode: imageContentMode, + labelTextAlignment: .center, + labelTextNumberOfLines: 1, + segmentStates: segmentioStates(), + animationDuration: 0.3 + ) + } + + private static func segmentioStates() -> SegmentioStates { + let font = UIFont.exampleAvenirMedium(ofSize: 13) + return SegmentioStates( + defaultState: segmentioState( + backgroundColor: .clear, + titleFont: font, + titleTextColor: ColorPalette.grayChateau + ), + selectedState: segmentioState( + backgroundColor: .cyan, + titleFont: font, + titleTextColor: ColorPalette.black + ), + highlightedState: segmentioState( + backgroundColor: ColorPalette.whiteSmoke, + titleFont: font, + titleTextColor: ColorPalette.grayChateau + ) + ) + } + + private static func segmentioState(backgroundColor: UIColor, titleFont: UIFont, titleTextColor: UIColor) -> SegmentioState { + return SegmentioState( + backgroundColor: backgroundColor, + titleFont: titleFont, + titleTextColor: titleTextColor + ) + } + + private static func segmentioIndicatorOptions() -> SegmentioIndicatorOptions { + return SegmentioIndicatorOptions( + type: .bottom, + ratio: 1, + height: 5, + color: ColorPalette.coral + ) + } + + private static func segmentioHorizontalSeparatorOptions() -> SegmentioHorizontalSeparatorOptions { + return SegmentioHorizontalSeparatorOptions( + type: .topAndBottom, + height: 1, + color: ColorPalette.whiteSmoke + ) + } + + private static func segmentioVerticalSeparatorOptions() -> SegmentioVerticalSeparatorOptions { + return SegmentioVerticalSeparatorOptions( + ratio: 1, + color: ColorPalette.whiteSmoke + ) + } + +} diff --git a/Example/Segmentio/Info.plist b/Example/Segmentio/Info.plist index 7e86183..737fc80 100644 --- a/Example/Segmentio/Info.plist +++ b/Example/Segmentio/Info.plist @@ -33,8 +33,6 @@ UISupportedInterfaceOrientations UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight diff --git a/Example/Segmentio/ViewControllers/ExampleViewController.swift b/Example/Segmentio/ViewControllers/ExampleViewController.swift index 927c15c..56d7114 100644 --- a/Example/Segmentio/ViewControllers/ExampleViewController.swift +++ b/Example/Segmentio/ViewControllers/ExampleViewController.swift @@ -46,132 +46,65 @@ class ExampleViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - setupSegmentioView() setupScrollView() - setupBadgeCountForIndex(1) - } - - override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { - super.viewWillTransition(to: size, with: coordinator) - coordinator.animate(alongsideTransition: { [weak self] _ in - self?.segmentioView.interfaceOrientationDidChange() - }, completion: nil) - } - - fileprivate func setupSegmentioView() { - segmentioView.setup( - content: segmentioContent(), - style: segmentioStyle, - options: segmentioOptions() + SegmentioBuilder.buildSegmentioView( + segmentioView: segmentioView, + segmentioStyle: segmentioStyle ) + SegmentioBuilder.setupBadgeCountForIndex(segmentioView, index: 1) segmentioView.selectedSegmentioIndex = selectedSegmentioIndex() segmentioView.valueDidChange = { [weak self] _, segmentIndex in if let scrollViewWidth = self?.scrollView.frame.width { let contentOffsetX = scrollViewWidth * CGFloat(segmentIndex) - self?.scrollView.setContentOffset(CGPoint(x: contentOffsetX, y: 0), animated: true) + self?.scrollView.setContentOffset( + CGPoint(x: contentOffsetX, y: 0), + animated: true + ) } } } - fileprivate func setupBadgeCountForIndex(_ index: Int) { - segmentioView.addBadge(at: index, count: 10, color: ColorPalette.coral) - } - - fileprivate func segmentioContent() -> [SegmentioItem] { - return [ - SegmentioItem(title: "Tornado", image: UIImage(named: "tornado")), - SegmentioItem(title: "Earthquakes", image: UIImage(named: "earthquakes")), - SegmentioItem(title: "Extreme heat", image: UIImage(named: "heat")), - SegmentioItem(title: "Eruption", image: UIImage(named: "eruption")), - SegmentioItem(title: "Floods", image: UIImage(named: "floods")), - SegmentioItem(title: "Wildfires", image: UIImage(named: "wildfires")) - ] - } - - fileprivate func segmentioOptions() -> SegmentioOptions { - var imageContentMode = UIViewContentMode.center - switch segmentioStyle { - case .imageBeforeLabel, .imageAfterLabel: - imageContentMode = .scaleAspectFit - default: - break - } - - return SegmentioOptions( - backgroundColor: ColorPalette.white, - maxVisibleItems: 3, - scrollEnabled: true, - indicatorOptions: segmentioIndicatorOptions(), - horizontalSeparatorOptions: segmentioHorizontalSeparatorOptions(), - verticalSeparatorOptions: segmentioVerticalSeparatorOptions(), - imageContentMode: imageContentMode, - labelTextAlignment: .center, - labelTextNumberOfLines: 1, - segmentStates: segmentioStates(), - animationDuration: 0.3 - ) - } - - fileprivate func segmentioStates() -> SegmentioStates { - let font = UIFont.exampleAvenirMedium(ofSize: 13) - return SegmentioStates( - defaultState: segmentioState( - backgroundColor: .clear, - titleFont: font, - titleTextColor: ColorPalette.grayChateau - ), - selectedState: segmentioState( - backgroundColor: .cyan, - titleFont: font, - titleTextColor: ColorPalette.black - ), - highlightedState: segmentioState( - backgroundColor: ColorPalette.whiteSmoke, - titleFont: font, - titleTextColor: ColorPalette.grayChateau - ) - ) - } - - fileprivate func segmentioState(backgroundColor: UIColor, titleFont: UIFont, titleTextColor: UIColor) -> SegmentioState { - return SegmentioState(backgroundColor: backgroundColor, titleFont: titleFont, titleTextColor: titleTextColor) - } - - fileprivate func segmentioIndicatorOptions() -> SegmentioIndicatorOptions { - return SegmentioIndicatorOptions(type: .bottom, ratio: 1, height: 5, color: ColorPalette.coral) - } - - fileprivate func segmentioHorizontalSeparatorOptions() -> SegmentioHorizontalSeparatorOptions { - return SegmentioHorizontalSeparatorOptions(type: .topAndBottom, height: 1, color: ColorPalette.whiteSmoke) - } - - fileprivate func segmentioVerticalSeparatorOptions() -> SegmentioVerticalSeparatorOptions { - return SegmentioVerticalSeparatorOptions(ratio: 1, color: ColorPalette.whiteSmoke) - } - // Example viewControllers fileprivate func preparedViewControllers() -> [ContentViewController] { let tornadoController = ContentViewController.create() - tornadoController.disaster = Disaster(cardName: "Before tornado", hints: Hints.tornado) + tornadoController.disaster = Disaster( + cardName: "Before tornado", + hints: Hints.tornado + ) let earthquakesController = ContentViewController.create() - earthquakesController.disaster = Disaster(cardName: "Before earthquakes", hints: Hints.earthquakes) + earthquakesController.disaster = Disaster( + cardName: "Before earthquakes", + hints: Hints.earthquakes + ) let extremeHeatController = ContentViewController.create() - extremeHeatController.disaster = Disaster(cardName: "Before extreme heat", hints: Hints.extremeHeat) + extremeHeatController.disaster = Disaster( + cardName: "Before extreme heat", + hints: Hints.extremeHeat + ) let eruptionController = ContentViewController.create() - eruptionController.disaster = Disaster(cardName: "Before eruption", hints: Hints.eruption) + eruptionController.disaster = Disaster( + cardName: "Before eruption", + hints: Hints.eruption + ) let floodsController = ContentViewController.create() - floodsController.disaster = Disaster(cardName: "Before floods", hints: Hints.floods) + floodsController.disaster = Disaster( + cardName: "Before floods", + hints: Hints.floods + ) let wildfiresController = ContentViewController.create() - wildfiresController.disaster = Disaster(cardName: "Before wildfires", hints: Hints.wildfires) + wildfiresController.disaster = Disaster( + cardName: "Before wildfires", + hints: Hints.wildfires + ) return [ tornadoController, diff --git a/Segmentio/Source/Cells/SegmentioCell.swift b/Segmentio/Source/Cells/SegmentioCell.swift index 27f369b..bbc69f6 100644 --- a/Segmentio/Source/Cells/SegmentioCell.swift +++ b/Segmentio/Source/Cells/SegmentioCell.swift @@ -188,7 +188,7 @@ class SegmentioCell: UICollectionViewCell { toItem: containerView, attribute: .centerX, multiplier: 1, - constant: 0.0 + constant: 0 ) let segmentTitleLabelVerticalCenterConstraint = @@ -199,9 +199,12 @@ class SegmentioCell: UICollectionViewCell { toItem: containerView, attribute: .centerY, multiplier: 1, - constant: 0.0 + constant: 0 ) - addConstraints([segmentTitleLabelHorizontalCenterConstraint, segmentTitleLabelVerticalCenterConstraint]) + addConstraints([ + segmentTitleLabelHorizontalCenterConstraint, + segmentTitleLabelVerticalCenterConstraint + ]) } fileprivate func setupImageContainerConstraints() { @@ -220,7 +223,7 @@ class SegmentioCell: UICollectionViewCell { toItem: imageContainerView, attribute: .top, multiplier: 1, - constant: 0.0 + constant: 0 ) let segmentImageViewLeadingConstraint = @@ -231,7 +234,7 @@ class SegmentioCell: UICollectionViewCell { toItem: imageContainerView, attribute: .leading, multiplier: 1, - constant: 0.0 + constant: 0 ) let segmentImageViewTrailingConstraint = @@ -242,7 +245,7 @@ class SegmentioCell: UICollectionViewCell { toItem: imageContainerView, attribute: .trailing, multiplier: 1, - constant: 0.0 + constant: 0 ) let segmentImageViewBottomConstraint = @@ -253,9 +256,14 @@ class SegmentioCell: UICollectionViewCell { toItem: imageContainerView, attribute: .bottom, multiplier: 1, - constant: 0.0 + constant: 0 ) - addConstraints([segmentImageViewBottomConstraint, segmentImageViewTrailingConstraint, segmentImageViewLeadingConstraint, segmentImageViewTopConstraint]) + addConstraints([ + segmentImageViewBottomConstraint, + segmentImageViewTrailingConstraint, + segmentImageViewLeadingConstraint, + segmentImageViewTopConstraint + ]) } diff --git a/Segmentio/Source/Segmentio.swift b/Segmentio/Source/Segmentio.swift index 64887c9..758fafd 100644 --- a/Segmentio/Source/Segmentio.swift +++ b/Segmentio/Source/Segmentio.swift @@ -67,6 +67,11 @@ open class Segmentio: UIView { commonInit() } + open override func layoutSubviews() { + super.layoutSubviews() + reloadSegmentio() + } + fileprivate func commonInit() { setupSegmentedCollectionView() } @@ -187,12 +192,6 @@ open class Segmentio: UIView { segmentioCollectionView?.reloadData() } - open func interfaceOrientationDidChange() { - segmentioCollectionView?.collectionViewLayout.invalidateLayout() - scrollToItemAtContext() - moveShapeLayerAtContext() - } - // MARK: Collection view setup fileprivate func setupCellWithStyle(_ style: SegmentioStyle) { @@ -323,7 +322,6 @@ open class Segmentio: UIView { // MARK: - Actions: // MARK: Reload segmentio public func reloadSegmentio() { -// segmentioCollectionView?.reloadData() segmentioCollectionView?.collectionViewLayout.invalidateLayout() scrollToItemAtContext() moveShapeLayerAtContext() @@ -389,9 +387,10 @@ open class Segmentio: UIView { ) } - if context.isFirstOrSecondVisibleCell == true { + if context.isFirstOrSecondVisibleCell == true && selectedSegmentioIndex != -1 { let newIndex = selectedSegmentioIndex - (context.isFirstIndex ? 1 : 0) let newIndexPath = IndexPath(item: newIndex, section: numberOfSections - 1) + segmentioCollectionView?.scrollToItem( at: newIndexPath, at: UICollectionViewScrollPosition(), diff --git a/Segmentio/Source/SegmentioOptions.swift b/Segmentio/Source/SegmentioOptions.swift index 14528d8..3473d24 100644 --- a/Segmentio/Source/SegmentioOptions.swift +++ b/Segmentio/Source/SegmentioOptions.swift @@ -84,7 +84,7 @@ public struct SegmentioVerticalSeparatorOptions { var ratio: CGFloat var color: UIColor - public init(ratio: CGFloat = 1.0, color: UIColor = .darkGray) { + public init(ratio: CGFloat = 1, color: UIColor = .darkGray) { self.ratio = ratio self.color = color } @@ -107,7 +107,7 @@ public struct SegmentioIndicatorOptions { var height: CGFloat var color: UIColor - public init(type: SegmentioIndicatorType = .bottom, ratio: CGFloat = 1.0, height: CGFloat = 2.0, color: UIColor = .orange) { + public init(type: SegmentioIndicatorType = .bottom, ratio: CGFloat = 1, height: CGFloat = 2, color: UIColor = .orange) { self.type = type self.ratio = ratio self.height = height