Получить визуализированные границы представления в viewDidLoad () - PullRequest
0 голосов
/ 16 февраля 2020

Я весь день искал помощи, но не могу найти ответ.

У меня есть подпредставление, в котором я рисую прямоугольник, прямоугольник обрамлен подпредставлением, поэтому мне нужно знать размер подпредставления, отрегулированный autolayout, чтобы правильно его обрамить. Я не могу найти способ сделать это из ViewDidLoad(), чтобы прямоугольник правильно отображался при запуске. Я пробовал следующее:

  1. Использование dayView.setNeedsLayout() с последующим dayView.layoutIfNeeded() перед тем, как я начну рисовать прямоугольник в viewDidLoad(), но проверка с обеих сторон этих утверждений показывает dayView.bounds без изменений.
  2. Рисование вида из viewDidLayoutSubviews(), что работает, но в результате мой прямоугольник рисуется 5 раз, так как viewDidLayoutSubviews() вызывается для каждого подпредставления (у меня их 5), которое перерисовывается (соответствующее подпредставление, содержащее прямоугольник) перерисовывается при вызове 4 из 5) - это, кажется, расточительство ресурсов, наверняка есть лучший способ?
  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)
}

gradient drawing

Ответы [ 2 ]

3 голосов
/ 17 февраля 2020

Пара наблюдений:

  1. Если вы настраиваете frame вида в вашем контроллере вида, правильное место для этого находится в viewDidLayoutSubviews. Да, это называется несколько раз, но, как правило, оно не оказывает заметного влияния на производительность.

    Я бы не советовал ни одну из этих чрезвычайно хрупких техник setNeedsLayout, layoutIfNeeded или DispatchQueue.main.async внутри viewDidLoad. viewDidLayoutSubviews - правильное место, если вы собираетесь сделать это в контроллере вида.

  2. Как правило, если вы делаете собственный чертеж подвида и компоновку подпредставлений, вы делаете это в layoutSubviews вида, а не в каком-либо из методов контроллера вида.

    Аналогично, если вы делаете какую-либо ручную отрисовку, вы поместите это в UIView подкласс (или любой из соответствующих CALayer подклассов), а не контроллер представления.

  3. Даже лучше, чем регулировать кадры вручную, лучше позволить системе автоматической разметки обрабатывать это для Вы, если можете. Если вы обнаружите, что вручную настраиваете frame, то, как правило, шаблоны получше.

    FWIW, вы можете определить ограничения вида контейнера, основываясь на размере (или размере intrinsi c) его подпредставлений ( и установите контент-сопротивление и сопротивление сжатию соответствующих представлений). Мы часто думаем об автоматической компоновке как о нисходящем движке, но он работает в обоих направлениях.

Если вы покажете нам свой «чертежный» код и / или снимок экрана или два, мы, вероятно, можем предложить более конкретный совет.

1 голос
/ 16 февраля 2020

Перейдите к основному потоку в viewDidLoad, и действие Perform решит вашу проблему

         DispatchQueue.main.async { 
                // here you can add anything it will have proper frame
            }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...