简体   繁体   中英

UIViewRepresentable hidden behind SwiftUI View

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!)

在此处输入图像描述

The problem seemed to be with intrinsicContentSize . I changed in in version 2.3.3 of the control, and now fixedSize() works fine.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM