Skip to content
This repository has been archived by the owner on Dec 22, 2023. It is now read-only.

Commit

Permalink
Refactor layoutAttributesForElements to fix rare rendering glitches (#…
Browse files Browse the repository at this point in the history
…122)

* Improve layoutAttributesForElements

- Set default padding to 1 if `itemsPerRow` is not set
- Add additional padding to the visible rectangle to avoid rare rendering issues with larger collections

* Fix tests and one warning

* Bump version to 0.12.0
  • Loading branch information
zenangst authored Aug 5, 2019
1 parent c0a4d89 commit d2810ea
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 12 deletions.
2 changes: 1 addition & 1 deletion Blueprints.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "Blueprints"
s.summary = "A collection of flow layouts that is meant to make your life easier."
s.version = "0.11.5"
s.version = "0.12.0"
s.homepage = "https://github.com/zenangst/Blueprints"
s.license = 'MIT'
s.author = { "Christoffer Winterkvist" => "[email protected]" }
Expand Down
25 changes: 23 additions & 2 deletions Sources/Shared/Core/BlueprintLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -338,12 +338,33 @@
let closure: (LayoutAttributes) -> Bool = scrollDirection == .horizontal
? { rect.maxX >= $0.frame.minX }
: { rect.maxY >= $0.frame.minY }
var rect = rect
let offset: CGFloat

// Add offset to the visible rectangle to avoid rare rendering issues when using binary search.
// It simply makes the visible rectangle slightly larger to ensure that all items on screen
// get rendered correctly. It will use the item size to determine how much offset should be
// added as padding to the visible rectangle.
switch scrollDirection {
case .horizontal:
offset = itemSize.width
rect.origin.x -= offset
rect.size.width += offset * 2
case .vertical:
offset = itemSize.height
rect.origin.y -= offset
rect.size.height += offset * 2
@unknown default:
fatalError("Case not implemented in current implementation")
}

