Archived
Push from command line
This commit is contained in:
+1053
File diff suppressed because it is too large
Load Diff
Generated
+41
@@ -0,0 +1,41 @@
|
||||
// Created by bryankeller on 7/24/17.
|
||||
// Copyright © 2018 Airbnb, Inc.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import UIKit
|
||||
|
||||
/// Encapsulates the vertical fitting priority for an element laid out by `MagazineLayout`.
|
||||
///
|
||||
/// Used by `UICollectionViewCell` and `UICollectionReusableView` subclasses to determine which
|
||||
/// vertical fitting priority to pass into
|
||||
/// `systemLayoutSizeFitting(_:withHorizontalFittingPriority:verticalFittingPriority)` via
|
||||
/// `preferredLayoutAttributesFitting(_:)`.
|
||||
public final class MagazineLayoutCollectionViewLayoutAttributes: UICollectionViewLayoutAttributes {
|
||||
|
||||
/// `MagazineLayout` supports self-sizing and static-sizing in the vertical direction. The value
|
||||
/// of this property will change the layout priority used for sizing.
|
||||
public var shouldVerticallySelfSize = true
|
||||
|
||||
override public func copy(with zone: NSZone? = nil) -> Any {
|
||||
let copy = super.copy(with: zone) as! MagazineLayoutCollectionViewLayoutAttributes
|
||||
copy.shouldVerticallySelfSize = shouldVerticallySelfSize
|
||||
return copy
|
||||
}
|
||||
|
||||
override public func isEqual(_ object: Any?) -> Bool {
|
||||
return super.isEqual(object) &&
|
||||
shouldVerticallySelfSize == (object as? MagazineLayoutCollectionViewLayoutAttributes)?.shouldVerticallySelfSize
|
||||
}
|
||||
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// Created by bryankeller on 9/24/18.
|
||||
// Copyright © 2018 Airbnb, Inc.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import UIKit
|
||||
|
||||
/// `MagazineLayout`'s invalidation context type.
|
||||
///
|
||||
/// Used to indicate that collection view properties and/or delegate layout metrics changed.
|
||||
public final class MagazineLayoutInvalidationContext: UICollectionViewLayoutInvalidationContext {
|
||||
|
||||
/// Indicates whether to recompute the positions and sizes of elements based on the current
|
||||
/// collection view and delegate layout metrics.
|
||||
public var invalidateLayoutMetrics = true
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// Created by bryankeller on 10/18/18.
|
||||
// Copyright © 2018 Airbnb, Inc.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import UIKit
|
||||
|
||||
extension MagazineLayout {
|
||||
|
||||
/// Constants for layout sizing and spacing defaults.
|
||||
public enum Default {
|
||||
|
||||
public static let ItemSizeMode = MagazineLayoutItemSizeMode(
|
||||
widthMode: .fullWidth(respectsHorizontalInsets: true),
|
||||
heightMode: MagazineLayoutItemHeightMode.static(height: ItemHeight))
|
||||
public static let HeaderVisibilityMode = MagazineLayoutHeaderVisibilityMode.hidden
|
||||
public static let FooterVisibilityMode = MagazineLayoutFooterVisibilityMode.hidden
|
||||
public static let BackgroundVisibilityMode = MagazineLayoutBackgroundVisibilityMode.hidden
|
||||
|
||||
public static let ItemHeight: CGFloat = 150
|
||||
public static let HeaderHeight: CGFloat = 44
|
||||
public static let FooterHeight: CGFloat = 44
|
||||
public static let VerticalSpacing: CGFloat = 0
|
||||
public static let HorizontalSpacing: CGFloat = 0
|
||||
public static let SectionInsets: UIEdgeInsets = .zero
|
||||
public static let ItemInsets: UIEdgeInsets = .zero
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Generated
Executable
+27
@@ -0,0 +1,27 @@
|
||||
// Created by bryankeller on 10/18/18.
|
||||
// Copyright © 2018 Airbnb, Inc.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
extension MagazineLayout {
|
||||
|
||||
/// Constants for supported supplementary view element kinds.
|
||||
public enum SupplementaryViewKind {
|
||||
|
||||
public static let sectionHeader = "MagazineLayoutSupplementaryViewKindSectionHeader"
|
||||
public static let sectionFooter = "MagazineLayoutSupplementaryViewKindSectionFooter"
|
||||
public static let sectionBackground = "MagazineLayoutSupplementaryViewKindSectionBackground"
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Generated
+27
@@ -0,0 +1,27 @@
|
||||
// Created by bryankeller on 10/15/18.
|
||||
// Copyright © 2018 Airbnb, Inc.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Represents the visibility mode for a background.
|
||||
public enum MagazineLayoutBackgroundVisibilityMode {
|
||||
|
||||
/// This visiblity mode will cause the background to be displayed behind the items and headers in
|
||||
/// its respective section.
|
||||
case visible
|
||||
|
||||
/// This visibility mode will cause the background to not be visibile behind the items and headers
|
||||
/// in its respective section.
|
||||
case hidden
|
||||
|
||||
}
|
||||
Generated
Executable
+78
@@ -0,0 +1,78 @@
|
||||
// Created by Roman Laitarenko on 2/4/19.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import CoreGraphics
|
||||
|
||||
// MARK: - MagazineLayoutFooterVisibilityMode
|
||||
|
||||
/// Represents the visibility mode for a footer.
|
||||
public enum MagazineLayoutFooterVisibilityMode {
|
||||
|
||||
/// This visibility mode will cause the footer to be displayed using the specified height mode in
|
||||
/// its respective section. If `pinToVisibleBounds` is true, the footer will pin to the visible
|
||||
/// bounds of the collection view while its containing section is visible.
|
||||
case visible(heightMode: MagazineLayoutFooterHeightMode, pinToVisibleBounds: Bool)
|
||||
|
||||
/// This visibility mode will cause the footer to not be visibile in its respective section.
|
||||
case hidden
|
||||
|
||||
/// This visibility mode will cause the footer to be displayed using the specified height mode in
|
||||
/// its respective section.
|
||||
public static func visible(
|
||||
heightMode: MagazineLayoutFooterHeightMode)
|
||||
-> MagazineLayoutFooterVisibilityMode
|
||||
{
|
||||
return .visible(heightMode: heightMode, pinToVisibleBounds: false)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - MagazineLayoutFooterHeightMode
|
||||
|
||||
/// Represents the vertical sizing mode for a footer.
|
||||
public enum MagazineLayoutFooterHeightMode {
|
||||
|
||||
/// This height mode will force the footer to be displayed with a height equal to `height`.
|
||||
///
|
||||
/// To properly support multiline labels, dynamic type, and other technologies that could affect
|
||||
/// the height of your footers dynamically, consider using the `dynamic` height mode.
|
||||
case `static`(height: CGFloat)
|
||||
|
||||
/// This height mode will cause the footer to self-size in the vertical direction.
|
||||
///
|
||||
/// In practice, self-sizing in the vertical direction means that the footer will get its height
|
||||
/// from the Auto Layout engine. Use this height mode for footers whose height is not known
|
||||
/// upfront. For example, if you support multiline labels or dynamic type, your height is likely
|
||||
/// not known until the Auto Layout engine resolves the layout at runtime.
|
||||
case dynamic
|
||||
|
||||
}
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
extension MagazineLayoutFooterHeightMode: Equatable {
|
||||
|
||||
public static func == (
|
||||
lhs: MagazineLayoutFooterHeightMode,
|
||||
rhs: MagazineLayoutFooterHeightMode)
|
||||
-> Bool
|
||||
{
|
||||
switch (lhs, rhs) {
|
||||
case (.static(let l), .static(let r)): return l == r
|
||||
case (.dynamic, .dynamic): return true
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Generated
Executable
+79
@@ -0,0 +1,79 @@
|
||||
// Created by bryankeller on 10/15/18.
|
||||
// Copyright © 2018 Airbnb, Inc.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import CoreGraphics
|
||||
|
||||
// MARK: - MagazineLayoutHeaderVisibilityMode
|
||||
|
||||
/// Represents the visibility mode for a header.
|
||||
public enum MagazineLayoutHeaderVisibilityMode {
|
||||
|
||||
/// This visibility mode will cause the header to be displayed using the specified height mode in
|
||||
/// its respective section. If `pinToVisibleBounds` is true, the header will pin to the visible
|
||||
/// bounds of the collection view while its containing section is visible.
|
||||
case visible(heightMode: MagazineLayoutHeaderHeightMode, pinToVisibleBounds: Bool)
|
||||
|
||||
/// This visibility mode will cause the header to not be visibile in its respective section.
|
||||
case hidden
|
||||
|
||||
/// This visibility mode will cause the header to be displayed using the specified height mode in
|
||||
/// its respective section.
|
||||
public static func visible(
|
||||
heightMode: MagazineLayoutHeaderHeightMode)
|
||||
-> MagazineLayoutHeaderVisibilityMode
|
||||
{
|
||||
return .visible(heightMode: heightMode, pinToVisibleBounds: false)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - MagazineLayoutHeaderHeightMode
|
||||
|
||||
/// Represents the vertical sizing mode for a header.
|
||||
public enum MagazineLayoutHeaderHeightMode {
|
||||
|
||||
/// This height mode will force the header to be displayed with a height equal to `height`.
|
||||
///
|
||||
/// To properly support multiline labels, dynamic type, and other technologies that could affect
|
||||
/// the height of your headers dynamically, consider using the `dynamic` height mode.
|
||||
case `static`(height: CGFloat)
|
||||
|
||||
/// This height mode will cause the header to self-size in the vertical direction.
|
||||
///
|
||||
/// In practice, self-sizing in the vertical direction means that the header will get its height
|
||||
/// from the Auto Layout engine. Use this height mode for headers whose height is not known
|
||||
/// upfront. For example, if you support multiline labels or dynamic type, your height is likely
|
||||
/// not known until the Auto Layout engine resolves the layout at runtime.
|
||||
case dynamic
|
||||
|
||||
}
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
extension MagazineLayoutHeaderHeightMode: Equatable {
|
||||
|
||||
public static func == (
|
||||
lhs: MagazineLayoutHeaderHeightMode,
|
||||
rhs: MagazineLayoutHeaderHeightMode)
|
||||
-> Bool
|
||||
{
|
||||
switch (lhs, rhs) {
|
||||
case (.static(let l), .static(let r)): return l == r
|
||||
case (.dynamic, .dynamic): return true
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
// Created by bryankeller on 10/15/18.
|
||||
// Copyright © 2018 Airbnb, Inc.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import CoreGraphics
|
||||
|
||||
// MARK: - MagazineLayoutItemSizeMode
|
||||
|
||||
/// Represents the horizontal and vertical sizing mode for an item.
|
||||
public struct MagazineLayoutItemSizeMode {
|
||||
|
||||
// MARK: Lifecycle
|
||||
|
||||
public init(widthMode: MagazineLayoutItemWidthMode, heightMode: MagazineLayoutItemHeightMode) {
|
||||
self.widthMode = widthMode
|
||||
self.heightMode = heightMode
|
||||
}
|
||||
|
||||
// MARK: Public
|
||||
|
||||
/// The width mode for the item.
|
||||
public let widthMode: MagazineLayoutItemWidthMode
|
||||
|
||||
/// The height mode for the item.
|
||||
public let heightMode: MagazineLayoutItemHeightMode
|
||||
|
||||
}
|
||||
|
||||
// MARK: - MagazineLayoutItemWidthMode
|
||||
|
||||
/// Represents the horizontal sizing mode for an item.
|
||||
///
|
||||
/// Consecutive items with the same width mode will display on the same row until there is no more
|
||||
/// room.
|
||||
public enum MagazineLayoutItemWidthMode {
|
||||
|
||||
/// Full width items will fill the available width in a section.
|
||||
///
|
||||
/// Use this width mode to create lists of items.
|
||||
/// `respectsHorizontalInsets` specifies whether the item should be edge-to-edge in a section, or
|
||||
/// if it should be inset by the item insets specified for a section. `respectsHorizontalInsets`
|
||||
/// does not take into account section insets or the collection view's content inset.
|
||||
case fullWidth(respectsHorizontalInsets: Bool)
|
||||
|
||||
/// Fractional width items will take up `1/divisor` of the available width for a given row of
|
||||
/// items.
|
||||
///
|
||||
/// Use this width mode to create grids of items. Consider using `halfWidth`, `thirdWidth`,
|
||||
/// `fourthWidth`, or `fifthWidth`, which are equivalent to using `fractionalWidth` with a
|
||||
/// `divisor` of `2`, `3`, `4`, or `5`, respectively.
|
||||
///
|
||||
/// Fractional width items respect `contentInset.left` and `contentInset.right`, and are affected
|
||||
/// by the horizontal spacing specified for the section in which they're contained. On iOS 11 and
|
||||
/// higher, they will also take the safe area insets into account if the collection view's
|
||||
/// `contentInsetAdjustmentBehavior` property is set to a value that respects the safe area.
|
||||
///
|
||||
/// - Warning: `divisor` must be greater than `0`. Specifying `0` as the `divisor` is a programmer
|
||||
/// error and **will result in a runtime crash**.
|
||||
case fractionalWidth(divisor: UInt)
|
||||
|
||||
/// Half width items will take up `1/2` of the available width for a given row of items.
|
||||
public static var halfWidth: MagazineLayoutItemWidthMode {
|
||||
return .fractionalWidth(divisor: 2)
|
||||
}
|
||||
|
||||
/// Third width items will take up `1/3` of the available width for a given row of items.
|
||||
public static var thirdWidth: MagazineLayoutItemWidthMode {
|
||||
return .fractionalWidth(divisor: 3)
|
||||
}
|
||||
|
||||
/// Fourth width items will take up `1/4` of the available width for a given row of items.
|
||||
public static var fourthWidth: MagazineLayoutItemWidthMode {
|
||||
return .fractionalWidth(divisor: 4)
|
||||
}
|
||||
|
||||
/// Fifth width items will take up `1/5` of the available width for a given row of items.
|
||||
public static var fifthWidth: MagazineLayoutItemWidthMode {
|
||||
return .fractionalWidth(divisor: 5)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
extension MagazineLayoutItemWidthMode: Equatable {
|
||||
|
||||
public static func == (
|
||||
lhs: MagazineLayoutItemWidthMode,
|
||||
rhs: MagazineLayoutItemWidthMode)
|
||||
-> Bool
|
||||
{
|
||||
switch (lhs, rhs) {
|
||||
case (.fullWidth(let l), .fullWidth(let r)): return l == r
|
||||
case (.fractionalWidth(let l), .fractionalWidth(let r)): return l == r
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - MagazineLayoutItemHeightMode
|
||||
|
||||
/// Represents the vertical sizing mode for an item.
|
||||
///
|
||||
/// `MagazineLayout` supports vertically self-sizing and statically sized items. Since height modes
|
||||
/// are specified for each item, you can mix vertically self-sizing and statically sized items in
|
||||
/// the same sections, and even in the same rows.
|
||||
public enum MagazineLayoutItemHeightMode {
|
||||
|
||||
/// This height mode mode will cause the item to be displayed with a height equal to `height`.
|
||||
///
|
||||
/// To properly support multiline labels, dynamic type, and other technologies that could affect
|
||||
/// the height of your items dynamically, consider using one of the dynamic height modes.
|
||||
case `static`(height: CGFloat)
|
||||
|
||||
/// This height mode will cause the item to self-size in the vertical direction.
|
||||
///
|
||||
/// In practice, self-sizing in the vertical direction means that the item will get its height
|
||||
/// from the Auto Layout engine. Use this height mode for items whose height is not known upfront.
|
||||
/// For example, if you support multiline labels or dynamic type, your height is likely not known
|
||||
/// until the Auto Layout engine resolves the layout at runtime.
|
||||
case dynamic
|
||||
|
||||
/// This height mode will cause the item to self-size in the vertical direction, then resize to
|
||||
/// match the height of the tallest item in the same row of items.
|
||||
///
|
||||
/// If the item _is_ the tallest item in the row (after being self-sized), then it will stay
|
||||
/// at its self-sized height until it's no longer the tallest item in the row.
|
||||
///
|
||||
/// Note that items with this height mode will resize to match the height of the tallest item in
|
||||
/// the same row of items, even if the tallest item has a `static` height mode.
|
||||
case dynamicAndStretchToTallestItemInRow
|
||||
|
||||
}
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
extension MagazineLayoutItemHeightMode: Equatable {
|
||||
|
||||
public static func == (
|
||||
lhs: MagazineLayoutItemHeightMode,
|
||||
rhs: MagazineLayoutItemHeightMode)
|
||||
-> Bool
|
||||
{
|
||||
switch (lhs, rhs) {
|
||||
case (.static(let l), .static(let r)): return l == r
|
||||
case (.dynamic, .dynamic): return true
|
||||
case (.dynamicAndStretchToTallestItemInRow, .dynamicAndStretchToTallestItemInRow): return true
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Generated
Executable
+138
@@ -0,0 +1,138 @@
|
||||
// Created by bryankeller on 7/17/17.
|
||||
// Copyright © 2018 Airbnb, Inc.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import UIKit
|
||||
|
||||
public protocol UICollectionViewDelegateMagazineLayout: UICollectionViewDelegate {
|
||||
|
||||
/// Asks the delegate for the size mode 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 size mode of the specified item.
|
||||
func collectionView(
|
||||
_ collectionView: UICollectionView,
|
||||
layout collectionViewLayout: UICollectionViewLayout,
|
||||
sizeModeForItemAt indexPath: IndexPath)
|
||||
-> MagazineLayoutItemSizeMode
|
||||
|
||||
/// Asks the delegate for the visibility mode of the header in the specified section.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - collectionView: The collection view using the layout.
|
||||
/// - collectionViewLayout: The layout requesting the information.
|
||||
/// - index: The index of the section containing the header.
|
||||
///
|
||||
/// - Returns: The visibility mode of the header in the specified section.
|
||||
func collectionView(
|
||||
_ collectionView: UICollectionView,
|
||||
layout collectionViewLayout: UICollectionViewLayout,
|
||||
visibilityModeForHeaderInSectionAtIndex index: Int)
|
||||
-> MagazineLayoutHeaderVisibilityMode
|
||||
|
||||
/// Asks the delegate for the visibility mode of the footer in the specified section.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - collectionView: The collection view using the layout.
|
||||
/// - collectionViewLayout: The layout requesting the information.
|
||||
/// - index: The index of the section containing the footer.
|
||||
///
|
||||
/// - Returns: The visibility mode of the footer in the specified section.
|
||||
func collectionView(
|
||||
_ collectionView: UICollectionView,
|
||||
layout collectionViewLayout: UICollectionViewLayout,
|
||||
visibilityModeForFooterInSectionAtIndex index: Int)
|
||||
-> MagazineLayoutFooterVisibilityMode
|
||||
|
||||
/// Asks the delegate for the visibility mode of the background in the specified section.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - collectionView: The collection view using the layout.
|
||||
/// - collectionViewLayout: The layout requesting the information.
|
||||
/// - index: The index of the section containing the background.
|
||||
///
|
||||
/// - Returns: The visibility mode of the background in the specified section.
|
||||
func collectionView(
|
||||
_ collectionView: UICollectionView,
|
||||
layout collectionViewLayout: UICollectionViewLayout,
|
||||
visibilityModeForBackgroundInSectionAtIndex index: Int)
|
||||
-> MagazineLayoutBackgroundVisibilityMode
|
||||
|
||||
/// Asks the delegate for the horizontal spacing for items in the specified section.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - collectionView: The collection view using the layout.
|
||||
/// - collectionViewLayout: The layout requesting the information.
|
||||
/// - index: The index of the section whose horizontal item spacing is needed.
|
||||
///
|
||||
/// - Returns: The horizontal spacing for items in the specified section.
|
||||
func collectionView(
|
||||
_ collectionView: UICollectionView,
|
||||
layout collectionViewLayout: UICollectionViewLayout,
|
||||
horizontalSpacingForItemsInSectionAtIndex index: Int)
|
||||
-> CGFloat
|
||||
|
||||
/// Asks the delegate for the vertical spacing for items in the specified section.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - collectionView: The collection view using the layout.
|
||||
/// - collectionViewLayout: The layout requesting the information.
|
||||
/// - index: The index of the section whose vertical item spacing is needed.
|
||||
///
|
||||
/// - Returns: The vertical spacing for items in the specified section.
|
||||
func collectionView(
|
||||
_ collectionView: UICollectionView,
|
||||
layout collectionViewLayout: UICollectionViewLayout,
|
||||
verticalSpacingForElementsInSectionAtIndex index: Int)
|
||||
-> CGFloat
|
||||
|
||||
/// Asks the delegate for the amount by which to inset elements in the specified section.
|
||||
///
|
||||
/// Section insets are relative to the content's bounds, which is impacted by the collection
|
||||
/// view's content inset.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - collectionView: The collection view using the layout.
|
||||
/// - collectionViewLayout: The layout requesting the information.
|
||||
/// - index: The index of the section whose element insets are needed.
|
||||
///
|
||||
/// - Returns: The amount by which to inset elements in the specified section.
|
||||
func collectionView(
|
||||
_ collectionView: UICollectionView,
|
||||
layout collectionViewLayout: UICollectionViewLayout,
|
||||
insetsForSectionAtIndex index: Int)
|
||||
-> UIEdgeInsets
|
||||
|
||||
/// Asks the delegate for the amount by which to inset items in the specified section.
|
||||
///
|
||||
/// Item insets are relative to the section's bounds, which is impacted by the section's insets
|
||||
/// and, transitively, the collection view's content inset.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - collectionView: The collection view using the layout.
|
||||
/// - collectionViewLayout: The layout requesting the information.
|
||||
/// - index: The index of the section whose item insets are needed.
|
||||
///
|
||||
/// - Returns: The amount by which to inset items in the specified section.
|
||||
func collectionView(
|
||||
_ collectionView: UICollectionView,
|
||||
layout collectionViewLayout: UICollectionViewLayout,
|
||||
insetsForItemsInSectionAtIndex index: Int)
|
||||
-> UIEdgeInsets
|
||||
|
||||
}
|
||||
Generated
+61
@@ -0,0 +1,61 @@
|
||||
// Created by bryankeller on 11/29/18.
|
||||
// Copyright © 2018 Airbnb, Inc.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import UIKit
|
||||
|
||||
/// A collection reusable view that coordinates with `MagazineLayoutCollectionViewLayoutAttributes`
|
||||
/// to determine how to size itself: with self-sizing, or without self-sizing. Use this class
|
||||
/// (or subclasses) for displaying header and background supplementary views with `MagazineLayout`.
|
||||
///
|
||||
/// Note that this class is very similar to `MagazineLayoutCollectionViewCell`.
|
||||
///
|
||||
/// `UIKit` invokes `preferredLayoutAttributesFitting(_:)` with an initial set of layout attributes,
|
||||
/// giving this reusable view subclass a chance to modify the `size` property of the attributes
|
||||
/// based on whether or not we want to self-size.
|
||||
///
|
||||
/// Subclassing and/or adding additional protocol conformances is encouraged, although modifying
|
||||
/// the behavior of `preferredLayoutAttributesFitting(_:)` is not recommended.
|
||||
///
|
||||
/// This class exists because `MagazineLayout` supports self-sizing supplementary views in just the
|
||||
/// vertical dimension - a use case that `UICollectionReusableView` does not support out-of-the-box.
|
||||
open class MagazineLayoutCollectionReusableView: UICollectionReusableView {
|
||||
|
||||
override open func preferredLayoutAttributesFitting(
|
||||
_ layoutAttributes: UICollectionViewLayoutAttributes)
|
||||
-> UICollectionViewLayoutAttributes
|
||||
{
|
||||
guard let attributes = layoutAttributes as? MagazineLayoutCollectionViewLayoutAttributes else {
|
||||
assertionFailure("`layoutAttributes` must be an instance of `MagazineLayoutCollectionViewLayoutAttributes`")
|
||||
return super.preferredLayoutAttributesFitting(layoutAttributes)
|
||||
}
|
||||
|
||||
let size: CGSize
|
||||
if attributes.shouldVerticallySelfSize {
|
||||
// Self-sizing is required in the vertical dimension.
|
||||
size = super.systemLayoutSizeFitting(
|
||||
layoutAttributes.size,
|
||||
withHorizontalFittingPriority: .required,
|
||||
verticalFittingPriority: .fittingSizeLevel)
|
||||
} else {
|
||||
// No self-sizing is required; respect whatever size the layout determined.
|
||||
size = layoutAttributes.size
|
||||
}
|
||||
|
||||
layoutAttributes.size = size
|
||||
|
||||
return layoutAttributes
|
||||
}
|
||||
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
// Created by bryankeller on 11/29/18.
|
||||
// Copyright © 2018 Airbnb, Inc.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import UIKit
|
||||
|
||||
/// A cell that coordinates with `MagazineLayoutCollectionViewLayoutAttributes` to determine how to
|
||||
/// size itself: with self-sizing, or without self-sizing. Use this class (or subclasses) for
|
||||
/// displaying cells with `MagazineLayout`.
|
||||
///
|
||||
/// Note that this class is very similar to `MagazineLayoutCollectionReusableView`.
|
||||
///
|
||||
/// `UIKit` invokes `preferredLayoutAttributesFitting(_:)` with an initial set of layout attributes,
|
||||
/// giving this cell subclass a chance to modify the `size` property of the attributes based on
|
||||
/// whether or not we want to self-size.
|
||||
///
|
||||
/// Subclassing and/or adding additional protocol conformances is encouraged, although modifying
|
||||
/// the behavior of `preferredLayoutAttributesFitting(_:)` is not recommended.
|
||||
///
|
||||
/// This class exists because `MagazineLayout` supports self-sizing in just the vertical dimension -
|
||||
/// a use case that `UICollectionViewCell` does not support out-of-the-box.
|
||||
///
|
||||
/// As of iOS 12, `UICollectionReusableView` is tightly coupled with `UICollectionViewFlowLayout`'s
|
||||
/// private `_estimatesSizes` property, which is used to determine how to size cells displayed in a
|
||||
/// `UICollectionViewFlowLayout`. If `_estimatesSizes` is `true`, then `UICollectionReusableView`
|
||||
/// will self-size in both the horizontal and vertical dimensions. If it is `false`, no self-sizing
|
||||
/// will occur. In short, `UICollectionReusableView` is only optimized to work correctly with
|
||||
/// Apple's own layout.
|
||||
open class MagazineLayoutCollectionViewCell: UICollectionViewCell {
|
||||
|
||||
override open func preferredLayoutAttributesFitting(
|
||||
_ layoutAttributes: UICollectionViewLayoutAttributes)
|
||||
-> UICollectionViewLayoutAttributes
|
||||
{
|
||||
guard let attributes = layoutAttributes as? MagazineLayoutCollectionViewLayoutAttributes else {
|
||||
assertionFailure("`layoutAttributes` must be an instance of `MagazineLayoutCollectionViewLayoutAttributes`")
|
||||
return super.preferredLayoutAttributesFitting(layoutAttributes)
|
||||
}
|
||||
|
||||
// In some cases, `contentView`'s required width and height constraints
|
||||
// (created from its auto-resizing mask) will not have the correct constants before invoking
|
||||
// `systemLayoutSizeFitting(...)`, causing the cell to size incorrectly. This seems to be a
|
||||
// UIKit bug.
|
||||
// https://openradar.appspot.com/radar?id=5025850143539200
|
||||
// The issue seems most common when the collection view's bounds change (on rotation).
|
||||
// We correct for this by updating `contentView.bounds`, which updates the constants used by the
|
||||
// width and height constraints created by the `contentView`'s auto-resizing mask.
|
||||
|
||||
if contentView.bounds.width != layoutAttributes.size.width {
|
||||
contentView.bounds.size.width = layoutAttributes.size.width
|
||||
}
|
||||
|
||||
if
|
||||
!attributes.shouldVerticallySelfSize &&
|
||||
contentView.bounds.height != layoutAttributes.size.height
|
||||
{
|
||||
contentView.bounds.size.height = layoutAttributes.size.height
|
||||
}
|
||||
|
||||
let size: CGSize
|
||||
if attributes.shouldVerticallySelfSize {
|
||||
// Self-sizing is required in the vertical dimension.
|
||||
size = super.systemLayoutSizeFitting(
|
||||
layoutAttributes.size,
|
||||
withHorizontalFittingPriority: .required,
|
||||
verticalFittingPriority: .fittingSizeLevel)
|
||||
} else {
|
||||
// No self-sizing is required; respect whatever size the layout determined.
|
||||
size = layoutAttributes.size
|
||||
}
|
||||
|
||||
layoutAttributes.size = size
|
||||
|
||||
return layoutAttributes
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user