【问题标题】:Not able to lay out Subviews on a custom UIView in Swift无法在 Swift 中的自定义 UIView 上布置子视图
【发布时间】:2019-11-02 01:38:33
【问题描述】:

所以我创建了这个自定义容器视图,我正在使用自动布局约束进行布局。

    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() 中,我根据 numberOfSegments 添加 UIViews,这是它​​的代码:

 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 个 UIView,而是得到了 3 个,但是第三个没有正确放置并且超出了父容器。我怎样才能让这些 uiviews 正确对齐。我猜在需要调用setNeedsLayout()layoutIfNeeded() 的地方存在一些问题。请帮忙。

Segment 是一个具有两个属性的结构 - bottomSegment 和 topSegment。两者都是 UIView

您可以看到只有三个 UIView 段是如何出现的。我需要其中的 4 个(numberOfSegments = 4)。我还为right and leftAnchor 提供了父容器常量 8 和 -8。所以所有 4 个段都需要放在这个视图中。正如您在上图中看到的那样,最后一段超出了父容器。

【问题讨论】:

  • 问题在您的 configureSegmentFrame 方法中,使用您的逻辑位置调试器并逐步检查。
  • 这看起来像是 UIStackView 的理想案例 - 你看过了吗?
  • 还没有。让我试试 stackview 看看有没有什么改善
  • @AbuUlHassan 在 vi​​ewDidLayoutSubviews 中发送数据源可以完美地布置视图。但我不想使用 ViewDidLayoutSubviews 发送数据源信息。现在该做什么。
  • 在这种情况下,用户观察者......

标签: ios swift uiview frame subview


【解决方案1】:

问题是

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

被调用太早了。在 self 拥有它的框架之前,你不能做任何事情,直到它拥有它的真实框架。

对于 UIView,那一刻是在第一次调用 layoutSubviews 之后。

【讨论】:

    【解决方案2】:

    尝试拨打addSegmentsonViewDidAppear。如果它有效,则意味着在您的代码中视图仍然没有正确的框架。

    当视图控制器的视图发生变化时,您需要调整视图的框架:

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

    你可能不得不把它做得更干净,但它应该可以工作。

    【讨论】:

    • 明白了。我试过在 viewDidLayoutSubviews 中调用它。但是由于视图控制器在 pageviewcontroller 中,它会影响动画等。但是,我可能想在 viewDidLayoutSubviews() 以外的地方调用 addSegments。这个问题涉及到这个问题:stackoverflow.com/questions/56671161/…
    猜你喜欢
    • 2021-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-12
    相关资源
    最近更新 更多