UICollectionViewSplitLayout 1.0.0

UICollectionViewSplitLayout 1.0.0

Kazuhiro Hayashi 维护。



  • 作者:
  • Kazuhiro Hayashi

uicollectionviewsplitlayout_logo

Platform Swift 4.2 License Version Carthage compatible

UICollectionViewSplitLayout 使得集合视图更加响应。

这是什么?

UICollectionViewSplitLayout 是 UICollectionViewLayout 的子类。它将分区分为一列或两列。

集合视图有 "分区" 用于组织项集合。UICollectionViewFlowLayout 从顶部到底部排列它们。

另一方面,UICollectionViewSplitLayout 将分区分为两列。您可以动态更新它们的宽度以及每个分区所在的列。

例如,使用 UICollectionViewSplitLayout 的集合视图根据设备方向改变列数。您只需要在改变屏幕大小时设置 leftSideRatio 的值。此图描述了一个有三个分区(红色、蓝色和绿色)的集合视图和 UICollectionViewSplitLayout 将它们布局在左侧或右侧。

render_well

如果您无法想象它是如何工作的,请运行 EmojiCollectionViewController

要求

  • iOS 9.0+
  • Swift 4.2

安装

Carthage

1. 创建 Cartfile

github "https://github.com/yahoojapan/UICollectionViewSplitLayout"

2. 安装

> carthage update

CocoaPods

1. 创建 Podfile

platform :ios, '8.0'
use_frameworks!

pod "UICollectionViewSplitLayout", :git => 'https://github.com/yahoojapan/UICollectionViewSplitLayout.git'

2. 安装

> pod install

入门指南

从将 UICollectionViewFlowLayout 替换为 UICollectionViewSplitLayout 开始是个不错的选择。

1. 创建 UICollectionViewController

在 Storyboard 上设置 UICollectionViewController。

2018-10-24 10 28 36

添加构建集合视图的实现。

import UIKit

private let reuseIdentifier = "Cell"

class BasicCollectionViewController: UICollectionViewController {
    @IBOutlet weak var layout: UICollectionViewSplitLayout!
    
    var dataSource: [[UIColor]] = [
        (0..<20).map { _ in .red },
        (0..<20).map {  _ in .blue },
        (0..<20).map {  _ in .green }
    ]

    override func viewDidLoad() {
        super.viewDidLoad()
        self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
    }
    // MARK: UICollectionViewDataSource

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return dataSource.count
    }


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return dataSource[section].count
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
        cell.backgroundColor = dataSource[indexPath.section][indexPath.row]
        return cell
    }
}

构建代码。

2018-10-24 10 27 42

显示三个部分,其项目具有不同的颜色。

2. 将 UICollectionViewSplitLayout 输入到自定义布局类

将布局属性更改为 "Custom",然后在类和模块属性中输入 "UICollectionViewSplitLayout"。

2018-10-30 11 07 59

3. 设置 UICollectionViewSplitLayout 的参数

将故事板中的布局类连接到源代码。在 viewDidLoad() 中设置参数。

    @IBOutlet weak var layout: UICollectionViewSplitLayout!
 
    override func viewDidLoad() {
        super.viewDidLoad()
        //...
        //...
        
        layout.minimumItemLineSpacing = 8
        layout.minimumInterItemSpacing = 8
        layout.sectionInset = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
        layout.splitSpacing = 0.4
        collectionView.collectionViewLayout = layout

        //...
        //...
    }

4. 实现 UICollectionViewSplitLayout 的布局代理

实现 UICollectionViewDelegateTwoColumnLayout。以下方法是必需的。

extension BasicCollectionViewController: UICollectionViewDelegateSectionSplitLayout {
    // Fix the size of each item as UICollectionViewDelegateFlowLayout does. calculateFixedWidthRaughly() is utility method UICollectionViewSplitLayout has.
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath, width: CGFloat, side: UICollectionViewSplitLayoutSide) -> CGSize {
        let width = layout.calculateFixedWidthRaughly(
                               to: 3, 
                               of: side, 
                               minimumInterItemSpacing: layout.minimumInterItemSpacing, 
                               sectionInset: layout.sectionInset)
        return CGSize(width: width, height: 100)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sideForSection section: Int) -> UICollectionViewSplitLayoutSide {
        // when a section number is odd, the items are placed into left side. 
        return section % 2 == 0 ? .left : .right
    }
}

它将每个分区分为左侧或右侧。

2018-10-24 18 00 25

查看 BasicCollectionViewController 以运行上面的示例。

架构

