4

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

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

为了使图像居中,我将左右距离设置为零并移除垂直空间约束。为了使图像居中,我将底部空间约束替换为UIWindow的中心 y 对齐约束,而不是 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,这是我刚刚删除的约束。所以看起来它实际上并没有消除约束。

当我继续并让应用程序打破约束时,图像视图会移动,但会移动到错误的位置。它不在屏幕中央。它向上移动并离开屏幕。

显然我的做法是不对的。我究竟做错了什么?

4

2 回答 2

7

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

缩放图像视图演示

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

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

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

  1. 将所选单元格的图像视图边界转换为CGRect顶级视图坐标系中的 a。
  2. 创建一个仅用于缩放的新图像视图并将其框架设置为CGRect. 将其设置userInteractionEnabledYES。将其设置autoresizingMask为灵活的宽度和高度。添加点击手势识别器。
  3. 添加新的图像视图作为顶级视图的子视图。
  4. 将单元格的图像视图的hidden属性设置为YES
  5. 在动画块中,将新图像视图的框架设置为顶级视图的边界。
  6. 禁用表格视图的panGestureRecognizer.

当新的图像视图被点击时,反转过程:

  1. 将所选单元格的图像视图边界转换为CGRect顶级视图坐标系中的 a。
  2. 在动画块中,将缩放的图像视图的框架设置为CGRect.
  3. 在动画完成块中:
    1. 从其超级视图中删除缩放的图像视图。
    2. 将单元格的图像视图的hidden属性设置为NO
    3. 启用表格视图的panGestureRecognizer.

由于您没有移动原始图像视图,因此您不必弄乱它的约束。隐藏的视图仍然参与布局。

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

您可以在这个 github 存储库中找到完整的源代码。

于 2013-07-03T06:52:21.880 回答
0

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

引用 Erica Sadun 的优秀书籍 iOS Auto Layout Demystified (来自“约束、层次结构和边界系统”部分):

“注意边界系统。您不应该将某个视图上的按钮与单独的集合视图中的文本字段相关联。如果有某种内容视图具有自己的边界系统(例如集合视图、滚动视图)和表视图),不要跳到另一个视图中的完全不同的边界系统。”

于 2014-04-25T11:31:23.133 回答