在 viewDidLoad() 中获取视图的渲染边界

Jim*_*rke 0 ios autolayout swift

我一整天都在寻求这方面的帮助,但找不到答案。

我有一个子视图,在其中绘制一个矩形,该矩形由子视图构成,因此我需要知道通过自动布局调整的子视图的大小以正确地构建它。我无法找到一种方法来执行此操作ViewDidLoad(),以便在启动时正确渲染矩形。我已经尝试过以下方法:

  1. 在绘制矩形之前使用dayView.setNeedsLayout()后跟,但检查这些语句的两侧显示 dayView.bounds 不变。dayView.layoutIfNeeded()viewDidLoad()
  2. 从 绘制视图viewDidLayoutSubviews(),它可以工作,但会导致我的矩形被绘制 5 次,就像viewDidLayoutSubviews()为每个重绘的子视图(我有 5 个)所调用的那样(包含矩形的相关子视图在 5 次调用中的 4 次调用时重绘) - 这看起来浪费资源,肯定有更好的方法吗?
  3. 在 内绘制视图两次ViewDidLoad(),希望第一次强制绘制会导致视图调整大小,因此第二次绘制将在第一次绘制后访问新的边界(我知道很绝望,但它仍然不起作用)。

我希望有人能帮帮忙。

func drawGradient(object: UIView, rect: CGRect, slackX: Int, gradWidth: Int, yPos: Int) -> Void {
    // the rectangle width and height set to fit within view with x & y border.

    let gradientView = UIView(frame: rect)
    let gradient = CAGradientLayer()

    gradient.frame = gradientView.frame
    gradient.colors = getDayGradientLocations().gradientCol
    gradient.locations = getDayGradientLocations().gradientLoc
    dayView.layer.addSublayer(gradient)

    let civilDawn = getTimeAsProportionOfDay(time: tides.civilDawn) * Double(rect.height) + Double(yPos)
    let path = UIBezierPath()
    path.move(to: CGPoint(x: slackX, y: Int(civilDawn)))
    path.addLine(to: CGPoint(x: slackX + Int(rect.width), y: Int(civilDawn)))

    let shapeLayer = CAShapeLayer()
    shapeLayer.path = path.cgPath
    shapeLayer.strokeColor = UIColor.red.cgColor
    shapeLayer.lineWidth = CGFloat(2)

    let civilDusk = getTimeAsProportionOfDay(time: tides.civilDusk) * Double(rect.height) + Double(yPos)
    path.move(to: CGPoint(x: slackX, y: Int(civilDusk)))
    path.addLine(to: CGPoint(x: slackX + Int(rect.width), y: Int(civilDusk)))
    shapeLayer.path = path.cgPath
    shapeLayer.strokeColor = UIColor.red.cgColor
    shapeLayer.lineWidth = CGFloat(2)

    object.layer.addSublayer(shapeLayer)

    drawLabel(object: object, rect: rect, slackX: slackX, offset: 15, time: tides.civilDawn)
    drawLabel(object: object, rect: rect, slackX: slackX, offset: -15, time: tides.civilDusk)
}
Run Code Online (Sandbox Code Playgroud)

渐变绘图

Rob*_*Rob 5

一些观察结果:

\n
    \n
  1. 如果您要在视图控制器中调整 view\xe2\x80\x99s frame,则正确的位置是在viewDidLayoutSubviews. 是的,这被调用了很多次,但它通常不会对性能产生任何明显的影响。

    \n

    我不建议使用 、 或 inside 的任何极其setNeedsLayout脆弱layoutIfNeededDispatchQueue.main.async技术viewDidLoadviewDidLayoutSubviews如果您要在视图控制器中执行此操作,那么这是正确的位置。

    \n
  2. \n
  3. 通常,如果进行自定义子视图绘制和子视图布局,您可以在layoutSubviews视图中执行此操作,而不是在任何视图控制器方法中执行此操作。

    \n

    同样,如果您正在进行任何手动绘图,则将其放入子UIView类(或任何相关CALayer子类)中,而不是视图控制器中。

    \n
  4. \n
  5. 更好的是,如果可以的话,最好让自动布局系统为您处理此问题,而不是手动调整框架。如果您发现自己手动调整 a frame,通常有更好的模式。

    \n

    FWIW,您可以根据其子视图的大小(或内在大小)定义容器视图\xe2\x80\x99s 约束(并设置相关视图的内容拥抱和压缩阻力)。我们经常将自动布局视为自上而下的引擎,但它是双向的。

    \n
  6. \n
\n

如果您向我们展示您的 \xe2\x80\x9cdrawing\xe2\x80\x9d 代码和/或一两张屏幕快照,我们可能可以提供更具体的建议。

\n