Skip to content

Commit cb0bec1

Browse files
committed
Fixed clipping issue and paging on edges issue
1 parent d6e8f2f commit cb0bec1

File tree

5 files changed

+118
-8
lines changed

5 files changed

+118
-8
lines changed

Example/MSPeekCollectionViewDelegateImplementation.xcodeproj/project.pbxproj

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; };
1414
607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; };
1515
607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; };
16+
698929E023A78BD000396CC7 /* MSPeekingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 698929DF23A78BD000396CC7 /* MSPeekingTests.swift */; };
1617
6CC61A01D070E53B5C9713D3 /* Pods_MSPeekCollectionViewDelegateImplementation_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D63706738AAABD8B65F2802 /* Pods_MSPeekCollectionViewDelegateImplementation_Example.framework */; };
1718
/* End PBXBuildFile section */
1819

@@ -38,6 +39,7 @@
3839
607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
3940
607FACE51AFB9204008FA782 /* MSPeekCollectionViewDelegateImplementation_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MSPeekCollectionViewDelegateImplementation_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
4041
607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
42+
698929DF23A78BD000396CC7 /* MSPeekingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSPeekingTests.swift; sourceTree = "<group>"; };
4143
6D62A78B4ED727736705D900 /* Pods-MSPeekCollectionViewDelegateImplementation_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MSPeekCollectionViewDelegateImplementation_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-MSPeekCollectionViewDelegateImplementation_Example/Pods-MSPeekCollectionViewDelegateImplementation_Example.release.xcconfig"; sourceTree = "<group>"; };
4244
7C9735FF72CB49CDCEB9B535 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
4345
A2049B1E9B6ED415F87F1C5A /* MSPeekCollectionViewDelegateImplementation.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = MSPeekCollectionViewDelegateImplementation.podspec; path = ../MSPeekCollectionViewDelegateImplementation.podspec; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
@@ -134,6 +136,7 @@
134136
isa = PBXGroup;
135137
children = (
136138
607FACE91AFB9204008FA782 /* Supporting Files */,
139+
698929DF23A78BD000396CC7 /* MSPeekingTests.swift */,
137140
);
138141
path = Tests;
139142
sourceTree = "<group>";
@@ -213,7 +216,7 @@
213216
};
214217
607FACE41AFB9204008FA782 = {
215218
CreatedOnToolsVersion = 6.3.1;
216-
LastSwiftMigration = 1030;
219+
LastSwiftMigration = 1120;
217220
TestTargetID = 607FACCF1AFB9204008FA782;
218221
};
219222
};
@@ -328,6 +331,7 @@
328331
isa = PBXSourcesBuildPhase;
329332
buildActionMask = 2147483647;
330333
files = (
334+
698929E023A78BD000396CC7 /* MSPeekingTests.swift in Sources */,
331335
);
332336
runOnlyForDeploymentPostprocessing = 0;
333337
};
@@ -501,13 +505,16 @@
501505
baseConfigurationReference = DF7372422D5B44BC145D286F /* Pods-MSPeekCollectionViewDelegateImplementation_Tests.debug.xcconfig */;
502506
buildSettings = {
503507
BUNDLE_LOADER = "$(TEST_HOST)";
508+
CLANG_ENABLE_MODULES = YES;
504509
GCC_PREPROCESSOR_DEFINITIONS = (
505510
"DEBUG=1",
506511
"$(inherited)",
507512
);
508513
INFOPLIST_FILE = Tests/Info.plist;
514+
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
509515
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
510516
PRODUCT_NAME = "$(TARGET_NAME)";
517+
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
511518
SWIFT_VERSION = 5.0;
512519
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MSPeekCollectionViewDelegateImplementation_Example.app/MSPeekCollectionViewDelegateImplementation_Example";
513520
};
@@ -518,7 +525,9 @@
518525
baseConfigurationReference = A72FA0AC4731049825DB8C50 /* Pods-MSPeekCollectionViewDelegateImplementation_Tests.release.xcconfig */;
519526
buildSettings = {
520527
BUNDLE_LOADER = "$(TEST_HOST)";
528+
CLANG_ENABLE_MODULES = YES;
521529
INFOPLIST_FILE = Tests/Info.plist;
530+
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
522531
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
523532
PRODUCT_NAME = "$(TARGET_NAME)";
524533
SWIFT_VERSION = 5.0;

Example/Tests/MSPeekingTests.swift

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//
2+
// MSPeekingTests.swift
3+
// MSPeekCollectionViewDelegateImplementation_Tests
4+
//
5+
// Created by Maher Santina on 12/16/19.
6+
// Copyright © 2019 CocoaPods. All rights reserved.
7+
//
8+
9+
import XCTest
10+
@testable import MSPeekCollectionViewDelegateImplementation
11+
@testable import MSPeekCollectionViewDelegateImplementation_Example
12+
13+
class MSPeekingTests: XCTestCase {
14+
15+
var sut: MSCollectionViewPeekingBehavior!
16+
var collectionView: UICollectionView!
17+
18+
override func setUp() {
19+
20+
}
21+
22+
func setupWith(cellSpacing: CGFloat = 20, cellPeekWidth: CGFloat = 20) {
23+
sut = MSCollectionViewPeekingBehavior(cellSpacing: cellSpacing, cellPeekWidth: cellPeekWidth)
24+
collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: 375, height: 200), collectionViewLayout: UICollectionViewFlowLayout())
25+
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
26+
collectionView.configureForPeekingBehavior(behavior: sut)
27+
collectionView.dataSource = self
28+
collectionView.delegate = self
29+
}
30+
31+
override func tearDown() {
32+
// Put teardown code here. This method is called after the invocation of each test method in the class.
33+
}
34+
35+
private func simulateHorizontalScroll(distance: CGFloat, velocity: CGFloat) -> UnsafeMutablePointer<CGPoint> {
36+
collectionView.delegate?.scrollViewWillBeginDragging?(collectionView)
37+
let simulatedTargetContentOffset = UnsafeMutablePointer<CGPoint>.allocate(capacity: 1)
38+
simulatedTargetContentOffset.pointee = CGPoint(x: distance, y: 0)
39+
collectionView.delegate?.scrollViewWillEndDragging?(collectionView, withVelocity: CGPoint(x: velocity, y: 0), targetContentOffset: simulatedTargetContentOffset)
40+
return simulatedTargetContentOffset
41+
}
42+
43+
func test_100PeekWidth_0CellSpacing() {
44+
setupWith(cellSpacing: 0, cellPeekWidth: 100)
45+
let target = simulateHorizontalScroll(distance: 10, velocity: 2)
46+
XCTAssertEqual(sut.layout.collectionViewContentSize.width, 900)
47+
}
48+
49+
func test_0PeekWidth_0CellSpacing() {
50+
setupWith(cellSpacing: 0, cellPeekWidth: 0)
51+
let target = simulateHorizontalScroll(distance: 10, velocity: 2)
52+
print(target.pointee)
53+
XCTAssertEqual(sut.layout.collectionViewContentSize.width, 1500)
54+
}
55+
56+
func test_0PeekWidth_100CellSpacing() {
57+
setupWith(cellSpacing: 100, cellPeekWidth: 0)
58+
let target = simulateHorizontalScroll(distance: 10, velocity: 2)
59+
print(target.pointee)
60+
XCTAssertEqual(sut.layout.collectionViewContentSize.width, 1500)
61+
}
62+
63+
}
64+
65+
extension MSPeekingTests: UICollectionViewDataSource {
66+
func numberOfSections(in collectionView: UICollectionView) -> Int {
67+
return 1
68+
}
69+
70+
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
71+
return 4
72+
}
73+
74+
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
75+
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
76+
let value = (180 + CGFloat(indexPath.row)*20) / 255
77+
cell.contentView.backgroundColor = UIColor(red: value, green: value, blue: value, alpha: 1)
78+
return cell
79+
}
80+
}
81+
82+
extension MSPeekingTests: UICollectionViewDelegate {
83+
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
84+
sut.scrollViewWillEndDragging(scrollView, withVelocity: velocity, targetContentOffset: targetContentOffset)
85+
}
86+
}

