SwiftUI - disclosure group expanding behaviour - keep top item static

1.3k views Asked by At

I'm trying to create a drop down menu using swift UI. I'm actually implementing this into a UIKit project.

The basic functionality I am going for should be that the user clicks on a label with a certain data unit on it and a list expands with other units of measure that can be selected.

Here is my SwiftUI code:

import SwiftUI

@available(iOS 14.0.0, *)
struct DataUnitDropDown: View {
    var units = ["ltr", "usg", "impg"]
    
    @State private var selectedDataUnit = 0
    @State private var isExpanded = false
    
    var body: some View {
        VStack(alignment: .leading, spacing: 15) {
            DisclosureGroup(units[selectedDataUnit], isExpanded: $isExpanded) {
                VStack {
                    ForEach(0 ..< units.count, id: \.self) { index in
                        Text("\(units[index])")
                            .font(.title3)
                            .padding(.all)
                            .onTapGesture {
                                self.selectedDataUnit = index
                                withAnimation {
                                    self.isExpanded.toggle()
                                }
                            }
                        
                    }
                }
            }
        }
    }
}

So I have a couple of questions here. Firstly, ideally I wanted to place this into an existing horizontal UIStackView. However, the issue I have is that obviously once the dropdown expands, it increases the height of the stack, which is not what I want. Here is a screen shot of the component (see 'ltr'):

enter image description here

When expanded in the stackView:

enter image description here

So I reluctantly placed it in the main view adding some autolayout constraints:

    if #available(iOS 14.0.0, *) {
        let controller = UIHostingController(rootView: DataUnitDropDown())
        controller.view.translatesAutoresizingMaskIntoConstraints = false
        addSubview(controller.view)
        controller.view.leadingAnchor.constraint(equalTo: refuelInfoView.actualUpliftVolume.trailingAnchor).isActive = true
        controller.view.centerYAnchor.constraint(equalTo: refuelInfoView.actualUpliftVolume.centerYAnchor).isActive = true
    }

But now when I expand, the whole menu shifts up:

enter image description here

Clearly not what I am looking for.

So I suppose my question is 2-fold:

1- Is there any way I can incorporate this element into an existing stack view without the stack increasing in height when the dropdown is expanded? (I guess not!)

2- If I have to add this to the main view rather than the stack, how can I stop the entire menu shifting up when it expands?

Update:

I have amended the code as follows:

 if #available(iOS 14.0.0, *) {
        let controller = UIHostingController(rootView: DataUnitDropDown())
        controller.view.translatesAutoresizingMaskIntoConstraints = false
        controller.view.clipsToBounds = false
        controller.view.heightAnchor.constraint(equalToConstant: 22).isActive = true
        controller.view.topAnchor.constraint(equalTo: topAnchor).isActive = true
        stackSubviews = [inputField, controller.view]
    }

Now, without the topAnchor constraint this works perfectly, but I do need this constraint. But I get an error due to the views. not being in the same hierarchy

1

There are 1 answers

3
Asperi On

I assume instead of

controller.view.centerYAnchor.constraint(equalTo: 
       refuelInfoView.actualUpliftVolume.centerYAnchor).isActive = true

you need

controller.view.topAnchor.constraint(equalTo: 
       refuelInfoView.actualUpliftVolume.bottomAnchor).isActive = true