Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions UPCarouselFlowLayout/UPCarouselFlowLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,23 @@ public class UPCarouselFlowLayout: UICollectionViewFlowLayout {
var size: CGSize
var direction: UICollectionViewScrollDirection
func isEqual(otherState: LayoutState) -> Bool {
return CGSizeEqualToSize(self.size, otherState.size) && self.direction == otherState.direction
return self.size.equalTo(otherState.size) && self.direction == otherState.direction
}
}

@IBInspectable public var sideItemScale: CGFloat = 0.6
@IBInspectable public var sideItemAlpha: CGFloat = 0.6
public var spacingMode = UPCarouselFlowLayoutSpacingMode.fixed(spacing: 40)

private var state = LayoutState(size: CGSizeZero, direction: .Horizontal)
private var state = LayoutState(size: CGSize.zero, direction: .horizontal)


override public func prepareLayout() {
super.prepareLayout()
override public func prepare() {
super.prepare()

let currentState = LayoutState(size: self.collectionView!.bounds.size, direction: self.scrollDirection)

if !self.state.isEqual(currentState) {
if !self.state.isEqual(otherState: currentState) {
self.setupCollectionView()
self.updateLayout()
self.state = currentState
Expand All @@ -55,7 +55,7 @@ public class UPCarouselFlowLayout: UICollectionViewFlowLayout {
guard let collectionView = self.collectionView else { return }

let collectionSize = collectionView.bounds.size
let isHorizontal = (self.scrollDirection == .Horizontal)
let isHorizontal = (self.scrollDirection == .horizontal)

let yInset = (collectionSize.height - self.itemSize.height) / 2
let xInset = (collectionSize.width - self.itemSize.width) / 2
Expand All @@ -73,20 +73,20 @@ public class UPCarouselFlowLayout: UICollectionViewFlowLayout {
}
}

override public func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
override public func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}

override public func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let superAttributes = super.layoutAttributesForElementsInRect(rect),
override public func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let superAttributes = super.layoutAttributesForElements(in: rect),
let attributes = NSArray(array: superAttributes, copyItems: true) as? [UICollectionViewLayoutAttributes]
else { return nil }
return attributes.map({ self.transformLayoutAttributes($0) })
return attributes.map({ self.transformLayoutAttributes(attributes: $0) })
}

private func transformLayoutAttributes(attributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
guard let collectionView = self.collectionView else { return attributes }
let isHorizontal = (self.scrollDirection == .Horizontal)
let isHorizontal = (self.scrollDirection == .horizontal)

let collectionCenter = isHorizontal ? collectionView.frame.size.width/2 : collectionView.frame.size.height/2
let offset = isHorizontal ? collectionView.contentOffset.x : collectionView.contentOffset.y
Expand All @@ -104,23 +104,23 @@ public class UPCarouselFlowLayout: UICollectionViewFlowLayout {
return attributes
}

override public func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
guard let collectionView = collectionView where !collectionView.pagingEnabled,
let layoutAttributes = self.layoutAttributesForElementsInRect(collectionView.bounds)
else { return super.targetContentOffsetForProposedContentOffset(proposedContentOffset) }
override public func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
guard let collectionView = collectionView , !collectionView.isPagingEnabled,
let layoutAttributes = self.layoutAttributesForElements(in: collectionView.bounds)
else { return super.targetContentOffset(forProposedContentOffset: proposedContentOffset) }

let isHorizontal = (self.scrollDirection == .Horizontal)
let isHorizontal = (self.scrollDirection == .horizontal)

let midSide = (isHorizontal ? collectionView.bounds.size.width : collectionView.bounds.size.height) / 2
let proposedContentOffsetCenterOrigin = (isHorizontal ? proposedContentOffset.x : proposedContentOffset.y) + midSide

var targetContentOffset: CGPoint
if isHorizontal {
let closest = layoutAttributes.sort { abs($0.center.x - proposedContentOffsetCenterOrigin) < abs($1.center.x - proposedContentOffsetCenterOrigin) }.first ?? UICollectionViewLayoutAttributes()
let closest = layoutAttributes.sorted { abs($0.center.x - proposedContentOffsetCenterOrigin) < abs($1.center.x - proposedContentOffsetCenterOrigin) }.first ?? UICollectionViewLayoutAttributes()
targetContentOffset = CGPoint(x: floor(closest.center.x - midSide), y: proposedContentOffset.y)
}
else {
let closest = layoutAttributes.sort { abs($0.center.y - proposedContentOffsetCenterOrigin) < abs($1.center.y - proposedContentOffsetCenterOrigin) }.first ?? UICollectionViewLayoutAttributes()
let closest = layoutAttributes.sorted { abs($0.center.y - proposedContentOffsetCenterOrigin) < abs($1.center.y - proposedContentOffsetCenterOrigin) }.first ?? UICollectionViewLayoutAttributes()
targetContentOffset = CGPoint(x: proposedContentOffset.x, y: floor(closest.center.y - midSide))
}

Expand Down
14 changes: 12 additions & 2 deletions UPCarouselFlowLayoutDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,13 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0730;
LastUpgradeCheck = 0730;
LastUpgradeCheck = 0800;
ORGANIZATIONNAME = "Paul Ulric";
TargetAttributes = {
01D3876A1D1C4B9D00CE4E1F = {
CreatedOnToolsVersion = 7.3.1;
DevelopmentTeam = 5LPW7LLHS8;
DevelopmentTeam = 79S2A7FTB9;
LastSwiftMigration = 0800;
};
};
};
Expand Down Expand Up @@ -201,8 +202,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
Expand Down Expand Up @@ -246,8 +249,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
Expand All @@ -266,6 +271,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
VALIDATE_PRODUCT = YES;
};
name = Release;
Expand All @@ -274,21 +280,25 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 79S2A7FTB9;
INFOPLIST_FILE = UPCarouselFlowLayoutDemo/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = UP.UPCarouselFlowLayoutDemo;
PRODUCT_NAME = UPCarouselFlowLayoutDemo;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
01D3877F1D1C4B9D00CE4E1F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 79S2A7FTB9;
INFOPLIST_FILE = UPCarouselFlowLayoutDemo/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = UP.UPCarouselFlowLayoutDemo;
PRODUCT_NAME = UPCarouselFlowLayoutDemo;
SWIFT_VERSION = 3.0;
};
name = Release;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "29x29",
Expand Down
13 changes: 7 additions & 6 deletions UPCarouselFlowLayoutDemo/Base.lproj/LaunchScreen.storyboard
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8150" systemVersion="15A204g" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11201" systemVersion="16A313a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8122"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
Expand All @@ -13,10 +15,9 @@
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
Expand Down
2 changes: 1 addition & 1 deletion UPCarouselFlowLayoutDemo/CarouselCollectionViewCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ class CarouselCollectionViewCell: UICollectionViewCell {

self.layer.cornerRadius = max(self.frame.size.width, self.frame.size.height) / 2
self.layer.borderWidth = 10
self.layer.borderColor = UIColor(red: 110.0/255.0, green: 80.0/255.0, blue: 140.0/255.0, alpha: 1.0).CGColor
self.layer.borderColor = UIColor(red: 110.0/255.0, green: 80.0/255.0, blue: 140.0/255.0, alpha: 1.0).cgColor
}
}
20 changes: 10 additions & 10 deletions UPCarouselFlowLayoutDemo/GradientView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,22 @@ import UIKit

