Uitableview 自动布局:如何压缩复杂的popover

Uitableview 自动布局:如何压缩复杂的popover,uitableview,uiscrollview,uipopovercontroller,uicontainerview,container-view,Uitableview,Uiscrollview,Uipopovercontroller,Uicontainerview,Container View,如果您喜欢尝试源代码(您非常喜欢),请查看我的 我有一个弹出对话框,显示设置列表。这些设置列在多个UITableView中。UITableView不应可滚动,因为整体设置视图已处于滚动状态。此外,popover对话应根据需要垂直占据尽可能多的屏幕,但应水平压缩 因此,我设想了以下结构: UIView => MySettingsViewController - UIScrollView - UIView (Content View) - Container View1

如果您喜欢尝试源代码(您非常喜欢),请查看我的

我有一个弹出对话框,显示设置列表。这些设置列在多个UITableView中。UITableView不应可滚动,因为整体设置视图已处于滚动状态。此外,popover对话应根据需要垂直占据尽可能多的屏幕,但应水平压缩

因此,我设想了以下结构:

UIView => MySettingsViewController
- UIScrollView
  - UIView (Content View)
    - Container View1
      - UITableView (embedded) => MyTableViewController
    - Container View2
      - UITableView (embedded)
通过Interface Builder组装结构,并使用Autolayout调整尺寸

我有滚动视图、内容视图(我刚开始时只有一个)和容器视图,它们分别指向各自的超级视图(或布局指南)。我以以下方式约束内容视图的大小:

contentView.width == (topmost) UIView.width
contentView.height == 200 // removed at build time
此外,我将表视图的大小设置为其内容大小,因为否则popover看起来是空的:

类MyTableViewController:UITableViewController{
覆盖功能视图显示(动画:Bool){
super.viewdide显示(动画)
//这是制图语法-意图应该是明确的
布局(视图,替换:ConstraintGroup()){[unowned self]视图
view.width==self.tableView.contentSize.width
view.height==self.tableView.contentSize.height
}
view.setNeedsLayout()文件
}
} 
“设置”弹出窗口中充满了内容,但其大小不太正确:

为了解决这个问题,我尝试了以下不起作用的方法:

类MySettingsViewController:UIViewController{
重写变量preferredContentSize:CGSize{
得到{
让compressedSize=view.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
//这始终是(0,0),因为子视图尚未调整大小
返回压缩大小
}
设置{
super.preferredContentSize=newValue
}
}
}

总而言之:压缩不起作用。

所以我自己解决了这个问题,正如您在查看Bitbucket存储库时看到的那样

现在,在
MyTableViewController
mysettingviewcontroller
中,布局都已固定。前一个现在看起来像这样:

类MyTableViewController:UITableViewController{
var heightConstraint:NSLayoutConstraint?
var TableViewedgeConstraints:[NSLayoutConstraint]?
覆盖功能视图将出现(动画:Bool){
超级。视图将显示(动画)
如果let container=tableView.superview,其中tableviewEdgeConstraints==nil{
布局(tableView,容器,替换:ConstraintGroup()){[unowned self]tableView,中的容器
self.tableView.edgesconstraints=tableView.edges==inset(container.edges,0)
}
}
}
重写func viewdilayoutsubviews(){
super.viewDidLayoutSubviews()
如果让heightConstraint=heightConstraint{
如果Int(heightConstraint.constant)!=Int(tableView.contentSize.height){
heightConstraint.constant=self.tableView.contentSize.height
}
}否则{
布局(视图,替换:ConstraintGroup()){[unowned self]视图
如果(self.tableView.contentSize.height>0){
self.heightConstraint=view.height==self.tableView.contentSize.height
}
}
}
}
} 
因此,基本上,我将表的高度约束为其内容的高度,并在内容的高度发生变化时更改约束。桌子一摆好就可以这样做。此外,嵌套表视图的边固定到容器视图的边上。我认为这是强制性的,因为我无法找到如何在Interface Builder中约束不同场景的两个视图

MySettingsViewController
中,一旦知道滚动视图的大小,滚动视图的大小就会设置为内容视图框架的大小(可通过出口访问)。此外,为了压缩popover,当高度改变时,设置控制器的preferredContentSize会相应地调整(如果忽略此条件,您可能会陷入无休止的布局循环中)。此外,我做了3件事,使MySettingsViewController周围有一个导航控制器:

  • popover的宽度设置为固定值(否则有时会扩展到全宽)
  • presentedViewController的preferredContentSize需要同等设置
  • 我必须将scrollView的插入设置为0,以避免丑陋的垂直偏移-此解决方案是次优的,因为它稍微破坏了scrollView的体验。但它可以工作
  • 代码如下:

    类MySettingsViewController:UIViewController{
    @ibvar-contentView:UIView!
    @iBCROLLVIEW:UIScrollView!
    重写func viewdilayoutsubviews(){
    super.viewDidLayoutSubviews()
    scrollView.contentSize=contentView.frame.size
    if(preferredContentSize.height!=scrollView.contentSize.height){
    let newSize=CGSize(宽度:400,高度:scrollView.contentSize.height)
    preferredContentSize=newSize
    presentingViewController?.presentedViewController?.preferredContentSize=newSize
    scrollView.contentInset=UIEdgeInsetsMake(0,0,0,0)
    }
    }
    }
    
    这就是结果: