[英]iOS autolayout-move a view located inside a tableviewcell to the center of the screen
I have a tableview with cells containing text views as well as imageviews. 我有一个包含文本视图和图像视图的单元格的tableview。 My project is currently using AutoLayout.
我的项目目前正在使用AutoLayout。 My goal is to get the imageview to display in fullscreen when it is tapped.
我的目标是在点击时将图像视图全屏显示。 One option is to use a modal view controller, but I want to have this work sort of like the way tapping on images in the facebook app works, the app centers the image and fades the background.
一个选项是使用模态视图控制器,但我想让这项工作有点像在Facebook应用程序中点击图像的方式工作,应用程序使图像居中并淡化背景。
Since I'm using autolayout, I cannot simply set the frame of the imageview to fill the screen. 由于我使用autolayout,我不能简单地设置imageview的框架来填充屏幕。 Instead, I need to use autolayout constraints.
相反,我需要使用自动布局约束。 My image view has 5 constraints, a constraint setting a distance from the bottom of the cell, as well as the left an right sides, and one controlling the image height.
我的图像视图有5个约束,约束设置距单元格底部的距离,以及左侧和右侧,以及控制图像高度的约束。 The last is a vertical space constraint between the textview above the image view and the top of the image.
最后一个是图像视图上方的文本视图和图像顶部之间的垂直空间约束。 While this would appear to conflict with the height and bottom constraints, for some reason interface builder forces me to have this.
虽然这似乎与高度和底部约束相冲突,但由于某种原因,界面构建器迫使我有这个。 To avoid problems, I set this constraint's priority to be less than 1000 (the image should never overlap the textview anyways, since the tableview cell height is set so everything will fit perfectly).
为了避免出现问题,我将此约束的优先级设置为小于1000(无论如何,图像永远不会与textview重叠,因为tableview单元格高度设置为所有内容都完全适合)。
To center the image, I set the distance from the left and right to be zero and remove the vertical space constraint. 为了使图像居中,我将左右距离设置为零,并删除垂直空间约束。 In order to center the image, I replace the bottom space constraint with a center y alignment constraint to the UIWindow as opposed to the tableviewcell.
为了使图像居中,我将带有中心y对齐约束的底部空间约束替换为UIWindow而不是tableviewcell。 I want to have it be in the center of the screen, not the cell.
我希望它在屏幕的中心,而不是细胞。
To get the main window I use this: 要获取主窗口,我使用此:
AppDelegate* myDelegate = (((AppDelegate*) [UIApplication sharedApplication].delegate));
//access main window using myDelegate.window
Then, to set the constraint: 然后,设置约束:
//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];
However, this doesn't work. 但是,这不起作用。 The changes in the width and height of the image view apply just fine.
图像视图的宽度和高度的变化适用。 However, when readding the imagebottomspace constraint, I get an unsatisfiable layout--apparently the constraint conflicts with another constraint which sets the distance between the bottom and the image view to 14, the very constraint I just removed.
然而,当读取imagebottomspace约束时,我得到一个不可满足的布局 - 显然约束与另一个约束冲突,该约束将底部和图像视图之间的距离设置为14,这是我刚刚删除的约束。 So it seems that it isn't actually removing the constraint.
所以它似乎并没有实际删除约束。
When I proceed and let the app break a constraint, the imageview moves, but to the wrong place. 当我继续让app破坏约束时,imageview会移动,但会移动到错误的位置。 It isn't centering in the screen.
它不在屏幕中心。 It moves way up and off the screen.
它向上移动并离开屏幕。
Obviously what I'm doing isn't right. 显然我正在做的事情是不对的。 What am I doing wrong?
我究竟做错了什么?
So I guess you want something like this: 所以我想你想要这样的东西:
First, you need to know that as of Xcode 4.6.3, the nib editor (“Interface Builder”) has a bug when setting up constraints in a table view cell. 首先,您需要知道从Xcode 4.6.3开始,在表视图单元格中设置约束时,nib编辑器(“Interface Builder”)存在错误。 It should create the constraints between the subviews and the cell's content view, but instead it creates the constraints between the subviews and the cell itself.
它应该在子视图和单元格的内容视图之间创建约束,而是在子视图和单元格本身之间创建约束。 This tends to screw up layout at runtime.
这往往会在运行时搞砸布局。 (This bug is fixed in Xcode 5 and later.)
(此错误在Xcode 5及更高版本中得到修复。)
The consequence of this is that you should either remove all of the constraints that were in the nib and recreate them in code, or just get rid of the nib and create the cell's entire view hierarchy in code. 这样做的结果是你应该删除nib中的所有约束并在代码中重新创建它们,或者只是去除nib并在代码中创建单元格的整个视图层次结构。
Second, there's an easier way to do the image zooming. 其次,有一种更简单的方法来进行图像缩放。 Here's the basic procedure when a cell is selected:
这是选择单元格时的基本过程:
CGRect
in the top-level view's coordinate system. CGRect
。 CGRect
. CGRect
。 Set its userInteractionEnabled
to YES
. userInteractionEnabled
设置为YES
。 Set its autoresizingMask
to flexible width and height. autoresizingMask
设置为灵活的宽度和高度。 Add a tap gesture recognizer. hidden
property to YES
. hidden
属性设置为YES
。 panGestureRecognizer
. panGestureRecognizer
。 When the new image view is tapped, reverse the procedure: 点击新图像视图时,请执行以下步骤:
CGRect
in the top-level view's coordinate system. CGRect
。 CGRect
. CGRect
。 hidden
property to NO
. hidden
属性设置为NO
。 panGestureRecognizer
. panGestureRecognizer
。 Since you're not moving the original image view, you don't have to mess with its constraints. 由于您没有移动原始图像视图,因此您不必混淆其约束。 Hidden views still participate in layout.
隐藏的视图仍然参与布局。
Since you're creating the new image view in code, it will have translatesAutoresizingMaskIntoConstraints
set to YES
by default. 既然你在代码中创建的新的图像视,它将有
translatesAutoresizingMaskIntoConstraints
设置为YES
默认。 This means that you can just set its frame. 这意味着您可以设置其框架。 Auto layout will automatically turn the frame into constraints.
自动布局将自动将框架转换为约束。
You can find the full source code in this github repository . 您可以在此github存储库中找到完整的源代码。
I've just come across a similar issue. 我刚遇到类似的问题。 I think that the reason for these problems are that the views embedded in UIScrollViews exist in a different bounds system to those of the views outside it.
我认为这些问题的原因是UIScrollViews中嵌入的视图存在于与其外部视图不同的边界系统中。 This is effectively how scrolling works in the first place, think of it as just applying a variable offset to the views it contains.
这实际上是滚动首先如何工作,将其视为仅将变量偏移应用于它包含的视图。 Autolayout doesn't know how to translate between these different coordinate systems so any constraints that bridge across aren't going to be applied the way you expect.
Autolayout不知道如何在这些不同的坐标系之间进行转换,因此任何桥接的约束都不会以您期望的方式应用。
To quote from Erica Sadun's excellent book iOS Auto Layout Demystified (from the section 'Constraints, Hierarchies, and Bounds Systems'): 引用Erica Sadun的优秀书籍iOS Auto Layout Demystified(来自“约束,层次结构和边界系统”一节):
"Be aware of bounds systems. You should not relate a button on some view, for example, with a text field inside a separate collection view. If there's some sort of content view with its own bounds system (such as collection views, scroll views, and table views), don't hop out of that to an entirely different bounds system in another view."
“请注意边界系统。您不应该将某个视图上的按钮与单独的集合视图中的文本字段相关联。如果某种内容视图具有自己的边界系统(例如集合视图,滚动视图) ,和表视图),不要跳到另一个视图中完全不同的边界系统。“
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.