Reputation: 5303
I recently asked (and got a valid answer) to a question related to this issue.
How do I get my UIViewRepresentable to correctly size for its content?
As I mentioned in the previous post, I want to use the awesome MultiSegmentPicker written by Yonat Sharon in my SwiftUI View.
https://github.com/yonat/MultiSelectSegmentedControl
Implementing the answer showed that I'm not out of the woods, yet.
Notice that the bar is behind the "bottom" text view
In my non-demo view it is completely hidden behind other views - so it's not visible at all.
I understand this is a constraints issue, and Xcode view debugging helpfully confirms:
runtime: Layout Issues: Position is ambiguous for MultiSelectSegmentedControl.
Where do I address this problem? Is it in the UIViewRepresentable which is not behaving as I would expect? Since the package has been around for years, and pure UIKit code does not encounter this issue, I'm pretty sure that the issue is in the UIViewRepresentable code.
In the init for MultiSelectSegmentedControl is the following setup code:
private func setup() {
addConstrainedSubview(borderView, constrain: .top, .bottom, .left, .right)
addConstrainedSubview(stackView, constrain: .top, .bottom)
constrain(stackView, at: .left, to: borderView, diff: 1)
constrain(stackView, at: .right, to: borderView, diff: -1)
clipsToBounds = true
stackView.distribution = .fillEqually
borderWidth = { borderWidth }()
borderRadius = { borderRadius }()
tintColorDidChange()
borderView.isUserInteractionEnabled = false
addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didTap)))
accessibilityIdentifier = "MultiSelectSegmentedControl"
}
In the MultiSegmentPicker: UIViewRepresentable's init I find the following code related to constraints:
public init(
selectedSegmentIndexes: Binding<IndexSet>,
items: [Any],
allowsMultipleSelection: Bool? = nil,
borderWidth: CGFloat? = nil,
borderRadius: CGFloat? = nil,
isVertical: Bool? = nil,
isVerticalSegmentContents: Bool? = nil,
selectedBackgroundColor: UIColor? = nil
) {
_selectedSegmentIndexes = selectedSegmentIndexes
uiView = MultiSelectSegmentedControl(items: items)
uiView.translatesAutoresizingMaskIntoConstraints = false
uiView.allowsMultipleSelection =? allowsMultipleSelection
uiView.borderWidth =? borderWidth
uiView.borderRadius =? borderRadius
uiView.isVertical =? isVertical
uiView.isVerticalSegmentContents =? isVerticalSegmentContents
uiView.selectedBackgroundColor =? selectedBackgroundColor
}
Also, the segment views MultiSelectSegment: UIView use this code:
private func setup() {
addConstrainedSubview(stackView, constrain: .topMargin, .bottomMargin, .leftMargin, .rightMargin)
layoutMargins = UIEdgeInsets(top: 7, left: 7, bottom: 7, right: 7)
stackView.spacing = layoutMargins.left
stackView.isUserInteractionEnabled = false
stackView.alignment = .center
isAccessibilityElement = true
accessibilityTraits = [.button]
accessibilityIdentifier = "MultiSelectSegment"
}
Here is the code that demonstrates the problem shown above:
var body: some View {
VStack(alignment: .center) {
Text("top")
Spacer()
MultiSegmentPicker(
selectedSegmentIndexes: $selectedSegmentIndexes,
items: ["First", "Second", "Third", "Done"]
).fixedSize()
Text("bottom")
}
}
}
What I expected from this code is that the bar with "First", "Second", etc. would be centered on the bottom, not pushed to the trailing edge, and that it would be above not behind the Text View displaying "bottom"
=== EDIT === Here's the view with the spacer removed and the .center alignment removed as well.
It might be helpful to see the difference...
=== EDIT 2 ==
I want to show a little more "unexpected" behavior. Once you think about it, it isn't unexpected at all. The Multiselector was positioned correctly, but hidden by the bigger view. When I added a regular Picker() object after the Multiselector, the multiselector peeks through... But these two pictures explain a lot:
== Edit 3 ==
Yonat has fixed this bug, it works as expected now! (thanks!)
Upvotes: 0
Views: 2030
Reputation: 4608
The problem seemed to be with intrinsicContentSize
. I changed in in version 2.3.3 of the control, and now fixedSize()
works fine.
Upvotes: 1
Reputation: 33
The alignment: .center is centering the leading edge of your picker, remove that from VSTack.
remove the Spacer() and it won't be behind, but since it's set up as a stackView SwiftUI won't automatically position it in relation to other elements.
Upvotes: 0