CGLayout 0.7.2

CGLayout 0.7.2

测试已测试
Lang语言 SwiftSwift
许可证 MIT
已发布最新发布2019 年 12 月
SPM支持 SPM

Denis Koryttsev 维护。




CGLayout 0.7.2

CGLayout

CI Status Version License Platform

一个强大的自动布局框架,可以管理 UIView(NSView)、CALayer 和未渲染的视图。具有跨层级坐标系。采用基于矩形约束的执行。快速、异步、声明式、可缓存、可扩展。支持 iOS、macOS、tvOS、Linux。

由 [LayoutBenchmarkFramework](https://github.com/lucdion/LayoutFrameworkBenchmark) 执行

快速教程

使用 CGLayout 和布局块构建布局。要组合块到单一单元,请使用 LayoutScheme 实体(或其他后缀为 Scheme 的实体)。

let subviewsScheme = LayoutScheme(blocks: [
// ... layout blocks
])

要定义 "视图" 元素的块,请使用 LayoutBlock 实体,或直接使用便利获取方法 func layoutBlock(with:constraints:)

titleLabel.layoutBlock(
    with: Layout(x: .center(), y: .top(5), width: .scaled(1), height: .fixed(120)),
    constraints: [
        logoImageView.layoutConstraint(for: [.bottom(.limit(on: .inner))])
    ]
)
/// or using anchors
titleLabel.layoutBlock(
    with: Layout(x: .center(), y: .top(5), width: .scaled(1), height: .fixed(120)),
    constraints: { anchors in
        anchors.top.equal(to: logoImageView.layoutAnchors.bottom)
    }
)

为了理解如何构建布局块,让我们看看在 LayoutBlock 中的布局过程。例如,我们有这个配置

LayoutBlock(
    with: layoutElement, 
    layout: Layout(x: .left(10), y: .top(10), width: .boxed(10), height: .boxed(10)),
    constraints: [
        element1.layoutConstraint(for: [
            .bottom(.limit(on: .outer)), .right(.limit(on: .inner))
        ]),
        element2.layoutConstraint(for: [
            .right(.limit(on: .outer)), .bottom(.limit(on: .inner))
        ])
    ]
)

您需要仔细处理块创建,因为锚点和基于它们的约束没有优先级,并且是按顺序应用的。约束应该操作实际框架,因此下一个布局块必须具有与 "视图" 的约束,这些视图不会更改框架。

布局锚点是限制器,它们面向框架属性(例如侧面、大小、位置)。任何基于侧面的锚点有三种基本实现:对齐、限制(裁剪)、拉动。这些实现中的每一个都依赖于工作空间:内部和外部。基于大小的锚点由两种实现表示:大小、内边距。您可以在 enum LayoutAnchor 中找到所有布局锚点。

要创建关联的布局约束,请使用 protocol LayoutConstraintProtocol。框架提供了这样的默认实现

  • LayoutConstraint:简单关联约束,该约束使用传递的元素的 var frame 来约束源矩形。使用它可以建立对外部工作空间的依赖。
  • AdjustLayoutConstraint:关联约束以调整源空间的尺寸。只有符合protocol AdjustableLayoutElement的元素才能使用它。
  • ContentLayoutConstraint:使用内部边界进行约束的关联约束,定义在protocol LayoutElement的'layoutBounds'属性中。如果你需要创建对内部工作空间的依赖,请使用它。例如,UIScrollView内的元素。
  • BaselineLayoutConstraint:依赖于基准线的关联约束。只有符合protocol TextPresentedElement的元素才能使用它。
  • AnonymConstraint:独立于外部环境限制源空间的约束。
  • MutableLayoutConstraint:创建可更改活动状态的布局约束。您可以通过相关元素的便利函数找到所有这些约束。用它来构建布局块。

在常见情况下,应在其他所有约束之后(但不总是如此)应用调整约束。

weatherLabel.layoutBlock(
    with: Layout(x: .left(10), y: .top(), width: .scaled(1), height: .scaled(1)),
    constraints: [
        weatherImageView.layoutConstraint(for: [.top(.limit(.inner)), .right(.limit(.outer)), .height()]),
        weatherLabel.adjustLayoutConstraint(for: [.width()])
    ]
)
AnonymConstraint(anchors: [
    Inset(UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 15))
])

为了实现自定义布局实体并保存强类型代码,请使用static func build(_ base: Conformed) -> Self方法。

每个布局块都有布局、截屏和应用截屏的方法。因此,您可以使用布局块进行直接布局、背景布局和缓存布局。

// layout directly
layoutScheme.layout()

// layout in background
let bounds = view.bounds
    DispatchQueue.global(qos: .background).async {
    let snapshot = self.layoutScheme.snapshot(for: bounds)
    DispatchQueue.main.sync {
        self.layoutScheme.apply(snapshot: snapshot)
    }
}

// cached layout
if UIDevice.current.orientation.isPortrait, let snapshot = portraitSnapshot {
    layoutScheme.apply(snapshot: snapshot)
} else if UIDevice.current.orientation.isLandscape, let snapshot = landscapeSnapshot {
    layoutScheme.apply(snapshot: snapshot)
} else {
    layoutScheme.layout()
}

典型的sizeThatFits(_:)方法实现。

func sizeThatFits(_ size: CGSize) -> CGSize {
    let sourceRect = CGRect(origin: .zero, size: size)
    let snapshot = scheme.snapshot(for: sourceRect)
    return snapshot.frame
}

LayoutGuide

框架提供了LayoutGuide,作为UILayoutGuide的类似物。它可以生成视图并将它们添加到层次结构中。LayoutGuide可以用作不可见的限制器,也可以用作布局容器。默认布局容器:StackLayoutGuide - 简单的堆叠实现。ScrollLayoutGuide - 与UIScrollView具有类似接口。通过使用它,我们可以在任何地方启用滚动。LayoutPlaceholder - 单个元素容器,可以懒惰地加载视图。针对CALayer - LayerPlaceholderUIView - ViewPlaceholder有默认实现。UIViewPlaceholder - 基于UILayoutGuide的单个元素容器。

UILayoutGuide也采用了LayoutElement协议。因此,你可以安全地基于UIView.safeAreaLayoutGuide和其他内容创建约束。

RTL

要启用从右到左的模式,请使用全局配置。

CGLConfiguration.default.isRTLMode = true

有关更多详细信息,请参阅文档和示例项目。

代码文档

请参阅这里

示例

macOS, iOS, tvOS

要运行示例项目,请先克隆存储库,然后从 Example 目录中运行 pod install.

Linux

要运行示例项目,请先克隆存储库,然后从 linux_example 目录中运行 swift run.

需求

Swift 5

安装

CGLayout 通过 CocoaPods 提供。要安装它,只需将以下行添加到您的 Podfile 中

pod "CGLayout"

贡献

我非常欢迎您的反馈、建议和 pull 请求。更多信息请参阅 这里

作者

Denis Koryttsev 邮箱:[email protected] Twitter:[https://twitter.com/K_o_D_e_N](https://twitter.com/K_o_D_e_N)

许可

CGLayout 在MIT许可下可用。有关更多信息,请参阅LICENSE文件。