将 UILabel 的边界与同一子视图中的姐妹 UIView 按比例对齐
Aligning the bounds of a UILabel proportionally to a sister UIView in the same subview
我有一个静态图像,上面有一个区域用于显示一些多行文本。就像电子游戏中角色的对话泡泡。我抓取了一张看起来像这样的库存图片:
我在主视图的子视图内设置了一个 UIImageView 以适应纵横比(参见此 question)。我还在子视图内部设置了一个 UILabel,它将保存多行文本。我希望能够在屏幕上移动子视图并将其设置为任意大小并且仍然让 UIImageView 保持相同的外观并让 UILabel 适合图像的气泡。
我做了一个 sample project 已经设置好了。
我打算将 UILabel 的边界保持在对话气泡区域内的方法是设置与 UIImageView 的中心 x 和 y 成比例的约束。对于我的图像,左边乘数是0.65,右边是1.8,顶部是0.19,底部是0.63。
我写了几个从 UIView 扩展的函数来确认这一点:
/**
Draws a vertical line proportional to the center x of the view.
A `proportional` value of 0 is the left edge, while 2 is the right edge.
:param: proportion The value from the left edge (0.0) to the right edge (2.0)
:param: inColor The color to draw the line in (red by default)
*/
func drawVertLineAtProportion(proportion: CGFloat, inColor: UIColor = UIColor.redColor()) {
let size = self.frame.size
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
let context = UIGraphicsGetCurrentContext()
let x = self.bounds.origin.x + proportion*self.frame.size.width/2
var vertPath = UIBezierPath()
vertPath.lineWidth = size.height/150.0
vertPath.moveToPoint(CGPointMake(x, 0))
vertPath.addLineToPoint(CGPointMake(x, self.frame.size.height))
inColor.setStroke()
vertPath.stroke()
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.addSubview(UIImageView(image: image))
}
和drawHorizLineAtProportion
类似,不过是横线。
我可以通过 运行 viewDidAppear
中的这 4 行来确认我的乘数值是正确的:
imageView.drawVertLineAtProportion(0.65)
imageView.drawVertLineAtProportion(1.8)
imageView.drawHorizLineAtProportion(0.19)
imageView.drawHorizLineAtProportion(0.63)
然后 imageView 看起来像这样:
我可以将包含 imageView 的子视图的大小更改为我想要的任何大小,并且 imageView 保持宽高比,并且那些红线交叉处的红色框始终正是我想要的。
那么,当我设置 UILabel 的边缘约束以遵循相同的公式时,为什么边缘不对齐?
似乎当imageView的宽度最大化时,左右边缘是正确的,但顶部和底部是错误的:
并且如果高度为max,则上下正确,左右错误:
那么 UILabel 边界怎么没有与红线对齐?
编辑以指定我知道有一个运行时修复程序,但我想知道为什么故事板不起作用。
如果我在 viewDidAppear
中添加这些行来修复 UILabel 的框架,它会起作用:
let upperLeft: CGPoint = CGPointMake(imageView.frame.origin.x + 0.65*imageView.frame.size.width/2, imageView.frame.origin.y + 0.19*imageView.frame.size.height/2)
let lowerRight: CGPoint = CGPointMake(imageView.frame.origin.x + 1.8*imageView.frame.size.width/2, imageView.frame.origin.y + 0.63*imageView.frame.size.height/2)
let size: CGSize = CGSizeMake(lowerRight.x - upperLeft.x, lowerRight.y - upperLeft.y)
speechLabel.frame = CGRectMake(upperLeft.x, upperLeft.y, size.width, size.height)
但我还是想知道为什么我在故事板中设置的内容不起作用。
我想出了一个解决方案,完全在情节提要中,这让我得到了我想要的,尽管我相信我最初的问题表明 Xcode 中存在错误。
我注意到由于 Xcode 似乎不尊重我想将 speechLabel
与姐妹 UI 元素 imageView
对齐,我只是做了UI我对齐的视图不再是 imageView
。
我实施的解决方案是将 imageView
和 speechLabel
放入一个新的父视图中,我称之为 aspectFitView
。我在 imageView
上施加的所有限制使其适合纵横比,我在 aspectFitView
上施加。
然后我设置 imageView
的约束,使其大小为 aspectFitView
:对齐中心 x 和 y,宽度和高度相等。
现在 speechLabel
的父级是 imageView
的确切大小、位置和纵横比,我为 speechLabel
和 [= 设置比例约束15=] 相反,瞧。一切都很好。它在我的故事板上看起来是正确的,我不需要添加任何 post-viewDidAppear 帧校正代码,并且它在我 运行 它所在的任何设备上都能完美运行。
我为感兴趣的人更新了 sample project (Xcode 6.4) 解决方案。
我有一个静态图像,上面有一个区域用于显示一些多行文本。就像电子游戏中角色的对话泡泡。我抓取了一张看起来像这样的库存图片:
我在主视图的子视图内设置了一个 UIImageView 以适应纵横比(参见此 question)。我还在子视图内部设置了一个 UILabel,它将保存多行文本。我希望能够在屏幕上移动子视图并将其设置为任意大小并且仍然让 UIImageView 保持相同的外观并让 UILabel 适合图像的气泡。
我做了一个 sample project 已经设置好了。
我打算将 UILabel 的边界保持在对话气泡区域内的方法是设置与 UIImageView 的中心 x 和 y 成比例的约束。对于我的图像,左边乘数是0.65,右边是1.8,顶部是0.19,底部是0.63。
我写了几个从 UIView 扩展的函数来确认这一点:
/**
Draws a vertical line proportional to the center x of the view.
A `proportional` value of 0 is the left edge, while 2 is the right edge.
:param: proportion The value from the left edge (0.0) to the right edge (2.0)
:param: inColor The color to draw the line in (red by default)
*/
func drawVertLineAtProportion(proportion: CGFloat, inColor: UIColor = UIColor.redColor()) {
let size = self.frame.size
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
let context = UIGraphicsGetCurrentContext()
let x = self.bounds.origin.x + proportion*self.frame.size.width/2
var vertPath = UIBezierPath()
vertPath.lineWidth = size.height/150.0
vertPath.moveToPoint(CGPointMake(x, 0))
vertPath.addLineToPoint(CGPointMake(x, self.frame.size.height))
inColor.setStroke()
vertPath.stroke()
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.addSubview(UIImageView(image: image))
}
和drawHorizLineAtProportion
类似,不过是横线。
我可以通过 运行 viewDidAppear
中的这 4 行来确认我的乘数值是正确的:
imageView.drawVertLineAtProportion(0.65)
imageView.drawVertLineAtProportion(1.8)
imageView.drawHorizLineAtProportion(0.19)
imageView.drawHorizLineAtProportion(0.63)
然后 imageView 看起来像这样:
我可以将包含 imageView 的子视图的大小更改为我想要的任何大小,并且 imageView 保持宽高比,并且那些红线交叉处的红色框始终正是我想要的。
那么,当我设置 UILabel 的边缘约束以遵循相同的公式时,为什么边缘不对齐?
似乎当imageView的宽度最大化时,左右边缘是正确的,但顶部和底部是错误的:
并且如果高度为max,则上下正确,左右错误:
那么 UILabel 边界怎么没有与红线对齐?
编辑以指定我知道有一个运行时修复程序,但我想知道为什么故事板不起作用。
如果我在 viewDidAppear
中添加这些行来修复 UILabel 的框架,它会起作用:
let upperLeft: CGPoint = CGPointMake(imageView.frame.origin.x + 0.65*imageView.frame.size.width/2, imageView.frame.origin.y + 0.19*imageView.frame.size.height/2)
let lowerRight: CGPoint = CGPointMake(imageView.frame.origin.x + 1.8*imageView.frame.size.width/2, imageView.frame.origin.y + 0.63*imageView.frame.size.height/2)
let size: CGSize = CGSizeMake(lowerRight.x - upperLeft.x, lowerRight.y - upperLeft.y)
speechLabel.frame = CGRectMake(upperLeft.x, upperLeft.y, size.width, size.height)
但我还是想知道为什么我在故事板中设置的内容不起作用。
我想出了一个解决方案,完全在情节提要中,这让我得到了我想要的,尽管我相信我最初的问题表明 Xcode 中存在错误。
我注意到由于 Xcode 似乎不尊重我想将 speechLabel
与姐妹 UI 元素 imageView
对齐,我只是做了UI我对齐的视图不再是 imageView
。
我实施的解决方案是将 imageView
和 speechLabel
放入一个新的父视图中,我称之为 aspectFitView
。我在 imageView
上施加的所有限制使其适合纵横比,我在 aspectFitView
上施加。
然后我设置 imageView
的约束,使其大小为 aspectFitView
:对齐中心 x 和 y,宽度和高度相等。
现在 speechLabel
的父级是 imageView
的确切大小、位置和纵横比,我为 speechLabel
和 [= 设置比例约束15=] 相反,瞧。一切都很好。它在我的故事板上看起来是正确的,我不需要添加任何 post-viewDidAppear 帧校正代码,并且它在我 运行 它所在的任何设备上都能完美运行。
我为感兴趣的人更新了 sample project (Xcode 6.4) 解决方案。