在SwiftUI中展开单个菜单并自动折叠其他菜单

xytpbqjk  于 2022-11-28  发布在  Swift
关注(0)|答案(1)|浏览(127)

我有一个视图,其中有几个可折叠的菜单。为了最大化空间,并且不需要滚动,我希望用户一次展开一个菜单,其他菜单应该自动折叠。
请查看下面的屏幕截图和代码,它们不具有此功能。
屏幕截图#1:“属性信息”菜单最初展开为

屏幕截图#2:“财产信息”和“财务”菜单均已展开。一次只能展开一个菜单,而其他菜单处于折叠状态

第一个

lndjwyie

lndjwyie1#

考虑以下简单方法:
在你的AnalyzeView中创建一个@State变量,名为expandedId,类型为UUID。通过绑定将其共享到你的两个子视图中。在子视图中,当你展开时,将此id设置为存储在你的子视图中的id。在你的子视图中响应此id的更改,如果它们与存储的id不匹配,则将collapsed变量设置为true。

struct Collapsible_main<Content: View>: View {
    @Binding var expandedId: UUID // add this
    
    @State var label: () -> Text
    @State var content: () -> Content
    
    @State private var collapsed: Bool = false
    
    private let id = UUID() // add this
    
    var body: some View {
        VStack {
            Button(
                action: {
                    self.collapsed.toggle()
                    if !self.collapsed{
                        self.expandedId = self.id
                    }
                },
                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)
        }
        .onChange(of: expandedId) { newValue in
            if newValue != self.id{
                self.collapsed = true
            }
        }
    }
}

struct Collapsible_other<Content: View>: View {
    @Binding var expandedId: UUID // add this
    
    @State var label: () -> Text
    @State var content: () -> Content
    
    @State private var collapsed: Bool = true
    
    
    private let id = UUID() // add this
    
    var body: some View {
        VStack {
            Button(
                action: {
                    self.collapsed.toggle()
                    if !self.collapsed{
                        expandedId = self.id
                    }
                },
                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)
        }
        .onChange(of: expandedId) { newValue in
            if newValue != self.id{
                self.collapsed = true
            }
        }
    }
}

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
    
    @State private var expandedId = UUID()
    
    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(
                // pass the id on
                expandedId: $expandedId, 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(
                //pass the id on
                expandedId: $expandedId, 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()
            
        }
        
    }
    
}

相关问题