let padding = Int(itemsPerRow ?? 1)
var items = binarySearch.findElements(in: cachedItemAttributes,
padding: Int(itemsPerRow ?? 0),
padding: padding,
less: { closure($0) },
match: { $0.frame.intersects(rect) }) ?? []
let supplementary = binarySearch.findElements(in: cachedSupplementaryAttributes,
padding: Int(itemsPerRow ?? 0),
padding: padding,
less: { closure($0) },
match: { $0.frame.intersects(rect) }) ?? []
items.append(contentsOf: supplementary)
Expand Down
6 changes: 3 additions & 3 deletions Tests/iOS+tvOS/HorizontalBlueprintLayoutTests+iOS+tvOS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ class HorizontalBlueprintLayoutTests_iOS_tvOS: XCTestCase {
horizontalLayout.prepare()

let size: CGSize = .init(width: 50, height: 50)
XCTAssertEqual(horizontalLayout.layoutAttributesForElements(in: CGRect(origin: .init(x: 0, y: 0), size: size))?.count, 1)
XCTAssertEqual(horizontalLayout.layoutAttributesForElements(in: CGRect(origin: .init(x: 75, y: 0), size: size))?.count, 2)
XCTAssertEqual(horizontalLayout.layoutAttributesForElements(in: CGRect(origin: .init(x: 100, y: 0), size: size))?.count, 1)
XCTAssertEqual(horizontalLayout.layoutAttributesForElements(in: CGRect(origin: .init(x: 0, y: 0), size: size))?.count, 2)
XCTAssertEqual(horizontalLayout.layoutAttributesForElements(in: CGRect(origin: .init(x: 75, y: 0), size: size))?.count, 4)
XCTAssertEqual(horizontalLayout.layoutAttributesForElements(in: CGRect(origin: .init(x: 100, y: 0), size: size))?.count, 3)
XCTAssertEqual(horizontalLayout.layoutAttributesForElements(in: CGRect(origin: .init(x: 0, y: 0), size: .init(width: 500, height: 500)))?.count, 10)
}
}
4 changes: 2 additions & 2 deletions Tests/iOS+tvOS/VerticalBlueprintLayoutTests+iOS+tvOS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class VerticalBlueprintLayoutTests_iOS_tvOS: XCTestCase {
XCTAssertEqual(verticalLayout.layoutAttributesForElements(in: .zero)?.count, 1)

let size = CGSize(width: 50, height: 50)
XCTAssertEqual(verticalLayout.layoutAttributesForElements(in: CGRect(origin: .init(x: 0, y: 0), size: size))?.count, 1)
XCTAssertEqual(verticalLayout.layoutAttributesForElements(in: CGRect(origin: .init(x: 0, y: 25), size: size))?.count, 2)
XCTAssertEqual(verticalLayout.layoutAttributesForElements(in: CGRect(origin: .init(x: 0, y: 0), size: size))?.count, 2)
XCTAssertEqual(verticalLayout.layoutAttributesForElements(in: CGRect(origin: .init(x: 0, y: 25), size: size))?.count, 1)
XCTAssertEqual(verticalLayout.layoutAttributesForElements(in: CGRect(origin: .init(x: 0, y: 50), size: size))?.count, 1)
XCTAssertEqual(verticalLayout.layoutAttributesForElements(in: CGRect(origin: .init(x: 0, y: 0), size: CGSize(width: 500, height: 500)))?.count, 10)
}
Expand Down
4 changes: 2 additions & 2 deletions Tests/macOS/HorizontalBlueprintLayoutTests+macOS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ class HorizontalBlueprintLayoutTests_macOS: XCTestCase {
XCTAssertEqual(horizontalLayout.layoutAttributesForElements(in: .zero).count, 1)

collectionView.contentOffset = .init(x: 75, y: 0)
XCTAssertEqual(horizontalLayout.layoutAttributesForElements(in: collectionView.enclosingScrollView!.documentVisibleRect).count, 2)
XCTAssertEqual(horizontalLayout.layoutAttributesForElements(in: collectionView.enclosingScrollView!.documentVisibleRect).count, 4)

collectionView.contentOffset = .init(x: 100, y: 0)
XCTAssertEqual(horizontalLayout.layoutAttributesForElements(in: collectionView.enclosingScrollView!.documentVisibleRect).count, 1)
XCTAssertEqual(horizontalLayout.layoutAttributesForElements(in: collectionView.enclosingScrollView!.documentVisibleRect).count, 3)

collectionView.enclosingScrollView?.frame.size = CGSize(width: 500, height: 500)
collectionView.contentOffset = .init(x: 0, y: 0)
Expand Down
4 changes: 2 additions & 2 deletions Tests/macOS/VerticalBlueprintLayoutTests+macOS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ class VerticalBlueprintLayoutTests_macOS: XCTestCase {

collectionView.enclosingScrollView?.frame.size = .init(width: 50, height: 50)
collectionView.contentOffset = .init(x: 0, y: 0)
XCTAssertEqual(verticalLayout.layoutAttributesForElements(in: collectionView.enclosingScrollView!.documentVisibleRect).count, 1)
XCTAssertEqual(verticalLayout.layoutAttributesForElements(in: collectionView.enclosingScrollView!.documentVisibleRect).count, 2)

collectionView.contentOffset = .init(x: 0, y: 25)
XCTAssertEqual(verticalLayout.layoutAttributesForElements(in: collectionView.enclosingScrollView!.documentVisibleRect).count, 2)
XCTAssertEqual(verticalLayout.layoutAttributesForElements(in: collectionView.enclosingScrollView!.documentVisibleRect).count, 1)

collectionView.contentOffset = .init(x: 0, y: 50)
XCTAssertEqual(verticalLayout.layoutAttributesForElements(in: collectionView.enclosingScrollView!.documentVisibleRect).count, 1)
Expand Down

0 comments on commit d2810ea

Please sign in to comment.