diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..7cad1c8 Binary files /dev/null and b/.DS_Store differ diff --git a/NavigationStackDemo.xcodeproj/project.pbxproj b/NavigationStackDemo.xcodeproj/project.pbxproj index fc6121e..ebb53ed 100755 --- a/NavigationStackDemo.xcodeproj/project.pbxproj +++ b/NavigationStackDemo.xcodeproj/project.pbxproj @@ -267,7 +267,6 @@ TargetAttributes = { 8444B0EB1C80238500B53B4E = { CreatedOnToolsVersion = 7.2.1; - DevelopmentTeam = 34MUF9YXTA; }; 8444B0FF1C80238500B53B4E = { CreatedOnToolsVersion = 7.2.1; @@ -423,6 +422,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -459,6 +459,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.2; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_VERSION = 4.2; VALIDATE_PRODUCT = YES; }; name = Release; @@ -468,6 +469,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = NavigationStackDemo/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -481,6 +483,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = NavigationStackDemo/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; diff --git a/NavigationStackDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/NavigationStackDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/NavigationStackDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/NavigationStackDemo.xcodeproj/project.xcworkspace/xcuserdata/hoseinmotlagh.xcuserdatad/UserInterfaceState.xcuserstate b/NavigationStackDemo.xcodeproj/project.xcworkspace/xcuserdata/hoseinmotlagh.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..c085521 Binary files /dev/null and b/NavigationStackDemo.xcodeproj/project.xcworkspace/xcuserdata/hoseinmotlagh.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/NavigationStackDemo.xcodeproj/xcuserdata/hoseinmotlagh.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/NavigationStackDemo.xcodeproj/xcuserdata/hoseinmotlagh.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..bc8c5c8 --- /dev/null +++ b/NavigationStackDemo.xcodeproj/xcuserdata/hoseinmotlagh.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,23 @@ + + + + + + + + + diff --git a/NavigationStackDemo/AppDelegate.swift b/NavigationStackDemo/AppDelegate.swift index 7c11f6d..d446b8a 100755 --- a/NavigationStackDemo/AppDelegate.swift +++ b/NavigationStackDemo/AppDelegate.swift @@ -30,37 +30,37 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + private func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Override point for customization after application launch. - UIApplication.sharedApplication().statusBarStyle = .LightContent + // UIApplication.shared.statusBarStyle = .lightContent UINavigationBar.appearance().titleTextAttributes = [ - NSForegroundColorAttributeName : UIColor.whiteColor(), - NSFontAttributeName : UIFont(name: "OpenSans-Semibold", size: 16)! + NSAttributedString.Key.foregroundColor : UIColor.white, + NSAttributedString.Key.font : UIFont(name: "OpenSans-Semibold", size: 16)! ] return true } - func applicationWillResignActive(application: UIApplication) { + func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - func applicationDidEnterBackground(application: UIApplication) { + func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - func applicationWillEnterForeground(application: UIApplication) { + func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - func applicationDidBecomeActive(application: UIApplication) { + func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - func applicationWillTerminate(application: UIApplication) { + func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } diff --git a/NavigationStackDemo/Base.lproj/Main.storyboard b/NavigationStackDemo/Base.lproj/Main.storyboard index 5e76211..87abbee 100755 --- a/NavigationStackDemo/Base.lproj/Main.storyboard +++ b/NavigationStackDemo/Base.lproj/Main.storyboard @@ -1,85 +1,59 @@ - - + + + + + - - + + - + OpenSans-Light - OpenSans-Light - OpenSans-Light - OpenSans-Light - OpenSans-Light - OpenSans-Light - OpenSans-Light - OpenSans-Light - OpenSans-Light - OpenSans-Light - OpenSans-Light - OpenSans-Light - OpenSans-Light - OpenSans-Light - OpenSans-Light - - - OpenSans - OpenSans + + OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - + - - + + - - + + - + - + - + - + @@ -97,30 +71,30 @@ - + - + - + - + @@ -138,30 +112,30 @@ - + - + - + - + @@ -179,30 +153,30 @@ - + - + - + - + @@ -220,30 +194,30 @@ - + - + - + - + @@ -292,48 +266,48 @@ - - + + - + - + - + - + - + @@ -348,37 +322,37 @@ - + - + - + @@ -393,37 +367,37 @@ - + - + - + @@ -438,37 +412,37 @@ - + - + - + @@ -493,45 +467,45 @@ - + - + - + - - + + - - + + - + - + - + - + - + @@ -540,7 +514,7 @@ @@ -565,15 +539,15 @@ - + @@ -603,10 +577,10 @@ USA - + - + @@ -617,16 +591,16 @@ USA @@ -645,10 +619,10 @@ USA - + - + @@ -659,16 +633,16 @@ USA @@ -687,10 +661,10 @@ USA - + - + @@ -701,16 +675,16 @@ USA @@ -738,9 +712,9 @@ USA - + - + @@ -761,13 +735,13 @@ USA - + - + @@ -785,20 +759,20 @@ USA - + - - + + - + - + @@ -809,20 +783,20 @@ USA @@ -841,10 +815,10 @@ The only moment, the only life we have is in the NOW. What happened a few moment - + - + @@ -864,13 +838,13 @@ The only moment, the only life we have is in the NOW. What happened a few moment @@ -899,9 +873,9 @@ The only moment, the only life we have is in the NOW. What happened a few moment - + - + @@ -909,7 +883,7 @@ The only moment, the only life we have is in the NOW. What happened a few moment - + @@ -918,46 +892,46 @@ The only moment, the only life we have is in the NOW. What happened a few moment - + - - + + - - + + - + - + - + - + @@ -982,14 +956,14 @@ USA - + - + @@ -1019,10 +993,10 @@ USA - + - + @@ -1033,16 +1007,16 @@ USA @@ -1061,10 +1035,10 @@ USA - + - + @@ -1075,16 +1049,16 @@ USA @@ -1112,15 +1086,15 @@ USA - + - + - + @@ -1129,32 +1103,32 @@ USA - + - + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + diff --git a/NavigationStackDemo/ViewControllers/FifthViewController/FifthViewController.swift b/NavigationStackDemo/ViewControllers/FifthViewController/FifthViewController.swift index 42632cb..24d35e5 100755 --- a/NavigationStackDemo/ViewControllers/FifthViewController/FifthViewController.swift +++ b/NavigationStackDemo/ViewControllers/FifthViewController/FifthViewController.swift @@ -11,6 +11,6 @@ import UIKit class FifthViewController: UITableViewController { @IBAction func backHandler(sender: AnyObject) { - navigationController?.popViewControllerAnimated(true) + navigationController?.popViewController(animated: true) } } diff --git a/NavigationStackDemo/ViewControllers/FirstViewController/FirstTableViewController.swift b/NavigationStackDemo/ViewControllers/FirstViewController/FirstTableViewController.swift index 9220ffc..715686d 100755 --- a/NavigationStackDemo/ViewControllers/FirstViewController/FirstTableViewController.swift +++ b/NavigationStackDemo/ViewControllers/FirstViewController/FirstTableViewController.swift @@ -21,7 +21,7 @@ class FirstTableViewController: UITableViewController { navigationItem.titleView = search } - override func viewWillAppear(animated: Bool) { + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) if let navigationController = navigationController { @@ -29,16 +29,15 @@ class FirstTableViewController: UITableViewController { } } - override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { - performSegueWithIdentifier("push", sender: nil) - } - + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + performSegue(withIdentifier: "push", sender: nil) + } } // MARK: UIGestureRecognizerDelegate extension FirstTableViewController: UIGestureRecognizerDelegate { - func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool { + func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { if navigationController?.viewControllers.count == 2 { return true diff --git a/NavigationStackDemo/ViewControllers/SecondViewController/SecondViewController.swift b/NavigationStackDemo/ViewControllers/SecondViewController/SecondViewController.swift index 0e33c82..92a88b3 100755 --- a/NavigationStackDemo/ViewControllers/SecondViewController/SecondViewController.swift +++ b/NavigationStackDemo/ViewControllers/SecondViewController/SecondViewController.swift @@ -10,7 +10,7 @@ import UIKit class SecondViewController: UITableViewController { - override func viewWillAppear(animated: Bool) { + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // if let navigationController = navigationController { @@ -22,11 +22,12 @@ class SecondViewController: UITableViewController { @IBAction func backHandler(sender: AnyObject) { - navigationController?.popViewControllerAnimated(true) + navigationController?.popViewController(animated: true) } - override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { - performSegueWithIdentifier("push", sender: nil) - } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + performSegue(withIdentifier: "push", sender: nil) + } + } diff --git a/NavigationStackDemo/ViewControllers/ThirdViewController/ThirdViewController.swift b/NavigationStackDemo/ViewControllers/ThirdViewController/ThirdViewController.swift index 6347b34..c0f8dc2 100755 --- a/NavigationStackDemo/ViewControllers/ThirdViewController/ThirdViewController.swift +++ b/NavigationStackDemo/ViewControllers/ThirdViewController/ThirdViewController.swift @@ -10,19 +10,19 @@ import UIKit class ThirdViewController: UITableViewController { - @IBInspectable var navbarColor: UIColor = .blackColor() + @IBInspectable var navbarColor: UIColor = .black - override func viewWillAppear(animated: Bool) { + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) } @IBAction func backHandler(sender: AnyObject) { - navigationController?.popViewControllerAnimated(true) + navigationController?.popViewController(animated: true) } - override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { - performSegueWithIdentifier("push", sender: nil) - } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + performSegue(withIdentifier: "push", sender: nil) + } } diff --git a/NavigationStackDemoTests/NavigationStackDemoTests.swift b/NavigationStackDemoTests/NavigationStackDemoTests.swift index b7bb2e5..c1cbb46 100755 --- a/NavigationStackDemoTests/NavigationStackDemoTests.swift +++ b/NavigationStackDemoTests/NavigationStackDemoTests.swift @@ -28,7 +28,7 @@ class NavigationStackDemoTests: XCTestCase { func testPerformanceExample() { // This is an example of a performance test case. - self.measureBlock { + self.measure { // Put the code you want to measure the time of here. } } diff --git a/README.md b/README.md index 91ea5ac..f29fa90 100755 --- a/README.md +++ b/README.md @@ -14,8 +14,9 @@ The [iPhone mockup](https://store.ramotion.com/product/iphone-6-mockups?utm_sour ## Requirements -- iOS 9.0+ -- Xcode 7.2 +- iOS 10.0+ +- Xcode 10 +- swift 4.2 ## Installation diff --git a/Source/CollectionView/Cell/CollectionViewStackCell.swift b/Source/CollectionView/Cell/CollectionViewStackCell.swift index 14abe30..a40d721 100755 --- a/Source/CollectionView/Cell/CollectionViewStackCell.swift +++ b/Source/CollectionView/Cell/CollectionViewStackCell.swift @@ -58,19 +58,19 @@ extension CollectionViewStackCell { contentView.addSubview(imageView) contentView.addConstraints([ - createConstraint(imageView, toItem: contentView, attribute: .Top), - createConstraint(imageView, toItem: contentView, attribute: .Bottom), - createConstraint(imageView, toItem: contentView, attribute: .Left), - createConstraint(imageView, toItem: contentView, attribute: .Right), + createConstraint(imageView, toItem: contentView, attribute: .top), + createConstraint(imageView, toItem: contentView, attribute: .bottom), + createConstraint(imageView, toItem: contentView, attribute: .left), + createConstraint(imageView, toItem: contentView, attribute: .right), ]) return imageView } - private func createConstraint(item: UIImageView, toItem: UIView, attribute: NSLayoutAttribute) -> NSLayoutConstraint { + private func createConstraint(_ item: UIImageView, toItem: UIView, attribute: NSLayoutConstraint.Attribute) -> NSLayoutConstraint { return NSLayoutConstraint(item: item, attribute: attribute, - relatedBy: .Equal, + relatedBy: .equal, toItem: toItem, attribute: attribute, multiplier: 1, @@ -82,11 +82,11 @@ extension CollectionViewStackCell { layer.shadowOpacity = 0.30; layer.shadowRadius = 10.0; layer.shadowOffset = CGSize.zero; - layer.shadowPath = UIBezierPath(rect: bounds).CGPath + layer.shadowPath = UIBezierPath(rect: bounds).cgPath layer.shouldRasterize = true; } - private func addBlurOnImage(image: UIImageView) { + //private func addBlurOnImage(image: UIImageView) { // create effect // UIBlurEffect *blur = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; // @@ -98,7 +98,7 @@ extension CollectionViewStackCell { // [self.imageView addSubview:effectView]; - } + //} } diff --git a/Source/CollectionView/CollectionStackViewController.swift b/Source/CollectionView/CollectionStackViewController.swift index 13438ea..b7e901a 100755 --- a/Source/CollectionView/CollectionStackViewController.swift +++ b/Source/CollectionView/CollectionStackViewController.swift @@ -28,7 +28,7 @@ import UIKit // MARK: CollectionStackViewController protocol CollectionStackViewControllerDelegate: class { - func controllerDidSelected(index index: Int) + func controllerDidSelected(index: Int) } @@ -55,7 +55,7 @@ class CollectionStackViewController: UICollectionViewController { if let collectionView = self.collectionView { collectionView.backgroundColor = bgColor - collectionView.decelerationRate = decelerationRate + collectionView.decelerationRate = UIScrollView.DecelerationRate(rawValue: decelerationRate) } } @@ -65,17 +65,17 @@ class CollectionStackViewController: UICollectionViewController { override func viewDidLoad() { configureCollectionView() - scrolltoIndex(screens.count - 1, animated: false, position: .Left) // move to end + collectionView.scrollToItem(at: IndexPath(item: (screens.count - 1), section: 0), at: .left, animated: true)// move to end } - override func viewDidAppear(animated: Bool) { + override func viewDidAppear(_ animated: Bool) { guard let collectionViewLayout = self.collectionViewLayout as? CollectionViewStackFlowLayout else { fatalError("wrong collection layout") } collectionViewLayout.openAnimating = true - scrolltoIndex(0, animated: true, position: .Left) // open animation + collectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .left, animated: true) // open animation } } @@ -88,9 +88,9 @@ extension CollectionStackViewController { fatalError("wrong collection layout") } - collectionViewLayout.scrollDirection = .Horizontal + collectionViewLayout.scrollDirection = .horizontal collectionView?.showsHorizontalScrollIndicator = false - collectionView?.registerClass(CollectionViewStackCell.self, forCellWithReuseIdentifier: String(CollectionViewStackCell)) + collectionView?.register(CollectionViewStackCell.self, forCellWithReuseIdentifier: "CollectionViewStackCell") } } @@ -99,38 +99,44 @@ extension CollectionStackViewController { extension CollectionStackViewController { - override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return screens.count } - override func collectionView(collectionView: UICollectionView, - willDisplayCell cell: UICollectionViewCell, - forItemAtIndexPath indexPath: NSIndexPath) { +// override func collectionView(collectionView: UICollectionView, +// willDisplayCell cell: UICollectionViewCell, +// forItemAtIndexPath indexPath: NSIndexPath) { +// +// +// } +// } - if let cell = cell as? CollectionViewStackCell { - cell.imageView?.image = screens[indexPath.row] + + override func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { + if let cell = cell as? CollectionViewStackCell { + cell.imageView?.image = screens[indexPath.row] + } + } + + override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewStackCell", + for: indexPath) + return cell } - } - - override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { - let cell = collectionView.dequeueReusableCellWithReuseIdentifier(String(CollectionViewStackCell), - forIndexPath: indexPath) - return cell - } - override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { + override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { delegate?.controllerDidSelected(index: indexPath.row) - guard let currentCell = collectionView.cellForItemAtIndexPath(indexPath) else { + guard let currentCell = collectionView.cellForItem(at: indexPath as IndexPath) else { return } // move cells - UIView.animateWithDuration(0.3, delay: 0, options:.CurveEaseIn, + UIView.animate(withDuration: 0.3, delay: 0, options:.curveEaseIn, animations: { () -> Void in - for cell in self.collectionView!.visibleCells() where cell != currentCell { - let row = self.collectionView?.indexPathForCell(cell)?.row - let xPosition = row < indexPath.row ? cell.center.x - self.view.bounds.size.width * 2 + for cell in self.collectionView!.visibleCells where cell != currentCell { + let row = self.collectionView?.indexPath(for: cell)?.row + let xPosition = row! < indexPath.row ? cell.center.x - self.view.bounds.size.width * 2 : cell.center.x + self.view.bounds.size.width * 2 cell.center = CGPoint(x: xPosition, y: cell.center.y) @@ -138,22 +144,22 @@ extension CollectionStackViewController { }, completion: nil) // move to center current cell - UIView.animateWithDuration(0.2, delay: 0.2, options:.CurveEaseOut, + UIView.animate(withDuration: 0.2, delay: 0.2, options:.curveEaseOut, animations: { () -> Void in let offset = collectionView.contentOffset.x - (self.view.bounds.size.width - collectionView.bounds.size.width * CGFloat(self.overlay)) * CGFloat(indexPath.row) currentCell.center = CGPoint(x: (currentCell.center.x + offset), y: currentCell.center.y) }, completion: nil) // scale current cell - UIView.animateWithDuration(0.2, delay: 0.6, options:.CurveEaseOut, animations: { () -> Void in - let scale = CGAffineTransformMakeScale(1, 1) + UIView.animate(withDuration: 0.2, delay: 0.6, options:.curveEaseOut, animations: { () -> Void in + let scale = CGAffineTransform(scaleX: 1, y: 1) currentCell.transform = scale currentCell.alpha = 1 }) { (success) -> Void in - dispatch_async(dispatch_get_main_queue(), { () -> Void in - self.dismissViewControllerAnimated(false, completion: nil) - }) + DispatchQueue.main.async { + self.dismiss(animated: false, completion: nil) + } } } } @@ -162,11 +168,11 @@ extension CollectionStackViewController { extension CollectionStackViewController: UICollectionViewDelegateFlowLayout { - func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return view.bounds.size } - func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: NSInteger) -> CGFloat { + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: NSInteger) -> CGFloat { return -collectionView.bounds.size.width * CGFloat(overlay) } } @@ -176,8 +182,8 @@ extension CollectionStackViewController: UICollectionViewDelegateFlowLayout { extension CollectionStackViewController { - private func scrolltoIndex(index: Int, animated: Bool , position: UICollectionViewScrollPosition) { - let indexPath = NSIndexPath(forItem: index, inSection: 0) - collectionView?.scrollToItemAtIndexPath(indexPath, atScrollPosition: position, animated: animated) + private func scrolltoIndex(index: Int, animated: Bool , position: UICollectionView.ScrollPosition) { + let indexPath = NSIndexPath(item: index, section: 0) + collectionView?.scrollToItem(at: indexPath as IndexPath, at: position, animated: animated) } } diff --git a/Source/CollectionView/FlowLayout/CollectionViewStackFlowLayout.swift b/Source/CollectionView/FlowLayout/CollectionViewStackFlowLayout.swift index cb5131e..2a072e2 100755 --- a/Source/CollectionView/FlowLayout/CollectionViewStackFlowLayout.swift +++ b/Source/CollectionView/FlowLayout/CollectionViewStackFlowLayout.swift @@ -28,119 +28,118 @@ import UIKit // MARK: CollectionViewStackFlowLayout class CollectionViewStackFlowLayout: UICollectionViewFlowLayout { - - let itemsCount: Int - let overlay: Float // from 0 to 1 - - let maxScale: Float - let scaleRatio: Float - - var additionScale = 1.0 - var openAnimating = false - - var dxOffset: Float = 0 - - init(itemsCount: Int, overlay: Float, scaleRatio: Float, scale: Float) { - self.itemsCount = itemsCount - self.overlay = overlay - self.scaleRatio = scaleRatio - self.maxScale = scale - super.init() - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - + + let itemsCount: Int + let overlay: Float // from 0 to 1 + + let maxScale: Float + let scaleRatio: Float + + var additionScale = 1.0 + var openAnimating = false + + var dxOffset: Float = 0 + + init(itemsCount: Int, overlay: Float, scaleRatio: Float, scale: Float) { + self.itemsCount = itemsCount + self.overlay = overlay + self.scaleRatio = scaleRatio + self.maxScale = scale + super.init() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + } extension CollectionViewStackFlowLayout { - - override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? { - let items = NSArray (array: super.layoutAttributesForElementsInRect(rect)!, copyItems: true) - var headerAttributes: UICollectionViewLayoutAttributes? - items.enumerateObjectsUsingBlock { (object, idex, stop) -> Void in - let attributes = object as! UICollectionViewLayoutAttributes - - if attributes.representedElementKind == UICollectionElementKindSectionHeader { - headerAttributes = attributes - } - else { - self.updateCellAttributes(attributes, headerAttributes: headerAttributes) - } + override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { + let items = NSArray (array: super.layoutAttributesForElements(in: rect)!, copyItems: true) + var headerAttributes: UICollectionViewLayoutAttributes? + + items.enumerateObjects { (object, idex, stop) -> Void in + let attributes = object as! UICollectionViewLayoutAttributes + + if attributes.representedElementKind == UICollectionView.elementKindSectionHeader { + headerAttributes = attributes + } else { + self.updateCellAttributes(attributes: attributes, headerAttributes: headerAttributes) + } + } + return items as? [UICollectionViewLayoutAttributes] } - return items as? [UICollectionViewLayoutAttributes] - } - - func updateCellAttributes(attributes: UICollectionViewLayoutAttributes, headerAttributes: UICollectionViewLayoutAttributes?) { - guard let collectionView = self.collectionView else { - return; + func updateCellAttributes(attributes: UICollectionViewLayoutAttributes, headerAttributes: UICollectionViewLayoutAttributes?) { + + guard let collectionView = self.collectionView else { + return; + } + let itemWidth = collectionView.bounds.size.width - collectionView.bounds.size.width * CGFloat(overlay) + let allWidth = itemWidth * CGFloat(itemsCount - 1) + + // set contentOffset range + let contentOffsetX = min(max(0, collectionView.contentOffset.x), allWidth) + + let scale = transformScale(attributes: attributes, allWidth: allWidth, offset: contentOffsetX) + let move = transformMove(attributes: attributes, itemWidth: itemWidth, offset: contentOffsetX) + attributes.transform = scale.concatenating(move) + attributes.alpha = calculateAlpha(attributes: attributes, itemWidth: itemWidth, offset: contentOffsetX) + + if additionScale > 0 && openAnimating { + additionScale -= 0.02 + additionScale = additionScale < 0 ? 0 : additionScale + } + attributes.zIndex = attributes.indexPath.row } - let itemWidth = collectionView.bounds.size.width - collectionView.bounds.size.width * CGFloat(overlay) - let allWidth = itemWidth * CGFloat(itemsCount - 1) - // set contentOffset range - let contentOffsetX = min(max(0, collectionView.contentOffset.x), allWidth) - - let scale = transformScale(attributes, allWidth: allWidth, offset: contentOffsetX) - let move = transformMove(attributes, itemWidth: itemWidth, offset: contentOffsetX) - attributes.transform = CGAffineTransformConcat(scale, move) - attributes.alpha = calculateAlpha(attributes, itemWidth: itemWidth, offset: contentOffsetX) - - if additionScale > 0 && openAnimating { - additionScale -= 0.02 - additionScale = additionScale < 0 ? 0 : additionScale + override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { + return true } - attributes.zIndex = attributes.indexPath.row - } - - override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool { - return true - } } // MARK: helpers extension CollectionViewStackFlowLayout { - - private func transformScale(attributes: UICollectionViewLayoutAttributes, - allWidth: CGFloat, - offset: CGFloat) -> CGAffineTransform { - var maximum = CGFloat(maxScale) - CGFloat(itemsCount - attributes.indexPath.row) / CGFloat(scaleRatio) - maximum += CGFloat(1.0 - maximum) * CGFloat(additionScale) - - var minimum = CGFloat(maxScale - 0.1) - CGFloat(itemsCount - attributes.indexPath.row) / CGFloat(scaleRatio) - minimum += CGFloat(1.0 - minimum) * CGFloat(additionScale) - - var currentScale = (maximum + minimum) - (minimum + offset / (allWidth / (maximum - minimum))) - currentScale = max(min(maximum, currentScale), minimum) - return CGAffineTransformMakeScale(currentScale, currentScale) - } - - private func transformMove(attributes: UICollectionViewLayoutAttributes, - itemWidth: CGFloat, - offset: CGFloat) -> CGAffineTransform { - var currentContentOffsetX = offset - itemWidth * CGFloat(attributes.indexPath.row) - currentContentOffsetX = min(max(currentContentOffsetX, 0),itemWidth) - - var dx = (currentContentOffsetX / itemWidth) - if let collectionView = self.collectionView { - dx *= collectionView.bounds.size.width / 8.0 - } - dx = currentContentOffsetX - dx - - return CGAffineTransformMakeTranslation(dx, 0) - } - - private func calculateAlpha(attributes: UICollectionViewLayoutAttributes, itemWidth: CGFloat, offset: CGFloat) -> CGFloat { - var currentContentOffsetX = offset - itemWidth * CGFloat(attributes.indexPath.row) - currentContentOffsetX = min(max(currentContentOffsetX, 0),itemWidth) - let dx = (currentContentOffsetX / itemWidth) + private func transformScale(attributes: UICollectionViewLayoutAttributes, + allWidth: CGFloat, + offset: CGFloat) -> CGAffineTransform { + var maximum = CGFloat(maxScale) - CGFloat(itemsCount - attributes.indexPath.row) / CGFloat(scaleRatio) + maximum += CGFloat(1.0 - maximum) * CGFloat(additionScale) + + var minimum = CGFloat(maxScale - 0.1) - CGFloat(itemsCount - attributes.indexPath.row) / CGFloat(scaleRatio) + minimum += CGFloat(1.0 - minimum) * CGFloat(additionScale) + + var currentScale = (maximum + minimum) - (minimum + offset / (allWidth / (maximum - minimum))) + currentScale = max(min(maximum, currentScale), minimum) + return CGAffineTransform(scaleX: currentScale, y: currentScale) + } + + private func transformMove(attributes: UICollectionViewLayoutAttributes, + itemWidth: CGFloat, + offset: CGFloat) -> CGAffineTransform { + var currentContentOffsetX = offset - itemWidth * CGFloat(attributes.indexPath.row) + currentContentOffsetX = min(max(currentContentOffsetX, 0),itemWidth) + + var dx = (currentContentOffsetX / itemWidth) + if let collectionView = self.collectionView { + dx *= collectionView.bounds.size.width / 8.0 + } + dx = currentContentOffsetX - dx + + return CGAffineTransform(translationX: dx, y: 0) + } + + private func calculateAlpha(attributes: UICollectionViewLayoutAttributes, itemWidth: CGFloat, offset: CGFloat) -> CGFloat { + var currentContentOffsetX = offset - itemWidth * CGFloat(attributes.indexPath.row) + currentContentOffsetX = min(max(currentContentOffsetX, 0),itemWidth) + + let dx = (currentContentOffsetX / itemWidth) + + return 1.0 - dx + } - return 1.0 - dx - } - } diff --git a/Source/NavigationStack.swift b/Source/NavigationStack.swift index 5319951..b173249 100755 --- a/Source/NavigationStack.swift +++ b/Source/NavigationStack.swift @@ -28,119 +28,103 @@ import UIKit // MARK: NavigationStack public class NavigationStack: UINavigationController { - - @IBInspectable var overlay: Float = 0.8 - @IBInspectable var scaleRatio: Float = 14.0 - @IBInspectable var scaleValue: Float = 0.99 - @IBInspectable var decelerationRate: CGFloat = UIScrollViewDecelerationRateNormal - - @IBInspectable var bgColor: UIColor = .blackColor() - - private var screens = [UIImage]() - - weak public var stackDelegate: UINavigationControllerDelegate? // use this instead delegate - - public required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - delegate = self - } + @IBInspectable var overlay: Float = 0.8 + @IBInspectable var scaleRatio: Float = 14.0 + @IBInspectable var scaleValue: Float = 0.99 + @IBInspectable var decelerationRate: CGFloat = UIScrollView.DecelerationRate.normal.rawValue + + @IBInspectable var bgColor: UIColor = .black + + private var screens = [UIImage]() + + weak public var stackDelegate: UINavigationControllerDelegate? // use this instead delegate + + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + + delegate = self + } } // MARK: pulbic methods extension NavigationStack { - public func showControllers() { - if screens.count == 0 { - return - } - - var allScreens = screens - allScreens.append(view.takeScreenshot()) - let collectioView = CollectionStackViewController(images: allScreens, - delegate: self, - overlay: overlay, - scaleRatio: scaleRatio, - scaleValue: scaleValue, - bgColor: bgColor, - decelerationRate: decelerationRate) + public func showControllers() { + if screens.count == 0 { + return + } - presentViewController(collectioView, animated: false, completion: nil) - } + var allScreens = screens + allScreens.append(view.takeScreenshot()) + let collectioView = CollectionStackViewController(images: allScreens, + delegate: self, + overlay: overlay, + scaleRatio: scaleRatio, + scaleValue: scaleValue, + bgColor: bgColor, + decelerationRate: decelerationRate) + + present(collectioView, animated: false, completion: nil) + } } // MARK: Additional helpers extension NavigationStack { - - private func popToIndex(index: Int, animated: Bool) { - let viewController = viewControllers[index] - popToViewController(viewController, animated: animated) - } + + private func popToIndex(index: Int, animated: Bool) { + let viewController = viewControllers[index] + popToViewController(viewController, animated: animated) + } } // MARK: UINavigationControllerDelegate extension NavigationStack: UINavigationControllerDelegate { - - public func navigationController(navigationController: UINavigationController, - willShowViewController viewController: UIViewController, - animated: Bool) { - - stackDelegate?.navigationController?(navigationController, willShowViewController: viewController, animated: animated) - - if navigationController.viewControllers.count > screens.count + 1 { - screens.append(view.takeScreenshot()) - } else - if navigationController.viewControllers.count == screens.count && screens.count > 0 { - screens.removeLast() - } - } - - public func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) { - stackDelegate?.navigationController?(navigationController, didShowViewController: viewController, animated: animated) - } - -// ??? -// public func navigationControllerSupportedInterfaceOrientations(navigationController: UINavigationController) -> UIInterfaceOrientationMask { -// return stackDelegate?.navigationControllerSupportedInterfaceOrientations?(navigationController) -// } - -// ??? -// optional public func navigationControllerPreferredInterfaceOrientationForPresentation(navigationController: UINavigationController) -> UIInterfaceOrientation -// - - public func navigationController(navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { - return stackDelegate?.navigationController?(navigationController, interactionControllerForAnimationController: animationController) - } - - public func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { - return stackDelegate?.navigationController?(navigationController, animationControllerForOperation: operation, fromViewController: fromVC, toViewController: toVC) - } - + + public func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) { + stackDelegate?.navigationController?(navigationController, willShow: viewController, animated: animated) + + if navigationController.viewControllers.count > screens.count + 1 { + screens.append(view.takeScreenshot()) + } else + if navigationController.viewControllers.count == screens.count && screens.count > 0 { + screens.removeLast() + } + } + + public func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) { + stackDelegate?.navigationController?(navigationController, didShow: navigationController, animated: animated) + } + + public func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { + return stackDelegate?.navigationController?(navigationController, animationControllerFor: operation, from: fromVC, to: toVC) + } + } extension NavigationStack: CollectionStackViewControllerDelegate { - func controllerDidSelected(index index: Int) { - popToIndex(index, animated: false) - screens.removeRange(index.. UIImage { - - UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, UIScreen.mainScreen().scale) - drawViewHierarchyInRect(self.bounds, afterScreenUpdates: true) - let image = UIGraphicsGetImageFromCurrentImageContext() - UIGraphicsEndImageContext() - - return image - } + func takeScreenshot() -> UIImage { + + UIGraphicsBeginImageContextWithOptions(self.bounds.size, true, UIScreen.main.scale) + drawHierarchy(in: self.bounds, afterScreenUpdates: false) + + let image = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + + return image! + } }