Не удается выложить подвиды на пользовательский UIView в Swift - PullRequest
0 голосов
/ 19 июня 2019

Итак, я создал этот пользовательский контейнерный вид, который я размечал, используя ограничение autolayout.

    func configureSegmentContainerView() {
    segmentContainerView.topAnchor.constraint(equalTo: view.topAnchor, constant: 40).isActive = true
    segmentContainerView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8).isActive = true
    segmentContainerView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8).isActive = true
    segmentContainerView.heightAnchor.constraint(equalToConstant: 3).isActive = true 
    }

В контроллере вида, viewDidLoad() это:

    setupDataSource()
    segmentContainerView = ATCStorySegmentsView()
    view.addSubview(segmentContainerView)
    configureSegmentContainerView()
    segmentContainerView.translatesAutoresizingMaskIntoConstraints = false
    segmentContainerView.numberOfSegments = friendStory.count

Теперь, когда источник данных настроен и у меня есть счет friendStory, я присваиваю его segmentContainerView.numberofSegments

В segmentContainerview классе это то, что происходит:

    var numberOfSegments: Int? {
    didSet {
        addSegments()
    } 
  }

В addSegments() я добавляю UIViews в зависимости от n umberOfSegments, это код для этого:

 private func addSegments() {
    guard let numberOfSegments = numberOfSegments else { return }
    layoutIfNeeded()
    setNeedsLayout()
    for i in 0..<numberOfSegments {
        let segment = Segment()
        addSubview(segment.bottomSegment)
        addSubview(segment.topSegment)
        configureSegmentFrame(index: i, segmentView: segment)
        segmentsArray.append(segment)
    }
}

private func configureSegmentFrame(index: Int, segmentView: Segment) {
    guard let numberOfSegments = numberOfSegments else { return }
    let widthOfSegment : CGFloat = (self.frame.width - (padding * CGFloat(numberOfSegments - 1))) / CGFloat(numberOfSegments)

    let i = CGFloat(index)

    let segmentFrame = CGRect(x: i * (widthOfSegment + padding), y: 0, width: widthOfSegment, height: self.frame.height)
    segmentView.bottomSegment.frame = segmentFrame
    segmentView.topSegment.frame = segmentFrame
    segmentView.topSegment.frame.size.width = 0
}

** Вопрос и проблема: ** Вместо того, чтобы получать 4 UIViews, я получаю 3, но третий размещен неправильно и выходит за пределы родительского контейнера.Как я могу выровнять эти uiviews правильно.Я предполагаю, что есть некоторая проблема с тем, где setNeedsLayout() и layoutIfNeeded() должны быть вызваны.Пожалуйста помоги.

Segment - это структура с двумя свойствами - bottomSegment и topSegment.Оба UIView

enter image description here

Вы можете видеть, как появляются только три сегмента UIView.Мне нужно 4 (numberOfSegments = 4) из них.Также я даю константе родительского контейнера 8 и -8 для right and leftAnchor.поэтому все 4 сегмента должны быть размещены в этом представлении.Как видно на рисунке выше, последний сегмент выходит за пределы родительского контейнера.

Ответы [ 2 ]

0 голосов
/ 19 июня 2019

Проблема в том, что

let widthOfSegment : CGFloat = (self.frame.width ...

вызывается слишком рано . Вы не можете делать ничего, что зависит от self, имеющего свой фрейм, до тех пор, пока у не будет его реального фрейма.

Для UIView этот момент наступает после того, как layoutSubviews был вызван впервые.

0 голосов
/ 19 июня 2019

Попробуйте позвонить addSegments на onViewDidAppear.Если это работает, это означает, что в вашем коде у представления все еще нет правильного фрейма.

Чтобы это работало, вам нужно адаптировать кадры видов, когда вид контроллера контроллера изменился:

override func viewDidLayoutSubviews() {
     super.viewDidLayoutSubviews()
     guard let numberOfSegments = numberOfSegments else { return }
     for i in 0..<numberOfSegments {
        configureSegmentFrame(index: i, segmentView: segment)
    }
}

Возможно, вам придется сделать это чище, но это должно сработать.

...