MSPeekCollectionViewDelegateImplementation/Classes/MSCollectionViewCellPeekingLayout.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ open class MSCollectionViewCellPeekingLayout: UICollectionViewLayout {
102102
switch axis {
103103
case .main:
104104
let length = itemLength(axis: .main)
105-
let offsets = spacingLength * 2 //One from the start and one at the end
105+
let offsets = spacingLength * 2 + peekingLength * 2 //One from the start and one at the end
106106
return (length * CGFloat(numberOfItems)) + (CGFloat(numberOfItems) * spacingLength) + offsets
107107
case .cross:
108108
return itemLength(axis: .cross)

MSPeekCollectionViewDelegateImplementation/Classes/MSCollectionViewPaging.swift

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public protocol MSCollectionViewPagingDataSource: AnyObject {
2727
func collectionViewPagingMaximumItemsToScroll(_ collectionViewPaging: MSCollectionViewPaging) -> Int?
2828

2929
/// Returns whether a specific index exists in the collection items or not
30-
func collectionViewPaging(_ collectionViewPaging: MSCollectionViewPaging, indexExists index: Int) -> Bool
30+
func collectionViewNumberOfItems(_ collectionViewPaging: MSCollectionViewPaging) -> Int
3131
}
3232

3333
// Default arguments
@@ -55,12 +55,25 @@ public class MSCollectionViewPaging: NSObject {
5555
return dataSource?.collectionViewPagingScrollThreshold(self) ?? 0
5656
}
5757

58+
var numberOfItems: Int {
59+
return dataSource?.collectionViewNumberOfItems(self) ?? 0
60+
}
61+
62+
func setIndex(_ index: Int) {
63+
currentContentOffset = dataSource?.collectionViewPaging(self, offsetForItemAtIndex: index) ?? 0
64+
}
65+
5866
func getNewTargetOffset(startingOffset: CGFloat, velocity: CGFloat, targetOffset: CGFloat) -> CGFloat {
5967

6068
// Get the current index and target index based on the offset
6169
let currentIndex = dataSource?.collectionViewPaging(self, indexForItemAtOffset: startingOffset) ?? 0
6270
let targetIndex = dataSource?.collectionViewPaging(self, indexForItemAtOffset: targetOffset) ?? 0
6371

72+
let imAtFistItemAndScrollingBack = currentIndex == 0 && velocity < 0
73+
let imAtLastItemAndScrollingForward = currentIndex == numberOfItems && velocity > 0
74+
75+
guard !imAtFistItemAndScrollingBack && !imAtLastItemAndScrollingForward else { return startingOffset }
76+
6477
let delta = targetIndex - currentIndex
6578

6679
var offset: Int
@@ -87,8 +100,9 @@ public class MSCollectionViewPaging: NSObject {
87100
// The final index is the current index ofsetted by the value and in the velocity direction
88101
var finalIndex = currentIndex + (offset * Sign(value: delta).multiplier)
89102

103+
let indexExists = finalIndex < numberOfItems
90104
// Move to index only if it exists. This will solve issues when there are multiple items in the same page
91-
if !(dataSource?.collectionViewPaging(self, indexExists: finalIndex) ?? false) {
105+
if !indexExists {
92106
finalIndex = currentIndex
93107
}
94108

MSPeekCollectionViewDelegateImplementation/Classes/MSCollectionViewPeekingBehavior.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public class MSCollectionViewPeekingBehavior {
6666
/// Scrolls to an item at a specific index with or without animation
6767
public func scrollToItem(at index: Int, animated: Bool) {
6868
layout.collectionView?.setContentOffset(layout.startingPointForItem(index: index), animated: animated)
69+
paging.setIndex(index)
6970
}
7071

7172
/// Required function to be called when the `scrollViewWillEndDragging` `UICollectionViewDelegate` function is called
@@ -89,6 +90,10 @@ extension MSCollectionViewPeekingBehavior: MSCollectionViewCellPeekingLayoutData
8990
}
9091

9192
extension MSCollectionViewPeekingBehavior: MSCollectionViewPagingDataSource {
93+
public func collectionViewNumberOfItems(_ collectionViewPaging: MSCollectionViewPaging) -> Int {
94+
return numberOfItems
95+
}
96+
9297
public func collectionViewPaging(_ collectionViewPaging: MSCollectionViewPaging, offsetForItemAtIndex index: Int) -> CGFloat {
9398
return layout.startingPointForItem(index: index).attribute(axis: .main, scrollDirection: scrollDirection)
9499
}
@@ -115,8 +120,4 @@ extension MSCollectionViewPeekingBehavior: MSCollectionViewPagingDataSource {
115120
public func collectionViewPagingMaximumItemsToScroll(_ collectionViewPaging: MSCollectionViewPaging) -> Int? {
116121
return maximumItemsToScroll
117122
}
118-
119-
public func collectionViewPaging(_ collectionViewPaging: MSCollectionViewPaging, indexExists index: Int) -> Bool {
120-
return index < numberOfItems
121-
}
122123
}

0 commit comments

Comments
 (0)