iOS自动布局 - 将位于tableviewcell内的视图移动到屏幕中心

时间:2013-07-03 04:55:52

标签: ios uitableview autolayout nsautolayout

我有一个包含文本视图和imageview的单元格的tableview。我的项目目前正在使用AutoLayout。我的目标是在点击时将图像视图全屏显示。一种选择是使用模态视图控制器,但我希望这项工作有点像在Facebook应用程序中点击图像的方式,应用程序使图像居中并淡化背景。

由于我使用autolayout,我不能简单地设置imageview的帧来填充屏幕。相反,我需要使用自动布局约束。我的图像视图有5个约束,约束设置距单元格底部的距离,以及左侧和右侧,以及控制图像高度的约束。最后一个是图像视图上方的文本视图和图像顶部之间的垂直空间约束。虽然这似乎与高度和底部约束相冲突,但由于某种原因,界面构建器迫使我有这个。为了避免出现问题,我将此约束的优先级设置为小于1000(无论如何,图像都不应与textview重叠,因为tableview单元格高度已设置,因此所有内容都能完美匹配)。

为了使图像居中,我将左右的距离设置为零并删除垂直空间约束。为了使图像居中,我将带有中心y对齐约束的底部空间约束替换为 UIWindow 而不是tableviewcell。我希望它在屏幕的中心,而不是细胞。

要获取主窗口,我使用它:

AppDelegate* myDelegate = (((AppDelegate*) [UIApplication sharedApplication].delegate));
//access main window using myDelegate.window

然后,设置约束:

//currently sets the distance from the bottom of the cell to 14
//changing it...
[cellselected removeConstraint:cellselected.imagebottomspace];
cellselected.imagebottomspace = [NSLayoutConstraint constraintWithItem:cellselected.viewimage attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:myDelegate.window attribute:NSLayoutAttributeCenterY multiplier:0 constant:0];
[cellselected addConstraint:cellselected.imagebottomspace];

然而,这不起作用。图像视图的宽度和高度的变化适用。然而,当读取imagebottomspace约束时,我得到一个不可满足的布局 - 显然约束与另一个约束冲突,该约束将底部和图像视图之间的距离设置为14,这是我刚刚删除的约束。所以它似乎并没有实际删除约束。

当我继续让app破坏约束时,imageview移动,但移动到错误的位置。它不在屏幕中心。它向上移动并离开屏幕。

显然我正在做的事情是不对的。我做错了什么?

2 个答案:

答案 0 :(得分:7)

所以我想你想要这样的东西:

zooming image view demo

首先,您需要知道,从Xcode 4.6.3开始,nib编辑器(“Interface Builder”)在表视图单元格中设置约束时会出错。它应该在子视图和单元格的内容视图之间创建约束,而是在子视图和单元格本身之间创建约束。这往往会在运行时搞砸布局。 (此错误已在Xcode 5及更高版本中修复。)

这样做的结果是你应该删除nib中的所有约束并在代码中重新创建它们,或者只是去除nib并在代码中创建单元格的整个视图层次结构。

其次,有一种更简单的方法来进行图像缩放。以下是选择单元格时的基本步骤:

  1. 将选定单元格的图像视图边界转换为顶级视图坐标系中的CGRect
  2. 仅为缩放创建新图像视图,并将其框架设置为CGRect。将其userInteractionEnabled设置为YES。将其autoresizingMask设置为灵活的宽度和高度。添加点击手势识别器。
  3. 将新图片视图添加为顶级视图的子视图。
  4. 将单元格的图片视图的hidden属性设置为YES
  5. 在动画块中,将新图像视图的帧设置为顶级视图的边界。
  6. 禁用表格视图的panGestureRecognizer
  7. 点击新图像视图时,请执行以下步骤:

    1. 将选定单元格的图像视图边界转换为顶级视图坐标系中的CGRect
    2. 在动画块中,将缩放图像视图的帧设置为CGRect
    3. 在动画完成块中:
      1. 从超级视图中删除缩放的图像视图。
      2. 将单元格的图片视图的hidden属性设置为NO
      3. 启用表格视图的panGestureRecognizer
    4. 由于您没有移动原始图像视图,因此您不必混淆其约束。隐藏的视图仍然参与布局。

      由于您是在代码中创建新的图片视图,因此默认情况下translatesAutoresizingMaskIntoConstraints设置为YES。这意味着您可以设置其框架。自动布局会自动将帧转换为约束。

      您可以在this github repository中找到完整的源代码。

答案 1 :(得分:0)

我刚刚遇到过类似的问题。我认为这些问题的原因是UIScrollViews中嵌入的视图存在于与其外部视图不同的边界系统中。这实际上是滚动首先如何工作,将其视为仅将变量偏移应用于它包含的视图。 Autolayout不知道如何在这些不同的坐标系之间进行转换,因此任何跨越的约束都不会按照您期望的方式应用。

引用Erica Sadun的优秀书籍iOS Auto Layout Demystified(来自' Constraints,Hierarchies,and Bounds Systems')

  

"了解边界系统。你不应该在一些按钮上关联   例如,查看单独集合中的文本字段   视图。如果有某种内容视图有自己的边界系统   (如集合视图,滚动视图和表视图),不要跳   在另一个视图中,这是一个完全不同的边界系统。"