Skip to content

Commit

Permalink
Add support fox custom z index
Browse files Browse the repository at this point in the history
  • Loading branch information
Yossi Avramov committed Jun 11, 2019
1 parent f1e8410 commit d542a95
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 10 deletions.
6 changes: 4 additions & 2 deletions MagazineLayout/LayoutCore/ItemModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ struct ItemModel {

// MARK: Lifecycle

init(sizeMode: MagazineLayoutItemSizeMode, height: CGFloat) {
init(sizeMode: MagazineLayoutItemSizeMode, height: CGFloat, zIndex: Int?) {
id = NSUUID().uuidString
self.sizeMode = sizeMode
originInSection = .zero
size = CGSize(width: 0, height: height)
self.zIndex = zIndex
}

// MARK: Internal
Expand All @@ -36,5 +37,6 @@ struct ItemModel {
var originInSection: CGPoint
var size: CGSize
var preferredHeight: CGFloat?

var zIndex: Int?

}
3 changes: 2 additions & 1 deletion MagazineLayout/LayoutCore/ModelState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -547,9 +547,10 @@ final class ModelState {
invalidateSectionMaxYsCacheForSectionIndices(startingAt: sectionIndex)
}

func updateItemSizeMode(to sizeMode: MagazineLayoutItemSizeMode, forItemAt indexPath: IndexPath) {
func updateItemSizeMode(to sizeMode: MagazineLayoutItemSizeMode, zIndex: Int?, forItemAt indexPath: IndexPath) {
currentSectionModels[indexPath.section].updateItemSizeMode(
to: sizeMode,
zIndex: zIndex,
atIndex: indexPath.item)

invalidateSectionMaxYsCacheForSectionIndices(startingAt: indexPath.section)
Expand Down
5 changes: 3 additions & 2 deletions MagazineLayout/LayoutCore/SectionModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -165,14 +165,15 @@ struct SectionModel {
updateIndexOfFirstInvalidatedRowIfNecessary(toProposedIndex: 0)
}

mutating func updateItemSizeMode(to sizeMode: MagazineLayoutItemSizeMode, atIndex index: Int) {
mutating func updateItemSizeMode(to sizeMode: MagazineLayoutItemSizeMode, zIndex: Int?, atIndex index: Int) {
// Accessing this array using an unsafe, untyped (raw) pointer avoids expensive copy-on-writes
// and Swift retain / release calls.
let itemModelsPointer = UnsafeMutableRawPointer(mutating: &itemModels)
let directlyMutableItemModels = itemModelsPointer.assumingMemoryBound(to: ItemModel.self)

directlyMutableItemModels[index].sizeMode = sizeMode

directlyMutableItemModels[index].zIndex = zIndex

if case let .static(staticHeight) = sizeMode.heightMode {
directlyMutableItemModels[index].size.height = staticHeight
}
Expand Down
28 changes: 23 additions & 5 deletions MagazineLayout/Public/MagazineLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public final class MagazineLayout: UICollectionViewLayout {
let numberOfItems = modelState.numberOfItems(inSectionAtIndex: sectionIndex, .afterUpdates)
for itemIndex in 0..<numberOfItems {
let indexPath = IndexPath(item: itemIndex, section: sectionIndex)
modelState.updateItemSizeMode(to: sizeModeForItem(at: indexPath), forItemAt: indexPath)
modelState.updateItemSizeMode(to: sizeModeForItem(at: indexPath), zIndex: zIndexForItem(at: indexPath), forItemAt: indexPath)
}
}
}
Expand Down Expand Up @@ -163,7 +163,7 @@ public final class MagazineLayout: UICollectionViewLayout {
}

newHeaderLayoutAttributes[headerLocation]?.shouldVerticallySelfSize = heightMode == .dynamic
newHeaderLayoutAttributes[headerLocation]?.zIndex = numberOfItems + 1
newHeaderLayoutAttributes[headerLocation]?.zIndex = numberOfItems + Default.HeaderZIndexByAddingToNumberOfItems
}

// Create footer layout attributes if necessary
Expand All @@ -179,7 +179,7 @@ public final class MagazineLayout: UICollectionViewLayout {
}

newFooterLayoutAttributes[footerLocation]?.shouldVerticallySelfSize = heightMode == .dynamic
newFooterLayoutAttributes[footerLocation]?.zIndex = numberOfItems + 1
newFooterLayoutAttributes[footerLocation]?.zIndex = numberOfItems + Default.FooterZIndexByAddingToNumberOfItems
}

// Create background layout attributes if necessary
Expand Down Expand Up @@ -216,7 +216,12 @@ public final class MagazineLayout: UICollectionViewLayout {
newItemLayoutAttributes[itemLocation]?.shouldVerticallySelfSize = true
}

newItemLayoutAttributes[itemLocation]?.zIndex = numberOfItems - itemIndex

if let zIndex = zIndexForItem(at: itemLocation.indexPath) {
newItemLayoutAttributes[itemLocation]?.zIndex = zIndex
} else {
newItemLayoutAttributes[itemLocation]?.zIndex = numberOfItems - itemIndex
}
}
}

Expand Down Expand Up @@ -778,6 +783,17 @@ public final class MagazineLayout: UICollectionViewLayout {
sizeModeForItemAt: indexPath)
}