class GradientView: UIView {

override func drawRect(rect: CGRect) {
let colorSpace: CGColorSpaceRef = CGColorSpaceCreateDeviceRGB()!
let context: CGContextRef = UIGraphicsGetCurrentContext()!
CGContextSaveGState(context)
override func draw(_ rect: CGRect) {
let colorSpace: CGColorSpace = CGColorSpaceCreateDeviceRGB()
let context: CGContext = UIGraphicsGetCurrentContext()!
context.saveGState()

let startColor: UIColor = UIColor(red: 79.0/255.0, green: 30.0/255.0, blue: 122.0/255.0, alpha: 1.0)
let endColor: UIColor = UIColor(red: 46.0/255.0, green: 12.0/255.0, blue: 80.0/255.0, alpha: 1.0)
let colors = [startColor.CGColor, endColor.CGColor]
let colors = [startColor.cgColor, endColor.cgColor]
let locations: [CGFloat] = [0, 1]
let gradient: CGGradientRef = CGGradientCreateWithColors(colorSpace, colors, locations)!
let gradient: CGGradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: locations)!

let startPoint: CGPoint = CGPoint(x:CGRectGetMidX(rect), y: CGRectGetMinY(rect))
let endPoint: CGPoint = CGPoint(x: CGRectGetMidX(rect), y: CGRectGetMaxY(rect))
let startPoint: CGPoint = CGPoint(x:rect.midX, y: rect.minY)
let endPoint: CGPoint = CGPoint(x: rect.midX, y: rect.maxY)

CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, [])
CGContextRestoreGState(context)
context.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: [])
context.restoreGState()
}

}
38 changes: 22 additions & 16 deletions UPCarouselFlowLayoutDemo/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
import UIKit

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
@available(iOS 6.0, *)
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//NOT IMPLEMENTED
return UICollectionViewCell()
}


