在同一子视图中将UILabel的边界与姐妹UIView成比例对齐

时间:2015-10-13 04:19:55

标签: ios storyboard autolayout alignment

我有一个静态图像,上面有一个区域,用于显示一些多行文字。就像电子游戏中角色的讲话泡泡一样。我抓住了一个看起来像这样的股票图像:

speech bubble

我在主视图的子视图中设置了一个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看起来像这样:

redlines

我可以将包含imageView的子视图的大小更改为我想要的任何大小,并且imageView保持纵横比较,并且这些红线交叉处的红色框始终是我想要的。

那么为什么我设置UILabel边缘的约束以遵循相同的公式边缘不排列?

似乎当imageView的宽度最大时,左右边缘是正确的但顶部和底部是错误的:

width maxed

如果高度最大,那么顶部和底部都是正确的,但是左边和右边是错误的:

height maxed

那么为什么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)

但我仍然想知道为什么我在故事板中设置的内容不起作用。

1 个答案:

答案 0 :(得分:0)

我想出了一个完全在故事板中的解决方案,它可以让我得到我想要的东西,尽管我相信我原来的问题表明Xcode中存在一个错误。

我注意到,由于Xcode似乎并不尊重我想将speechLabel与姐妹-UI元素imageView对齐,我只是做了UIView我不再调整{ {1}}。

我实施的解决方案是将imageViewimageView放入新的父视图中,我称之为speechLabel。我在aspectFitView上设置的所有约束使其适应方面,我改为imageView

然后我设置aspectFitView的约束,使其大小为imageView:对齐中心x和y,等于宽度和高度。

既然aspectFitView的父级是speechLabel的确切大小,位置和宽高比,我就imageViewspeechLabel设置了比例约束相反,瞧。一切都很美妙。它在我的故事板上看起来是正确的,我不需要添加任何post-viewDidAppear帧校正代码,它在我运行它的任何设备上都能正常工作。

我为所有感兴趣的人更新了sample project (Xcode 6.4)解决方案。