private func zIndexForItem(at indexPath: IndexPath) -> Int? {
guard let delegateMagazineLayout = delegateMagazineLayout else {
return nil
}

return delegateMagazineLayout.collectionView(
currentCollectionView,
layout: self,
zIndexForItemAt: indexPath)
}

private func initialItemHeight(from itemSizeMode: MagazineLayoutItemSizeMode) -> CGFloat {
switch itemSizeMode.heightMode {
case let .static(staticHeight):
Expand Down Expand Up @@ -868,9 +884,11 @@ public final class MagazineLayout: UICollectionViewLayout {

private func itemModelForItem(at indexPath: IndexPath) -> ItemModel {
let itemSizeMode = sizeModeForItem(at: indexPath)
let zIndex = zIndexForItem(at: indexPath)
return ItemModel(
sizeMode: itemSizeMode,
height: initialItemHeight(from: itemSizeMode))
height: initialItemHeight(from: itemSizeMode),
zIndex: zIndex)
}

private func headerModelForHeader(
Expand Down
2 changes: 2 additions & 0 deletions MagazineLayout/Public/Types/MagazineLayout+Default.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ extension MagazineLayout {
public static let SectionInsets: UIEdgeInsets = .zero
public static let ItemInsets: UIEdgeInsets = .zero

public static let HeaderZIndexByAddingToNumberOfItems: Int = 1
public static let FooterZIndexByAddingToNumberOfItems: Int = 1
}

}
24 changes: 24 additions & 0 deletions MagazineLayout/Public/UICollectionViewDelegateMagazineLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ public protocol UICollectionViewDelegateMagazineLayout: UICollectionViewDelegate
sizeModeForItemAt indexPath: IndexPath)
-> MagazineLayoutItemSizeMode

/// Asks the delegate for the zIndex of the specified item.
///
/// - Parameters:
/// - collectionView: The collection view using the layout.
/// - collectionViewLayout: The layout requesting the information.
/// - indexPath: The index path of the item.
///
/// - Returns: The zIndex of the specified item. Returns 0 for default zIndex
func collectionView(
_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
zIndexForItemAt indexPath: IndexPath)
-> Int?

/// Asks the delegate for the visibility mode of the header in the specified section.
///
/// - Parameters:
Expand Down Expand Up @@ -136,3 +150,13 @@ public protocol UICollectionViewDelegateMagazineLayout: UICollectionViewDelegate
-> UIEdgeInsets

}

public extension UICollectionViewDelegateMagazineLayout {
func collectionView(
_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
zIndexForItemAt indexPath: IndexPath)
-> Int? {
return nil
}
}

0 comments on commit d542a95

Please sign in to comment.