Compare commits

..

3 Commits

Author SHA1 Message Date
Arnaud Dorgans c125f52695 fix open var 2018-01-03 11:02:50 +01:00
Arnaud Dorgans 075fb6c75b add exemples & delegate 2018-01-03 10:23:49 +01:00
Arnaud Dorgans 03e9dbd3a4 add CocoaProxy 2017-12-27 23:26:31 +01:00
18 changed files with 730 additions and 209 deletions
@@ -9,12 +9,15 @@
/* Begin PBXBuildFile section */
5259B95F4E58F763F6C70333 /* Pods_InfiniteLayout_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A6830D8B970E919B725A0D5E /* Pods_InfiniteLayout_Example.framework */; };
607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; };
607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; };
607FACD81AFB9204008FA782 /* CustomViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* CustomViewController.swift */; };
607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; };
607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; };
607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; };
607FACEC1AFB9204008FA782 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* Tests.swift */; };
D403973F1FEBFA9D006C41D2 /* Cell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D403973E1FEBFA9D006C41D2 /* Cell.swift */; };
D4162A391FF502A900AC2572 /* CustomLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4162A381FF502A900AC2572 /* CustomLayout.swift */; };
D43362D11FF64B330040C679 /* BaseCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43362CF1FF64B330040C679 /* BaseCollectionViewController.swift */; };
D4B9816E1FFCCC900016C676 /* PickerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4B9816D1FFCCC900016C676 /* PickerController.swift */; };
E997A539C8278E7A661C9F91 /* Pods_InfiniteLayout_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C50F79B0DFFDE95D322480B2 /* Pods_InfiniteLayout_Tests.framework */; };
/* End PBXBuildFile section */
@@ -35,7 +38,7 @@
607FACD01AFB9204008FA782 /* InfiniteLayout_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = InfiniteLayout_Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
607FACD71AFB9204008FA782 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
607FACD71AFB9204008FA782 /* CustomViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomViewController.swift; sourceTree = "<group>"; };
607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
@@ -46,6 +49,9 @@
AD3D900D0067605DEAFF148B /* Pods-InfiniteLayout_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InfiniteLayout_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-InfiniteLayout_Example/Pods-InfiniteLayout_Example.release.xcconfig"; sourceTree = "<group>"; };
C50F79B0DFFDE95D322480B2 /* Pods_InfiniteLayout_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_InfiniteLayout_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D403973E1FEBFA9D006C41D2 /* Cell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cell.swift; sourceTree = "<group>"; };
D4162A381FF502A900AC2572 /* CustomLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomLayout.swift; sourceTree = "<group>"; };
D43362CF1FF64B330040C679 /* BaseCollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseCollectionViewController.swift; sourceTree = "<group>"; };
D4B9816D1FFCCC900016C676 /* PickerController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickerController.swift; sourceTree = "<group>"; };
EF577FD009F0E2F96F1CECC6 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; };
F900DDE615FA1056EB58998B /* Pods-InfiniteLayout_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InfiniteLayout_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InfiniteLayout_Tests/Pods-InfiniteLayout_Tests.debug.xcconfig"; sourceTree = "<group>"; };
FD6AC573B93C313B5BDFF3FE /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
@@ -96,8 +102,9 @@
isa = PBXGroup;
children = (
607FACD51AFB9204008FA782 /* AppDelegate.swift */,
607FACD71AFB9204008FA782 /* ViewController.swift */,
D403973E1FEBFA9D006C41D2 /* Cell.swift */,
D43362D31FF64B9E0040C679 /* Base */,
D43362CC1FF64AD30040C679 /* Custom */,
D4B9816C1FFCCC5B0016C676 /* Picker */,
607FACD91AFB9204008FA782 /* Main.storyboard */,
607FACDC1AFB9204008FA782 /* Images.xcassets */,
607FACDE1AFB9204008FA782 /* LaunchScreen.xib */,
@@ -151,6 +158,32 @@
name = Frameworks;
sourceTree = "<group>";
};
D43362CC1FF64AD30040C679 /* Custom */ = {
isa = PBXGroup;
children = (
607FACD71AFB9204008FA782 /* CustomViewController.swift */,
D4162A381FF502A900AC2572 /* CustomLayout.swift */,
);
name = Custom;
sourceTree = "<group>";
};
D43362D31FF64B9E0040C679 /* Base */ = {
isa = PBXGroup;
children = (
D403973E1FEBFA9D006C41D2 /* Cell.swift */,
D43362CF1FF64B330040C679 /* BaseCollectionViewController.swift */,
);
name = Base;
sourceTree = "<group>";
};
D4B9816C1FFCCC5B0016C676 /* Picker */ = {
isa = PBXGroup;
children = (
D4B9816D1FFCCC900016C676 /* PickerController.swift */,
);
name = Picker;
sourceTree = "<group>";
};
E938139B99B9D91C14707C07 /* Pods */ = {
isa = PBXGroup;
children = (
@@ -291,10 +324,12 @@
);
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-InfiniteLayout_Example/Pods-InfiniteLayout_Example-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/CocoaProxy/CocoaProxy.framework",
"${BUILT_PRODUCTS_DIR}/InfiniteLayout/InfiniteLayout.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaProxy.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/InfiniteLayout.framework",
);
runOnlyForDeploymentPostprocessing = 0;
@@ -375,9 +410,12 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
607FACD81AFB9204008FA782 /* ViewController.swift in Sources */,
607FACD81AFB9204008FA782 /* CustomViewController.swift in Sources */,
607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */,
D4162A391FF502A900AC2572 /* CustomLayout.swift in Sources */,
D4B9816E1FFCCC900016C676 /* PickerController.swift in Sources */,
D403973F1FEBFA9D006C41D2 /* Cell.swift in Sources */,
D43362D11FF64B330040C679 /* BaseCollectionViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+348 -27
View File
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="yGQ-hH-2v6">
<device id="retina5_9" orientation="portrait">
<device id="retina3_5" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@@ -14,68 +16,387 @@
<objects>
<navigationController id="yGQ-hH-2v6" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="IdE-R7-9TG">
<rect key="frame" x="0.0" y="44" width="375" height="44"/>
<rect key="frame" x="0.0" y="20" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="sSL-wr-E9v" kind="relationship" relationship="rootViewController" id="6hU-n3-d5H"/>
<segue destination="pMz-7t-sA5" kind="relationship" relationship="rootViewController" id="AAf-BN-dLc"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="0uD-Xz-jjT" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-988" y="37"/>
<point key="canvasLocation" x="-1644" y="61"/>
</scene>
<!--View Controller-->
<scene sceneID="Tsa-GF-Rqw">
<!--InfiniteLayout-->
<scene sceneID="fMt-PB-wyT">
<objects>
<collectionViewController id="sSL-wr-E9v" customClass="ViewController" customModule="InfiniteLayout_Example" customModuleProvider="target" sceneMemberID="viewController">
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="BuB-JB-b15" customClass="InfiniteCollectionView" customModule="InfiniteLayout">
<rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
<tableViewController id="pMz-7t-sA5" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="YNN-Jo-hL3">
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="Tcc-xt-sXE">
<size key="itemSize" width="150" height="100"/>
<sections>
<tableViewSection id="wLh-Qy-wV4">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="VSq-Pr-6ay" style="IBUITableViewCellStyleDefault" id="Ave-Hr-Gmz">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Ave-Hr-Gmz" id="Fri-pG-UG3">
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Horizontal Layout" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="VSq-Pr-6ay">
<rect key="frame" x="16" y="0.0" width="288" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
<connections>
<segue destination="CU7-Hg-6kG" kind="show" id="yzb-gl-6Xz"/>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="Efh-hp-Yw4" style="IBUITableViewCellStyleDefault" id="e4W-KK-bkI">
<rect key="frame" x="0.0" y="44" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="e4W-KK-bkI" id="WDz-rM-Z2L">
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Vertical Layout" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Efh-hp-Yw4">
<rect key="frame" x="16" y="0.0" width="288" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
<connections>
<segue destination="9P2-Ud-D2M" kind="show" id="H8w-EO-laS"/>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="9We-VT-VYi" style="IBUITableViewCellStyleDefault" id="5Ku-tY-Gtv">
<rect key="frame" x="0.0" y="88" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="5Ku-tY-Gtv" id="M7f-Mo-aWc">
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Custom Layout" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="9We-VT-VYi">
<rect key="frame" x="16" y="0.0" width="288" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
<connections>
<segue destination="ctO-Ld-yhL" kind="show" id="qss-AL-dgi"/>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="c9c-gc-NDL" style="IBUITableViewCellStyleDefault" id="7Dq-og-5lN">
<rect key="frame" x="0.0" y="132" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="7Dq-og-5lN" id="XGb-gg-zbn">
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Picker" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="c9c-gc-NDL">
<rect key="frame" x="16" y="0.0" width="288" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
<connections>
<segue destination="nUW-3u-2O9" kind="show" id="SPm-WC-Yf4"/>
</connections>
</tableViewCell>
</cells>
</tableViewSection>
</sections>
<connections>
<outlet property="dataSource" destination="pMz-7t-sA5" id="OC9-mx-dmD"/>
<outlet property="delegate" destination="pMz-7t-sA5" id="nwI-aQ-G7d"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="InfiniteLayout" id="6dR-xO-LQz"/>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="N5O-nh-h2i" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-770" y="61"/>
</scene>
<!--Custom Layout-->
<scene sceneID="Nwi-KZ-nuX">
<objects>
<viewController id="ctO-Ld-yhL" customClass="CustomViewController" customModule="InfiniteLayout_Example" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="pkO-J5-FlB"/>
<viewControllerLayoutGuide type="bottom" id="q9H-d0-4cm"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="C5p-bu-Djh">
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="enX-ef-ELn" customClass="InfiniteCollectionView" customModule="InfiniteLayout">
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<collectionViewLayout key="collectionViewLayout" id="ZR7-Jn-ewG" customClass="CustomLayout" customModule="InfiniteLayout_Example" customModuleProvider="target"/>
<cells>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="cell" id="w1M-Ws-9fK" customClass="Cell" customModule="InfiniteLayout_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="gVT-2b-OS8" customClass="CellView" customModule="InfiniteLayout_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="styleIndex">
<integer key="value" value="2"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
</subviews>
</view>
<constraints>
<constraint firstItem="gVT-2b-OS8" firstAttribute="top" secondItem="w1M-Ws-9fK" secondAttribute="top" id="9qG-Sx-gVG"/>
<constraint firstAttribute="bottom" secondItem="gVT-2b-OS8" secondAttribute="bottom" id="BOm-tM-pkP"/>
<constraint firstAttribute="trailing" secondItem="gVT-2b-OS8" secondAttribute="trailing" id="HC4-Mv-T4P"/>
<constraint firstItem="gVT-2b-OS8" firstAttribute="leading" secondItem="w1M-Ws-9fK" secondAttribute="leading" id="jH9-f5-fxA"/>
</constraints>
<connections>
<outlet property="cellView" destination="gVT-2b-OS8" id="Em8-Ah-Jzb"/>
</connections>
</collectionViewCell>
</cells>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="boolean" keyPath="isItemPagingEnabled" value="YES"/>
</userDefinedRuntimeAttributes>
<connections>
<outlet property="dataSource" destination="ctO-Ld-yhL" id="bXu-Jz-K7t"/>
<outlet property="delegate" destination="ctO-Ld-yhL" id="Vz4-5J-frZ"/>
</connections>
</collectionView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="enX-ef-ELn" firstAttribute="top" secondItem="C5p-bu-Djh" secondAttribute="top" id="2nB-Om-PsD"/>
<constraint firstAttribute="bottom" secondItem="enX-ef-ELn" secondAttribute="bottom" id="Tdv-eb-r3X"/>
<constraint firstAttribute="trailing" secondItem="enX-ef-ELn" secondAttribute="trailing" id="ZM0-nc-pUD"/>
<constraint firstItem="enX-ef-ELn" firstAttribute="leading" secondItem="C5p-bu-Djh" secondAttribute="leading" id="uX4-ox-gnL"/>
</constraints>
</view>
<navigationItem key="navigationItem" title="Custom Layout" id="hZl-1w-5Nq"/>
<connections>
<outlet property="infiniteCollectionView" destination="enX-ef-ELn" id="jKo-DT-4uH"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="4s9-AY-FII" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-770" y="802"/>
</scene>
<!--Infinite Delegate-->
<scene sceneID="HqS-9O-oG4">
<objects>
<viewController automaticallyAdjustsScrollViewInsets="NO" id="nUW-3u-2O9" customClass="PickerController" customModule="InfiniteLayout_Example" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="zFz-ZQ-lzW"/>
<viewControllerLayoutGuide type="bottom" id="ZuO-bs-QWL"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Vhd-CK-34X">
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="Yg1-5Z-6FI" customClass="InfiniteCollectionView" customModule="InfiniteLayout">
<rect key="frame" x="0.0" y="288" width="320" height="192"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="1000" id="PTo-iT-zZX">
<size key="itemSize" width="200" height="150"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="10" maxY="0.0"/>
</collectionViewFlowLayout>
<cells>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="cell" id="7Np-kQ-f93" customClass="Cell" customModule="InfiniteLayout_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="21" width="200" height="150"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
<rect key="frame" x="0.0" y="0.0" width="200" height="150"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Uz9-xR-d0L" customClass="CellView" customModule="InfiniteLayout_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="200" height="150"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="styleIndex">
<integer key="value" value="1"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
</subviews>
</view>
<constraints>
<constraint firstItem="Uz9-xR-d0L" firstAttribute="top" secondItem="7Np-kQ-f93" secondAttribute="top" id="2lt-hb-Zl9"/>
<constraint firstItem="Uz9-xR-d0L" firstAttribute="leading" secondItem="7Np-kQ-f93" secondAttribute="leading" id="Hj7-OH-iis"/>
<constraint firstAttribute="trailing" secondItem="Uz9-xR-d0L" secondAttribute="trailing" id="mr0-wj-ftP"/>
<constraint firstAttribute="bottom" secondItem="Uz9-xR-d0L" secondAttribute="bottom" id="t8H-tx-AHw"/>
</constraints>
<connections>
<outlet property="cellView" destination="Uz9-xR-d0L" id="Q84-nb-acR"/>
</connections>
</collectionViewCell>
</cells>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="boolean" keyPath="isItemPagingEnabled" value="YES"/>
<userDefinedRuntimeAttribute type="number" keyPath="velocityMultiplier">
<real key="value" value="1"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<connections>
<outlet property="dataSource" destination="nUW-3u-2O9" id="vHT-UO-3ny"/>
<outlet property="delegate" destination="nUW-3u-2O9" id="cXx-OK-csN"/>
<outlet property="infiniteDelegate" destination="nUW-3u-2O9" id="FQk-xA-mjb"/>
</connections>
</collectionView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="n2a-eR-E9T" customClass="CellView" customModule="InfiniteLayout_Example" customModuleProvider="target">
<rect key="frame" x="53.5" y="66.5" width="213" height="213"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="n2a-eR-E9T" firstAttribute="height" secondItem="Vhd-CK-34X" secondAttribute="width" multiplier="2:3" id="15l-Xa-cgF"/>
<constraint firstItem="n2a-eR-E9T" firstAttribute="centerY" secondItem="Yg1-5Z-6FI" secondAttribute="top" multiplier="0.6" id="831-T2-ANf"/>
<constraint firstItem="Yg1-5Z-6FI" firstAttribute="height" secondItem="Vhd-CK-34X" secondAttribute="height" multiplier="0.4" id="A7s-lr-k2k"/>
<constraint firstItem="ZuO-bs-QWL" firstAttribute="top" secondItem="Yg1-5Z-6FI" secondAttribute="bottom" id="GmZ-Db-ynH"/>
<constraint firstAttribute="trailing" secondItem="Yg1-5Z-6FI" secondAttribute="trailing" id="PSV-WU-ltt"/>
<constraint firstItem="Yg1-5Z-6FI" firstAttribute="leading" secondItem="Vhd-CK-34X" secondAttribute="leading" id="UQ7-m3-LKy"/>
<constraint firstItem="n2a-eR-E9T" firstAttribute="centerX" secondItem="Vhd-CK-34X" secondAttribute="centerX" id="hN7-qa-9iE"/>
<constraint firstItem="n2a-eR-E9T" firstAttribute="width" secondItem="Vhd-CK-34X" secondAttribute="width" multiplier="2:3" id="k1E-14-EKC"/>
</constraints>
</view>
<navigationItem key="navigationItem" title="Picker" id="Op4-F3-Cvs"/>
<connections>
<outlet property="infiniteCollectionView" destination="Yg1-5Z-6FI" id="dYW-hl-GxB"/>
<outlet property="selectedView" destination="n2a-eR-E9T" id="kE8-NA-C2Q"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="jlK-LR-KNy" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="22" y="802"/>
</scene>
<!--Horizontal Layout-->
<scene sceneID="0Xz-LA-moA">
<objects>
<collectionViewController id="CU7-Hg-6kG" customClass="BaseCollectionViewController" customModule="InfiniteLayout_Example" customModuleProvider="target" sceneMemberID="viewController">
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="prototypes" id="Iuy-Ov-jLz" customClass="InfiniteCollectionView" customModule="InfiniteLayout">
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="1000" id="i7U-Tf-kfd">
<size key="itemSize" width="250" height="150"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="10" maxY="0.0"/>
</collectionViewFlowLayout>
<cells>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="cell" id="Vf0-ro-DM5" customClass="Cell" customModule="InfiniteLayout_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="150" height="100"/>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="cell" id="BVQ-cb-bj4" customClass="Cell" customModule="InfiniteLayout_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="133" width="250" height="150"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
<rect key="frame" x="0.0" y="0.0" width="150" height="100"/>
<rect key="frame" x="0.0" y="0.0" width="250" height="150"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="SWd-w1-K3N" customClass="CellView" customModule="InfiniteLayout_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="150" height="100"/>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="1wM-ge-YKX" customClass="CellView" customModule="InfiniteLayout_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="250" height="150"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
</subviews>
</view>
<constraints>
<constraint firstItem="SWd-w1-K3N" firstAttribute="leading" secondItem="Vf0-ro-DM5" secondAttribute="leading" id="HM6-Rd-74h"/>
<constraint firstItem="SWd-w1-K3N" firstAttribute="top" secondItem="Vf0-ro-DM5" secondAttribute="top" id="jJh-U5-WWC"/>
<constraint firstAttribute="bottom" secondItem="SWd-w1-K3N" secondAttribute="bottom" id="n3V-C9-rAP"/>
<constraint firstAttribute="trailing" secondItem="SWd-w1-K3N" secondAttribute="trailing" id="oPa-mO-RJ6"/>
<constraint firstAttribute="bottom" secondItem="1wM-ge-YKX" secondAttribute="bottom" id="44V-6k-Vxi"/>
<constraint firstAttribute="trailing" secondItem="1wM-ge-YKX" secondAttribute="trailing" id="BO0-dS-ek7"/>
<constraint firstItem="1wM-ge-YKX" firstAttribute="leading" secondItem="BVQ-cb-bj4" secondAttribute="leading" id="O2r-kl-QZo"/>
<constraint firstItem="1wM-ge-YKX" firstAttribute="top" secondItem="BVQ-cb-bj4" secondAttribute="top" id="kT9-T5-w19"/>
</constraints>
<connections>
<outlet property="cellView" destination="SWd-w1-K3N" id="2A6-17-L1b"/>
<outlet property="cellView" destination="1wM-ge-YKX" id="BFc-xc-0VL"/>
</connections>
</collectionViewCell>
</cells>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="boolean" keyPath="isItemPagingEnabled" value="YES"/>
<userDefinedRuntimeAttribute type="number" keyPath="velocityMultiplier">
<real key="value" value="1"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<connections>
<outlet property="dataSource" destination="sSL-wr-E9v" id="weE-ef-YRt"/>
<outlet property="delegate" destination="sSL-wr-E9v" id="hva-cg-vBg"/>
<outlet property="dataSource" destination="CU7-Hg-6kG" id="BOZ-dL-WLG"/>
<outlet property="delegate" destination="CU7-Hg-6kG" id="NKU-4F-wIF"/>
</connections>
</collectionView>
<navigationItem key="navigationItem" id="qS4-kF-4vO"/>
<navigationItem key="navigationItem" title="Horizontal Layout" id="AaD-SQ-gYu"/>
</collectionViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="bMF-CJ-xJ6" userLabel="First Responder" sceneMemberID="firstResponder"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="Dsp-JP-Q6i" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-68" y="36.945812807881772"/>
<point key="canvasLocation" x="22" y="-599"/>
</scene>
<!--Vertical Layout-->
<scene sceneID="ccn-9j-1sQ">
<objects>
<collectionViewController id="9P2-Ud-D2M" customClass="BaseCollectionViewController" customModule="InfiniteLayout_Example" customModuleProvider="target" sceneMemberID="viewController">
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="prototypes" id="iW9-Tg-dTG" customClass="InfiniteCollectionView" customModule="InfiniteLayout">
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="1000" id="t85-Nu-Mt1">
<size key="itemSize" width="150" height="100"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="10"/>
</collectionViewFlowLayout>
<cells>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="cell" id="OtA-Vt-ejC" customClass="Cell" customModule="InfiniteLayout_Example" customModuleProvider="target">
<rect key="frame" x="85" y="0.0" width="150" height="100"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
<rect key="frame" x="0.0" y="0.0" width="150" height="100"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fuL-Uj-Mda" customClass="CellView" customModule="InfiniteLayout_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="150" height="100"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
</subviews>
</view>
<constraints>
<constraint firstItem="fuL-Uj-Mda" firstAttribute="leading" secondItem="OtA-Vt-ejC" secondAttribute="leading" id="KLH-6Z-vhB"/>
<constraint firstAttribute="trailing" secondItem="fuL-Uj-Mda" secondAttribute="trailing" id="bzB-oG-udJ"/>
<constraint firstAttribute="bottom" secondItem="fuL-Uj-Mda" secondAttribute="bottom" id="fgE-nQ-BGU"/>
<constraint firstItem="fuL-Uj-Mda" firstAttribute="top" secondItem="OtA-Vt-ejC" secondAttribute="top" id="t4I-qE-DtN"/>
</constraints>
<connections>
<outlet property="cellView" destination="fuL-Uj-Mda" id="AN4-RB-ul0"/>
</connections>
</collectionViewCell>
</cells>
<connections>
<outlet property="dataSource" destination="9P2-Ud-D2M" id="juO-P6-XzS"/>
<outlet property="delegate" destination="9P2-Ud-D2M" id="ns0-fe-DSq"/>
</connections>
</collectionView>
<navigationItem key="navigationItem" title="Vertical Layout" id="2E2-oh-ELb"/>
</collectionViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Lvb-qy-gZV" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="22" y="61"/>
</scene>
</scenes>
</document>
@@ -0,0 +1,25 @@
//
// BaseCollectionViewController.swift
// InfiniteLayout_Example
//
// Created by Arnaud Dorgans on 29/12/2017.
// Copyright © 2017 CocoaPods. All rights reserved.
//
import UIKit
import InfiniteLayout
class BaseCollectionViewController: InfiniteCollectionViewController {
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? Cell else {
fatalError()
}
cell.update(index: self.infiniteCollectionView!.indexPath(from: indexPath).row)
return cell
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 20
}
}
+32 -2
View File
@@ -17,12 +17,30 @@ class Cell: UICollectionViewCell {
}
}
enum CellStyle {
case circular
case `default`
static let all = [circular, `default`]
}
@IBDesignable class CellView: UIView {
let titleLabel = UILabel()
let colors = [#colorLiteral(red: 0.5254901961, green: 0.6901960784, blue: 0.9137254902, alpha: 1), #colorLiteral(red: 0.5254901961, green: 0.6196078431, blue: 0.9137254902, alpha: 1), #colorLiteral(red: 0.6078431373, green: 0.5254901961, blue: 0.9137254902, alpha: 1), #colorLiteral(red: 0.9137254902, green: 0.5254901961, blue: 0.8392156863, alpha: 1), #colorLiteral(red: 0.9137254902, green: 0.5254901961, blue: 0.6, alpha: 1), #colorLiteral(red: 0.9137254902, green: 0.6784313725, blue: 0.5254901961, alpha: 1), #colorLiteral(red: 0.9137254902, green: 0.9058823529, blue: 0.5254901961, alpha: 1), #colorLiteral(red: 0.5254901961, green: 0.9137254902, blue: 0.5921568627, alpha: 1), #colorLiteral(red: 0.5254901961, green: 0.8, blue: 0.9137254902, alpha: 1)]
@IBInspectable var styleIndex: Int {
get { return CellStyle.all.index(of: style)! }
set { style = CellStyle.all[newValue % CellStyle.all.count] }
}
var style: CellStyle = .default {
didSet {
updateStyle()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
sharedInit()
@@ -45,14 +63,26 @@ class Cell: UICollectionViewCell {
self.addSubview(titleLabel)
titleLabel.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
titleLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
self.layer.cornerRadius = 8
}
func update(index: Int) {
self.titleLabel.text = String(index + 1)
self.backgroundColor = colors[index % colors.count]
}
func updateStyle() {
switch style {
case .default:
self.layer.cornerRadius = 8
case .circular:
self.layer.cornerRadius = self.frame.height / 2
}
}
override func layoutSubviews() {
super.layoutSubviews()
updateStyle()
}
override func prepareForInterfaceBuilder() {
self.update(index: 0)
+33
View File
@@ -0,0 +1,33 @@
//
// CustomLayout.swift
// InfiniteLayout_Example
//
// Created by Arnaud Dorgans on 28/12/2017.
// Copyright © 2017 CocoaPods. All rights reserved.
//
import UIKit
import InfiniteLayout
class CustomLayout: InfiniteLayout {
let minimumScale: CGFloat = 0.75
let rangeRatio: CGFloat = 1
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let attributes = super.layoutAttributesForElements(in: rect).flatMap {
self.copyLayoutAttributes(from: $0)
}
guard let visibleRect = self.visibleCollectionViewRect() else {
return attributes
}
let centeredOffset = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
for attributes in attributes ?? [] {
let diff = self.scrollDirection == .horizontal ? centeredOffset.x - attributes.center.x : centeredOffset.y - attributes.center.y
let scale = max(min(diff / (min(visibleRect.width, visibleRect.height) * rangeRatio), 1), -1)
attributes.transform = attributes.transform.translatedBy(x: abs(scale * (visibleRect.width / 2)), y: 0)
attributes.transform = attributes.transform.rotated(by: scale * (CGFloat.pi / 2))
}
return attributes
}
}
@@ -0,0 +1,51 @@
//
// CustomViewController.swift
// InfiniteLayout
//
// Created by Arnoymous on 12/20/2017.
// Copyright (c) 2017 Arnoymous. All rights reserved.
//
import UIKit
import InfiniteLayout
class CustomViewController: UIViewController {
@IBOutlet weak var infiniteCollectionView: InfiniteCollectionView!
}
extension CustomViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 14
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 2
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! Cell
cell.update(index: self.infiniteCollectionView!.indexPath(from: indexPath).row)
return cell
}
}
extension CustomViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 100, height: 100)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return collectionView.frame.height
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
}
}
-1
View File
@@ -33,7 +33,6 @@
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
</array>
</dict>
</plist>
@@ -0,0 +1,41 @@
//
// PickerController.swift
// InfiniteLayout_Example
//
// Created by Arnaud Dorgans on 03/01/2018.
// Copyright © 2018 CocoaPods. All rights reserved.
//
import UIKit
import InfiniteLayout
class PickerController: UIViewController {
@IBOutlet weak var selectedView: CellView!
@IBOutlet weak var infiniteCollectionView: InfiniteCollectionView!
}
extension PickerController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 20
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? Cell else {
fatalError()
}
cell.update(index: self.infiniteCollectionView.indexPath(from: indexPath).row)
return cell
}
}
extension PickerController: InfiniteCollectionViewDelegate {
func infiniteCollectionView(_ infiniteCollectionView: InfiniteCollectionView, didChangeCenteredIndexPath centeredIndexPath: IndexPath?) {
guard let indexPath = centeredIndexPath else {
return
}
self.selectedView.update(index: self.infiniteCollectionView.indexPath(from: indexPath).row)
}
}
@@ -1,55 +0,0 @@
//
// ViewController.swift
// InfiniteLayout
//
// Created by Arnoymous on 12/20/2017.
// Copyright (c) 2017 Arnoymous. All rights reserved.
//
import UIKit
import InfiniteLayout
class ViewController: InfiniteCollectionViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
guard let collectionView = self.collectionView else {
return
}
let cells = collectionView.indexPathsForVisibleItems.sorted()
for i in 0..<cells.count {
guard let cell = collectionView.cellForItem(at: cells[i]) else {
return
}
cell.alpha = 0
UIView.animate(withDuration: 0.3, delay: TimeInterval(i) * 0.05, options: [], animations: {
cell.alpha = 1
}, completion: nil)
}
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 14
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! Cell
cell.update(index: self.infiniteCollectionView!.indexPath(from: indexPath).row)
return cell
}
}
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let height: CGFloat = 100
let width: CGFloat = height * 2
return CGSize(width: width, height: height)
}
}
+5 -2
View File
@@ -1,5 +1,7 @@
PODS:
- InfiniteLayout (0.1.0)
- CocoaProxy (0.1.1)
- InfiniteLayout (0.1.3):
- CocoaProxy (~> 0.1)
DEPENDENCIES:
- InfiniteLayout (from `../`)
@@ -9,7 +11,8 @@ EXTERNAL SOURCES:
:path: ../
SPEC CHECKSUMS:
InfiniteLayout: 82a21b8255623e2d72174f3082bef9e576140621
CocoaProxy: 35ab81e24325b33834cffe45a3d1fd48ca67ef3a
InfiniteLayout: 0ab39bf2a4d9ce5c473ebccfc0d3b7278de18ac9
PODFILE CHECKSUM: 3a658536624f41ec07c5a7a2c55407b9b8f48528
+2 -2
View File
@@ -8,7 +8,7 @@
Pod::Spec.new do |s|
s.name = 'InfiniteLayout'
s.version = '0.1.3'
s.version = '0.1.6'
s.summary = 'Horizontal and Vertical infinite scrolling feature for UICollectionView'
# This description is used to generate tags and improve search results.
@@ -40,5 +40,5 @@ Horizontal and Vertical infinite scrolling feature for UICollectionView with Pag
# s.public_header_files = 'Pod/Classes/**/*.h'
# s.frameworks = 'UIKit', 'MapKit'
# s.dependency 'AFNetworking', '~> 2.3'
s.dependency 'CocoaProxy', '~> 0.1'
end
@@ -7,15 +7,22 @@
import UIKit
@objc public protocol InfiniteCollectionViewDelegate {
@objc optional func infiniteCollectionView(_ infiniteCollectionView: InfiniteCollectionView, didChangeCenteredIndexPath centeredIndexPath: IndexPath?)
}
open class InfiniteCollectionView: UICollectionView {
lazy var delegateProxy = InfiniteCollectionViewDelegateProxy(self, exceptions: ["scrollViewDidScroll:",
"scrollViewWillEndDragging:withVelocity:targetContentOffset:"])
lazy var dataSourceProxy = InfiniteCollectionViewDataSourceProxy(self, exceptions: ["numberOfSectionsInCollectionView:",
"collectionView:numberOfItemsInSection:"])
lazy var delegateProxy = InfiniteCollectionViewDelegateProxy(collectionView: self)
lazy var dataSourceProxy = InfiniteCollectionViewDataSourceProxy(collectionView: self)
@IBInspectable var isItemPagingEnabled: Bool = false
@IBInspectable var velocityMultiplier: CGFloat = 500 {
@IBOutlet open var infiniteDelegate: InfiniteCollectionViewDelegate?
open var centeredIndexPath: IndexPath?
@IBInspectable open var isItemPagingEnabled: Bool = false
@IBInspectable open var velocityMultiplier: CGFloat = 500 {
didSet {
self.infiniteLayout.velocityMultiplier = velocityMultiplier
}
@@ -56,24 +63,24 @@ open class InfiniteCollectionView: UICollectionView {
return self.collectionViewLayout as? InfiniteLayout
}
private static func infiniteLayout(layout: UICollectionViewLayout) -> InfiniteLayout {
guard let infiniteLayout = layout as? InfiniteLayout else {
return InfiniteLayout(layout: layout)
}
return infiniteLayout
}
public override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
super.init(frame: frame, collectionViewLayout: InfiniteLayout(layout: layout))
sharedInit()
super.init(frame: frame, collectionViewLayout: InfiniteCollectionView.infiniteLayout(layout: layout))
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
let layout = self.collectionViewLayout
if !(layout is InfiniteLayout) {
self.collectionViewLayout = InfiniteLayout(layout: layout)
let infiniteLayout = InfiniteCollectionView.infiniteLayout(layout: self.collectionViewLayout)
if self.collectionViewLayout != infiniteLayout {
self.collectionViewLayout = infiniteLayout
}
sharedInit()
}
private func sharedInit() {
delegateProxy.collectionView = self
dataSourceProxy.collectionView = self
}
open override func layoutSubviews() {
@@ -94,6 +101,12 @@ extension InfiniteCollectionView: UICollectionViewDelegate {
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
delegateProxy.delegate?.scrollViewDidScroll?(scrollView)
self.loopCollectionViewIfNeeded()
let preferredVisibleIndexPath = infiniteLayout.preferredVisibleLayoutAttributes()?.indexPath
if self.centeredIndexPath != preferredVisibleIndexPath {
self.centeredIndexPath = preferredVisibleIndexPath
self.infiniteDelegate?.infiniteCollectionView?(self, didChangeCenteredIndexPath: preferredVisibleIndexPath)
}
}
// MARK: Paging
@@ -1,19 +0,0 @@
//
// InfiniteCollectionViewProxy.h
// InfiniteLayout
//
// Created by Arnaud Dorgans on 21/12/2017.
//
#import <Foundation/Foundation.h>
@interface _InfiniteCollectionViewProxy<T: id<NSObject>> : NSProxy <UICollectionViewDelegate, UICollectionViewDataSource>
-(nonnull instancetype)init:(nullable T)collectionView exceptions:(nonnull NSArray<NSString*>*)exceptions;
@property (nonatomic, weak, nullable) T collectionView;
@property (nonatomic, weak, nullable) T delegate;
@property (nonatomic, nonnull, retain) NSArray* exceptions;
@end
@@ -1,52 +0,0 @@
//
// InfiniteCollectionViewProxy.m
// InfiniteLayout
//
// Created by Arnaud Dorgans on 21/12/2017.
//
#import "InfiniteCollectionViewProxy.h"
@implementation _InfiniteCollectionViewProxy
-(instancetype)init:(nullable id)collectionView exceptions:(nonnull NSArray<NSString*>*)exceptions {
self.collectionView = collectionView;
self.exceptions = exceptions;
return self;
}
- (BOOL)respondsToSelector:(SEL)aSelector
{
return ([self.collectionView respondsToSelector:aSelector] || [self.delegate respondsToSelector:aSelector]);
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
NSObject *delegateForResonse = [self.delegate respondsToSelector:aSelector] ? self.delegate : self.collectionView;
NSMethodSignature *signature = [delegateForResonse respondsToSelector:aSelector] ? [delegateForResonse methodSignatureForSelector:aSelector] : nil;
return signature;
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
NSString *selectorName = NSStringFromSelector(invocation.selector);
NSArray<id<NSObject>> *delegates = @[self.delegate, self.collectionView];
if ([self.exceptions containsObject:selectorName]) {
delegates = [[delegates reverseObjectEnumerator] allObjects];
}
for (int i = 0; i < delegates.count; i++) {
if ([delegates[i] respondsToSelector:invocation.selector]) {
[self invokeInvocation:invocation onDelegate:delegates[i]];
return;
}
}
}
- (void)invokeInvocation:(NSInvocation *)invocation onDelegate:(id<NSObject>)delegate
{
if ([delegate respondsToSelector:invocation.selector]) {
[invocation invokeWithTarget:delegate];
}
}
@end
@@ -0,0 +1,85 @@
//
// Proxy.swift
// InfiniteLayout
//
// Created by Arnaud Dorgans on 20/12/2017.
//
import UIKit
import CocoaProxy
class InfiniteCollectionViewProxy<T: NSObjectProtocol>: CocoaProxy {
var collectionView: InfiniteCollectionView! {
get { return self.proxies.first as? InfiniteCollectionView }
set {
if !self.proxies.isEmpty {
self.proxies.removeFirst()
}
self.proxies.insert(newValue, at: 0)
}
}
var delegate: T? {
get {
guard self.proxies.count > 1 else {
return nil
}
return self.proxies.last as? T
} set {
while self.proxies.count > 1 {
self.proxies.removeLast()
}
guard let delegate = newValue else {
return
}
self.proxies.append(delegate)
}
}
override func proxies(for aSelector: Selector) -> [NSObjectProtocol] {
return super.proxies(for: aSelector).reversed()
}
init(collectionView: InfiniteCollectionView) {
super.init(proxies: [])
self.collectionView = collectionView
}
}
class InfiniteCollectionViewDelegateProxy: InfiniteCollectionViewProxy<UICollectionViewDelegate>, UICollectionViewDelegate {
override func proxies(for aSelector: Selector) -> [NSObjectProtocol] {
return super.proxies(for: aSelector)
.first { proxy in
guard !(aSelector == #selector(UIScrollViewDelegate.scrollViewDidScroll(_:)) ||
aSelector == #selector(UIScrollViewDelegate.scrollViewWillEndDragging(_:withVelocity:targetContentOffset:))) else {
return proxy is InfiniteCollectionView
}
return true
}.flatMap { [$0] } ?? []
}
}
class InfiniteCollectionViewDataSourceProxy: InfiniteCollectionViewProxy<UICollectionViewDataSource>, UICollectionViewDataSource {
override func proxies(for aSelector: Selector) -> [NSObjectProtocol] {
return super.proxies(for: aSelector)
.first { proxy in
guard !(aSelector == #selector(UICollectionViewDataSource.numberOfSections(in:)) ||
aSelector == #selector(UICollectionViewDataSource.collectionView(_:numberOfItemsInSection:))) else {
return proxy is InfiniteCollectionView
}
return true
}.flatMap { [$0] } ?? []
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.collectionView.collectionView(collectionView, numberOfItemsInSection: section)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
return self.delegate?.collectionView(collectionView, cellForItemAt: indexPath) ??
self.collectionView.collectionView(collectionView, cellForItemAt: indexPath)
}
}
+27 -11
View File
@@ -43,8 +43,13 @@ open class InfiniteLayout: UICollectionViewFlowLayout {
override open func prepare() {
let collectionViewContentSize = super.collectionViewContentSize
self.contentSize = CGSize(width: collectionViewContentSize.width, height: collectionViewContentSize.height)
self.isEnabled = (scrollDirection == .horizontal ? self.contentSize.width : self.contentSize.height) >=
InfiniteLayout.minimumContentSize.width
self.isEnabled = {
guard let collectionView = self.collectionView, collectionView.bounds != .zero else {
return false
}
return (scrollDirection == .horizontal ? self.contentSize.width : self.contentSize.height) >=
InfiniteLayout.minimumContentSize.width
}()
super.prepare()
}
@@ -119,7 +124,7 @@ open class InfiniteLayout: UICollectionViewFlowLayout {
}
private func layoutAttributes(from layoutAttributes: UICollectionViewLayoutAttributes, page: CGPoint) -> UICollectionViewLayoutAttributes! {
guard let attributes = layoutAttributes.copy() as? UICollectionViewLayoutAttributes else {
guard let attributes = self.copyLayoutAttributes(layoutAttributes) else {
return nil
}
attributes.frame = rect(from: attributes.frame, page: page)
@@ -145,7 +150,7 @@ open class InfiniteLayout: UICollectionViewFlowLayout {
}
// MARK: Paging
func collectionViewRect() -> CGRect? {
public func collectionViewRect() -> CGRect? {
guard let collectionView = self.collectionView else {
return nil
}
@@ -162,7 +167,7 @@ open class InfiniteLayout: UICollectionViewFlowLayout {
return visibleRect
}
func visibleCollectionViewRect() -> CGRect? {
public func visibleCollectionViewRect() -> CGRect? {
guard let collectionView = self.collectionView,
var collectionViewRect = self.collectionViewRect() else {
return nil
@@ -178,10 +183,10 @@ open class InfiniteLayout: UICollectionViewFlowLayout {
}
return (self.layoutAttributesForElements(in: CGRect(origin: offset ?? collectionView.contentOffset, size: collectionView.frame.size)) ?? [])
.sorted(by: { lhs, rhs in
guard let lhs = self.centerredContentOffset(forRect: lhs.frame) else {
guard let lhs = self.centeredContentOffset(forRect: lhs.frame) else {
return false
}
guard let rhs = self.centerredContentOffset(forRect: rhs.frame) else {
guard let rhs = self.centeredContentOffset(forRect: rhs.frame) else {
return true
}
let value: (CGPoint)->CGFloat = {
@@ -202,14 +207,14 @@ open class InfiniteLayout: UICollectionViewFlowLayout {
let targetDirection = direction(targetOffset ?? currentOffset)
return self.visibleLayoutAttributes(at: offset)
.first { attributes in
guard let offset = self.centerredContentOffset(forRect: attributes.frame) else {
guard let offset = self.centeredContentOffset(forRect: attributes.frame) else {
return false
}
return direction(offset) == targetDirection || velocity == 0
}
}
func centerredContentOffset(forRect rect: CGRect) -> CGPoint? {
func centeredContentOffset(forRect rect: CGRect) -> CGPoint? {
guard let collectionView = self.collectionView,
let collectionRect = self.collectionViewRect() else {
return nil
@@ -226,7 +231,7 @@ open class InfiniteLayout: UICollectionViewFlowLayout {
y: self.scrollDirection == .vertical ? collectionView.contentOffset.y + velocity.y * velocityMultiplier : targetContentOffset.pointee.y)
guard let preferredAttributes = self.preferredVisibleLayoutAttributes(at: newTarget, velocity: velocity, targetOffset: targetContentOffset.pointee),
let offset = self.centerredContentOffset(forRect: preferredAttributes.frame) else {
let offset = self.centeredContentOffset(forRect: preferredAttributes.frame) else {
return
}
targetContentOffset.pointee = offset
@@ -237,7 +242,7 @@ open class InfiniteLayout: UICollectionViewFlowLayout {
return
}
guard let preferredAttributes = self.preferredVisibleLayoutAttributes(),
let offset = self.centerredContentOffset(forRect: preferredAttributes.frame),
let offset = self.centeredContentOffset(forRect: preferredAttributes.frame),
collectionView.contentOffset != offset else {
return
}
@@ -245,4 +250,15 @@ open class InfiniteLayout: UICollectionViewFlowLayout {
collectionView.contentOffset = offset
}
}
// MARK: Copy
public func copyLayoutAttributes(_ attributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes? {
return attributes.copy() as? UICollectionViewLayoutAttributes
}
public func copyLayoutAttributes(from array: [UICollectionViewLayoutAttributes]) -> [UICollectionViewLayoutAttributes] {
return array.map { self.copyLayoutAttributes($0) }
.filter { $0 != nil }
.map { $0! }
}
}
-16
View File
@@ -1,16 +0,0 @@
//
// Proxy.swift
// InfiniteLayout
//
// Created by Arnaud Dorgans on 20/12/2017.
//
import UIKit
class InfiniteCollectionViewDelegateProxy: _InfiniteCollectionViewProxy<UICollectionViewDelegate> {
}
class InfiniteCollectionViewDataSourceProxy: _InfiniteCollectionViewProxy<UICollectionViewDataSource> {
}
+8
View File
@@ -59,6 +59,14 @@ InfiniteCollectionView provide a paging functionality, you can enable it by sett
When the **isItemPagingEnabled** flag is enabled you can adjust the deceleration rate by setting the **velocityMultiplier**, the more the value is high, the more the deceleration is long
### Picker
InfiniteCollectionView provide an **infiniteDelegate** protocol used to get the centered IndexPath, usefull if you want to use an InfiniteCollectionView like a Picker.
```swift
func infiniteCollectionView(_ infiniteCollectionView: InfiniteCollectionView, didChangeCenteredIndexPath centeredIndexPath: IndexPath?)
```
## Author
Arnoymous, ineox@me.com