它是 UICollectionViewLayout 之一。因此,您可以在不更新 UICollectionViewDelegate 和 UICollectionViewDataSource 中的代码的情况下更改布局。这是应用新布局的合理方式。您需要做的就是学习布局类和代理。

用法

如何分割

UICollectionViewSplitLayout 使用以下参数计算左右两侧的宽度。

leftSideRatio = 0.4

它包含一个浮点值,表示左边宽度与整个宽度的比例。此外,左右两侧之间还有间隔。

splitSpacing = 10

如果集合视图宽度为110pt,上述设置需要左侧40pt的宽度,右侧60pt的宽度。当左边比例(leftSideRatio)为0.0时,splitSpacing作为例外会被忽略。

您可以选择每个部分在哪一侧。UICollectionViewDelegateSectionSplitLayout提供了一个方法来实现这一点。

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sideForSection section: Int) -> UICollectionViewSplitLayoutSide

UICollectionViewSplitLayout在每次集合视图调用invalidateLayout()时都会挂钩委托。

边距

UICollectionViewSplitLayout有这些参数来确定边距。

/// The minimum spacing to use between items in the same row.
open var minimumInterItemSpacing: CGFloat
/// The minimum spacing to use between lines of items in the grid.
open var minimumItemLineSpacing: CGFloat
/// The margins used to lay out content in a section
open var sectionInset: UIEdgeInsets

它们通过部分(可选)有对应委托方法。

// section inset to each section
@objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int, side: UICollectionViewSplitLayoutSide) -> UIEdgeInsets
    
// minimumInterItemSpacing to each section
@objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInterItemSpacingForSectionAtIndex section: Int, side: UICollectionViewSplitLayoutSide) -> CGFloat

// minimumItemLineSpacing to each section
@objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumItemLineSpacingForSectionAtIndex section: Int, side: UICollectionViewSplitLayoutSide) -> CGFloat

固定(iOS 11~)

UICollectionViewSplitLayout像UICollectionViewFlowLayout一样固定部分标题。该功能从iOS 11开始支持。sectionPinToVisibleBounds允许其工作。

设置属性

UICollectionViewSplitLayout使用三种属性:项目(item)、辅助视图(supplementary view)和装饰视图(decoration view)。

项目

您需要实现单元格-sizing。UICollectionViewSplitLayout提供了一个委托来实现它。

func collectionView(
    _ collectionView: UICollectionView, 
    layout collectionViewLayout: UICollectionViewLayout, 
    sizeForItemAtIndexPath indexPath: IndexPath, 
    width: CGFloat, 
    side: UICollectionViewSplitLayoutSide) -> CGSize

您可以使用实用方法均匀地分配大小。

open func calculateFixedWidthRaughly(
    to num: Int, 
    of side: UICollectionViewSplitLayoutSide, 
    minimumInterItemSpacing: CGFloat, 
    sectionInset: UIEdgeInsets) -> CGFloat

标题和页脚的辅助视图

您可以实现标题和页脚的大小。UICollectionViewSplitLayout提供了一个委托来实现它。如果大小为零,则忽略标题和页脚。

// header
@objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int, width: CGFloat, side: UICollectionViewSplitLayoutSide) -> CGSize

// footer size
@objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int, width: CGFloat, side: UICollectionViewSplitLayoutSide) -> CGSize

为backgroundColor的装饰视图

UICollectionSplitLayout有一个特殊的装饰视图。它的大小与部分相同。你可以通过以下代理确定每个部分的backgroundColor。

@objc optional func collectionView(
    _ collectionView: UICollectionView, 
    layout collectionViewLayout: UICollectionViewLayout,
    itemsBackgroundColorFor section: Int, 
    side: UICollectionViewSplitLayoutSide) -> UIColor?

行高标准化

如果该属性为true,则项目高度调整为行轮廓高度(默认:false)。

open var isNormalizingLineHeight: Bool

许可证

MIT许可证(MIT)

版权所有(c)2018 Yahoo Japan Corporation

允许任何人在不支付费用的前提下使用此软件及其相关文档(“软件”),包括但不限于使用、复制、修改、合并、发布、分发、再许可或出售软件的副本,并允许向获取软件的个人提供使用软件的权利,但前提是遵守以下条件

本版权声明和本许可声明应包含在软件的所有副本或主要部分。

软件按“原样”提供,不提供任何明示或暗示的保证,包括但不限于适销性、特定用途适用性和非侵权性保证。在任何情况下,无论因合同、侵权或其他行为提起何种诉讼或诉讼原因,作者或版权持有者均不对任何索赔、损害或其他责任承担责任,无论是否基于软件或其使用或其他方式。