包含视图控制器的可调整大小的容器视图
Resizable container views containing view controllers
我希望能够同时在屏幕上显示多个 UIViewController,按照下图排列成窗格。
能够:
- 在程序 运行 时添加其他窗格。
- 拖动窗格之间的栏以调整它们的大小
我在考虑使用容器视图(它们只是视图控制器?)
我怎样才能最好地做到这一点?
┌───────────────────┳────────────────────────────┐
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
┣━━━━━━━━━━━━━━━━━━━┫ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
└───────────────────┻────────────────────────────┘
我会在单独的 xib 中设置每个视图 + 约束,并使用 Masonry 在代码中为视图之间的约束创建简单的 AutoLayouting 约束。
我会有一个 ViewController 负责管理和调整您要添加的视图控制器的大小。
然后,我会将视图控制器及其视图添加到该主视图控制器中。
因此,您需要注意以下几点:
- 如果您使用自动布局,您需要从带有约束的视图控制器添加视图,因此当尺寸改变时,视图的内容也会改变。
- 如果您不使用自动布局,您可能希望在尺寸更改时进行一些更改,您可以在 viewDidLayoutSubviews 中进行此操作
- 如果需要调整 tableviews/collectionviews
的大小,也可以使用 viewDidLayoutSubViews
我不会使用故事板的 ContainerViewController。当您已经知道屏幕中需要多少个控制器时,这些更适合用于故事板。您反而想在代码中动态添加删除控制器。
首先实现一个处理普通视图(窗格)的控制器。将所有逻辑放在其中,以便在新窗格为 added/removed 时添加窗格、删除窗格并调整现有视图的大小。我也不会使用约束,会太复杂。当你添加一个窗格时,你必须知道它周围是什么视图的边,抓住它们并向它添加约束。删除窗格时,您还必须删除某些窗格的一些约束(不是全部)..太多了。
但是,如果您使用框架,则只需构建一个方程式即可获取容器的宽度和高度并重新计算所有视图的框架。
完成后,只需将控制器添加到这些窗格(视图)中,例如:
//Here self would be the containerController and paneContainer one of the pane views
UIViewController *newPaneVC = [UIViewController new];
newPaneVC.view.frame = [self calculateFrameForNewPane];
[self.paneContainer addSubview:newPaneVC.view];
[self addChildViewController:newPaneVC];
[newPaneVC didMoveToParentViewController:self];
//Add resizing masks to make sure new VC resizes with superview changes (example: when more panes are added/removed)
[newPaneVC.view setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
最后,看一下这个库:
https://github.com/yatsu/treemapkit
它是 3 年前完成的,但我在一个项目中使用它并且效果很好。它为您提供了根据一组值在屏幕上绘制不同大小的视图的所有逻辑。您可以使用它添加和删除窗格,并使用代表 return 已添加控制器的单元格(窗格)。
我创建了一个快速原型来演示如何做到这一点:https://github.com/MrNickBarker/iOSAccordionPanels/tree/master
我会在这里解释本质。您可以在 repo 中查看详细信息。
- 所有面板和分隔符都被限制为相互引导
- 分隔符相互约束(尾随前导),第一个分隔符被约束到父视图的前导侧
- 每个分隔符都包含对其对前一个分隔符的约束的引用,并使用平移手势更新该约束常量
- 面板有最小宽度限制。不是严格需要,但看起来不错。
- 分隔符约束具有较低的优先级(例如 999),因此它们遵守面板的最小宽度,如果有更多空间,这也提供了面板恢复到其大小的良好效果
- 添加或删除面板时,删除约束并为所有面板和分隔符再次添加它们。可以改进这一点以保留现有面板或动画的大小。
这是一个粗略的图表:
superview-panel-separator-panel-separator-panel-superview
superview-------separator-------separator
一个简单的解决方案是创建和管理由单个 ViewController 依次管理的 UIView。您可以通过使用 Auto Layout 的宽高比工具调整大小来实现各种尺寸和平铺效果。要创建新的图块,您可以在设定的间隔之间获取一个随机数以获得不同的大小。
我希望能够同时在屏幕上显示多个 UIViewController,按照下图排列成窗格。 能够:
- 在程序 运行 时添加其他窗格。
- 拖动窗格之间的栏以调整它们的大小
我在考虑使用容器视图(它们只是视图控制器?)
我怎样才能最好地做到这一点?
┌───────────────────┳────────────────────────────┐
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
┣━━━━━━━━━━━━━━━━━━━┫ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
│ ┃ │
└───────────────────┻────────────────────────────┘
我会在单独的 xib 中设置每个视图 + 约束,并使用 Masonry 在代码中为视图之间的约束创建简单的 AutoLayouting 约束。
我会有一个 ViewController 负责管理和调整您要添加的视图控制器的大小。
然后,我会将视图控制器及其视图添加到该主视图控制器中。
因此,您需要注意以下几点:
- 如果您使用自动布局,您需要从带有约束的视图控制器添加视图,因此当尺寸改变时,视图的内容也会改变。
- 如果您不使用自动布局,您可能希望在尺寸更改时进行一些更改,您可以在 viewDidLayoutSubviews 中进行此操作
- 如果需要调整 tableviews/collectionviews 的大小,也可以使用 viewDidLayoutSubViews
我不会使用故事板的 ContainerViewController。当您已经知道屏幕中需要多少个控制器时,这些更适合用于故事板。您反而想在代码中动态添加删除控制器。
首先实现一个处理普通视图(窗格)的控制器。将所有逻辑放在其中,以便在新窗格为 added/removed 时添加窗格、删除窗格并调整现有视图的大小。我也不会使用约束,会太复杂。当你添加一个窗格时,你必须知道它周围是什么视图的边,抓住它们并向它添加约束。删除窗格时,您还必须删除某些窗格的一些约束(不是全部)..太多了。
但是,如果您使用框架,则只需构建一个方程式即可获取容器的宽度和高度并重新计算所有视图的框架。
完成后,只需将控制器添加到这些窗格(视图)中,例如:
//Here self would be the containerController and paneContainer one of the pane views
UIViewController *newPaneVC = [UIViewController new];
newPaneVC.view.frame = [self calculateFrameForNewPane];
[self.paneContainer addSubview:newPaneVC.view];
[self addChildViewController:newPaneVC];
[newPaneVC didMoveToParentViewController:self];
//Add resizing masks to make sure new VC resizes with superview changes (example: when more panes are added/removed)
[newPaneVC.view setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
最后,看一下这个库: https://github.com/yatsu/treemapkit
它是 3 年前完成的,但我在一个项目中使用它并且效果很好。它为您提供了根据一组值在屏幕上绘制不同大小的视图的所有逻辑。您可以使用它添加和删除窗格,并使用代表 return 已添加控制器的单元格(窗格)。
我创建了一个快速原型来演示如何做到这一点:https://github.com/MrNickBarker/iOSAccordionPanels/tree/master
我会在这里解释本质。您可以在 repo 中查看详细信息。
- 所有面板和分隔符都被限制为相互引导
- 分隔符相互约束(尾随前导),第一个分隔符被约束到父视图的前导侧
- 每个分隔符都包含对其对前一个分隔符的约束的引用,并使用平移手势更新该约束常量
- 面板有最小宽度限制。不是严格需要,但看起来不错。
- 分隔符约束具有较低的优先级(例如 999),因此它们遵守面板的最小宽度,如果有更多空间,这也提供了面板恢复到其大小的良好效果
- 添加或删除面板时,删除约束并为所有面板和分隔符再次添加它们。可以改进这一点以保留现有面板或动画的大小。
这是一个粗略的图表:
superview-panel-separator-panel-separator-panel-superview
superview-------separator-------separator
一个简单的解决方案是创建和管理由单个 ViewController 依次管理的 UIView。您可以通过使用 Auto Layout 的宽高比工具调整大小来实现各种尺寸和平铺效果。要创建新的图块,您可以在设定的间隔之间获取一个随机数以获得不同的大小。