I have a view with several collapsible menus. In order to maximize space and not need to scroll, I would like the user to expand one menu at a time and the other menus should automatically collapse.
Please see screenshots and code below that does not have this functionality.
Screenshot #1: Property Information menu initially expanded

Screenshot #2: Both Property Information and Financials menus are expanded. Only one menu should be expanded at a time while others are collapsed

// AnalyzeViewModel.swift
import SwiftUI
struct AnalyzeView: View {
@State var listingValue: Double = 200000
@State var unitsValue: Double = 2
@State var sqftValue: Double = 3000
@State var downPaymentValue: Double = 100000
@State var loanValue: Double = 10000
@State var pmiValue: Double = 700
@State var interestValue: Double = 0.02
@State var closingValue: Double = 14000
var body: some View {
VStack {
ZStack() {
Image("analyze_property")
.resizable()
// .aspectRatio(contentMode: .fit)
.scaledToFit()
RoundedRectangle(cornerRadius: 30, style: .continuous)
.fill(.blue)
.opacity(0.8)
.frame(width: 300, height: 170)
VStack {
Image("gauge")
Text("Analyze")
.foregroundColor(.white)
.font(
.largeTitle
.weight(.bold)
)
Text("Return On Investment")
.foregroundColor(.white)
}
}
Collapsible_main(
label: { Text("Property Information").font(.largeTitle) },
content: {
VStack(spacing: 20) {
Group {
Text("Enter your property info below. The more data you provide the better we can analyze.").frame(maxWidth: .infinity, alignment: .leading).fixedSize(horizontal: false, vertical: true)
}
Text("Listing Price")
Slider(value: $listingValue, in: 0...10000000, step: 1){
} minimumValueLabel: {Text("0")} maximumValueLabel: {Text("$10M")} .background(Color.gray.brightness(0.4)).padding(.trailing, 50).padding(.leading, 50)
//Text("\(listingValue, specifier: "%.0f")")
Text("Total Units")
Slider(value: $unitsValue, in: 0...20, step: 1){
} minimumValueLabel: {Text("0")} maximumValueLabel: {Text("20")}.background(Color.gray.brightness(0.4)).padding(.trailing, 50).padding(.leading, 50)
//Text("\(unitsValue, specifier: "%.0f")")
Text("Square Feet")
Slider(value: $sqftValue, in: 0...15000, step: 1){
} minimumValueLabel: {Text("0")} maximumValueLabel: {Text("15K")}.background(Color.gray.brightness(0.4)).padding(.trailing, 50).padding(.leading, 50)
//Text("\(sqftValue, specifier: "%.0f")")
}
}
)
Collapsible_other(
label: { Text("Financials").font(.largeTitle) },
content: {
VStack {
Text("Enter your financial data below.")
Group {
Text("Down Payment")
Slider(value: $downPaymentValue, in: 0...10000000, step: 1).padding(.trailing, 50).padding(.leading, 50)
Text("\(downPaymentValue, specifier: "%.0f")")
}
Group {
Text("Loan Amount")
Slider(value: $loanValue, in: 0...10000000, step: 1).padding(.trailing, 50).padding(.leading, 50)
Text("\(loanValue, specifier: "%.0f")")
}
Group {
Text("PMI")
Slider(value: $pmiValue, in: 0...5000, step: 1).padding(.trailing, 50).padding(.leading, 50)
Text("\(pmiValue, specifier: "%.0f")")
}
Group {
Text("Interest Rate")
Slider(value: $interestValue, in: 0...1, step: 0.01).padding(.trailing, 50).padding(.leading, 50)
Text("\(interestValue, specifier: "%.0f")")
}
Group {
Text("Closing Cost/Fees")
Slider(value: $closingValue, in: 0...30000, step: 1).padding(.trailing, 50).padding(.leading, 50)
Text("\(closingValue, specifier: "%.0f")")
}
}
}
)
Spacer()
}
}
}
struct AnalyzeView_Previews: PreviewProvider {
static var previews: some View {
AnalyzeView()
}
}
// CollapsibleViewModel.swift
import SwiftUI
struct Collapsible_main<Content: View>: View {
@State var label: () -> Text
@State var content: () -> Content
@State private var collapsed: Bool = false
var body: some View {
VStack {
Button(
action: { self.collapsed.toggle() },
label: {
HStack {
self.label()
Spacer()
Image(systemName: self.collapsed ? "chevron.down" : "chevron.up")
}
.padding(.bottom, 1)
.background(Color.white.opacity(0.01))
}
)
.buttonStyle(PlainButtonStyle())
VStack {
self.content()
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: collapsed ? 0 : .none)
.clipped()
// .animation(.easeOut)
.transition(.slide)
}
}
}
struct Collapsible_other<Content: View>: View {
@State var label: () -> Text
@State var content: () -> Content
@State private var collapsed: Bool = true
var body: some View {
VStack {
Button(
action: { self.collapsed.toggle() },
label: {
HStack {
self.label()
Spacer()
Image(systemName: self.collapsed ? "chevron.down" : "chevron.up")
}
.padding(.bottom, 1)
.background(Color.white.opacity(0.01))
}
)
.buttonStyle(PlainButtonStyle())
VStack {
self.content()
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: collapsed ? 0 : .none)
.clipped()
// .animation(.easeOut)
.transition(.slide)
}
}
}