问题
So I have created this custom container view which I am laying out using autolayout constraint.
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
}
In the view controller, the viewDidLoad()
is this:
setupDataSource()
segmentContainerView = ATCStorySegmentsView()
view.addSubview(segmentContainerView)
configureSegmentContainerView()
segmentContainerView.translatesAutoresizingMaskIntoConstraints = false
segmentContainerView.numberOfSegments = friendStory.count
Now once the data source is setup and I have the friendStory
count, I am assigning it to segmentContainerView.numberofSegments
In segmentContainerview
class this is what is happening:
var numberOfSegments: Int? {
didSet {
addSegments()
}
}
In addSegments()
, I am adding UIViews depending upon the numberOfSegments
this is the code for that:
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
}
**Question and Issue: ** Instead of getting 4 UIViews, I am getting 3, but the third one is not correctly placed and is going outside the parent container. How can I get these uiviews aligned correctly. I am guessing there is some issue with where setNeedsLayout()
and layoutIfNeeded()
needs to be called. Please help.
Segment
is a struct with two properties - bottomSegment and topSegment. Both being UIView
You can see how just three UIView segments appear. I needs to 4 (numberOfSegments
= 4) of these. Also I am giving the parent container constant of 8 and -8 for right and leftAnchor
. so all 4 segments need to be placed within this view. As you can see in the picture above the last segment is going outside of the parent container.
回答1:
Try to call addSegments
at onViewDidAppear
. If it works, it means that in your code the view does not still have the correct frame.
For this to work you need to adapt the frames of the views, when the view controller's view changed:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
guard let numberOfSegments = numberOfSegments else { return }
for i in 0..<numberOfSegments {
configureSegmentFrame(index: i, segmentView: segment)
}
}
You will probably have to do it cleaner, but it should work.
回答2:
The problem is that
let widthOfSegment : CGFloat = (self.frame.width ...
is being called too soon. You cannot do anything in that depends upon self
having its frame until after it has its real frame.
For a UIView, that moment is after layoutSubviews
has been called for the first time.
来源:https://stackoverflow.com/questions/56665550/not-able-to-lay-out-subviews-on-a-custom-uiview-in-swift