@IBOutlet weak var infoLabel: UILabel!
@IBOutlet weak var detailLabel: UILabel!
Expand All @@ -19,15 +25,15 @@ class ViewController: UIViewController, UICollectionViewDelegate, UICollectionVi
private var currentPage: Int = 0 {
didSet {
let character = self.items[self.currentPage]
self.infoLabel.text = character.name.uppercaseString
self.detailLabel.text = character.movie.uppercaseString
self.infoLabel.text = character.name.uppercased()
self.detailLabel.text = character.movie.uppercased()
}
}

private var pageSize: CGSize {
let layout = self.collectionView.collectionViewLayout as! UPCarouselFlowLayout
var pageSize = layout.itemSize
if layout.scrollDirection == .Horizontal {
if layout.scrollDirection == .horizontal {
pageSize.width += layout.minimumLineSpacing
} else {
pageSize.height += layout.minimumLineSpacing
Expand All @@ -36,7 +42,7 @@ class ViewController: UIViewController, UICollectionViewDelegate, UICollectionVi
}

private var orientation: UIDeviceOrientation {
return UIDevice.currentDevice().orientation
return UIDevice.current.orientation
}


Expand All @@ -48,7 +54,7 @@ class ViewController: UIViewController, UICollectionViewDelegate, UICollectionVi

self.currentPage = 0

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.rotationDidChange), name: UIDeviceOrientationDidChangeNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.rotationDidChange), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}

private func setupLayout() {
Expand All @@ -71,12 +77,12 @@ class ViewController: UIViewController, UICollectionViewDelegate, UICollectionVi

@objc private func rotationDidChange() {
let layout = self.collectionView.collectionViewLayout as! UPCarouselFlowLayout
let direction: UICollectionViewScrollDirection = UIDeviceOrientationIsPortrait(orientation) ? .Horizontal : .Vertical
let direction: UICollectionViewScrollDirection = UIDeviceOrientationIsPortrait(orientation) ? .horizontal : .vertical
layout.scrollDirection = direction
if currentPage > 0 {
let indexPath = NSIndexPath(forItem: currentPage, inSection: 0)
let scrollPosition: UICollectionViewScrollPosition = UIDeviceOrientationIsPortrait(orientation) ? .CenteredHorizontally : .CenteredVertically
self.collectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: scrollPosition, animated: false)
let indexPath = NSIndexPath(item: currentPage, section: 0)
let scrollPosition: UICollectionViewScrollPosition = UIDeviceOrientationIsPortrait(orientation) ? .centeredHorizontally : .centeredVertically
self.collectionView.scrollToItem(at: indexPath as IndexPath, at: scrollPosition, animated: false)
}
}

Expand All @@ -86,31 +92,31 @@ class ViewController: UIViewController, UICollectionViewDelegate, UICollectionVi
return 1
}

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return items.count
}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(CarouselCollectionViewCell.identifier, forIndexPath: indexPath) as! CarouselCollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CarouselCollectionViewCell.identifier, for: indexPath as IndexPath) as! CarouselCollectionViewCell
let character = items[indexPath.row]
cell.image.image = UIImage(named: character.imageName)
return cell
}

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let character = items[indexPath.row]
let alert = UIAlertController(title: character.name, message: nil, preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
presentViewController(alert, animated: true, completion: nil)
let alert = UIAlertController(title: character.name, message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alert, animated: true, completion: nil)
}


// MARK: - UIScrollViewDelegate

func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
let layout = self.collectionView.collectionViewLayout as! UPCarouselFlowLayout
let pageSide = (layout.scrollDirection == .Horizontal) ? self.pageSize.width : self.pageSize.height
let offset = (layout.scrollDirection == .Horizontal) ? scrollView.contentOffset.x : scrollView.contentOffset.y
let pageSide = (layout.scrollDirection == .horizontal) ? self.pageSize.width : self.pageSize.height
let offset = (layout.scrollDirection == .horizontal) ? scrollView.contentOffset.x : scrollView.contentOffset.y
currentPage = Int(floor((offset - pageSide / 2) / pageSide) + 1)
}

Expand Down