swift 动态列表中只有一个按钮处于活动状态|快速用户界面

58wvjzkj  于 2022-12-10  发布在  Swift
关注(0)|答案(1)|浏览(161)

我有一个从ForEach循环生成的列表:

struct TrainingList: View {
    
    @EnvironmentObject var trainingVM: TrainingViewModel
    
    var body: some View {
        VStack(alignment: .leading) {
            Text("Your training sessions")
                .font(.system(size: 35, weight: .semibold, design: .default))
                .padding(.all, 10)
                .foregroundColor(.white)
            Divider()
            ScrollView{
                if(trainingVM.loading){
                    ProgressView("Loading training session").progressViewStyle(CircularProgressViewStyle(tint: .blue))
                }
                LazyVStack {
                    ForEach(trainingVM.trainingList) { training in
                        TrainingCell(training: training)
                    }
                }
            }
            Spacer()
        }
        .background {
            Rectangle()
                .fill(Color(.sRGB, red: 41/255, green: 41/255, blue: 41/255))
                .cornerRadius(10, corners: [.topRight, .bottomRight])
                .shadow(color: .black.opacity(1), radius: 8, x: 6, y: 0)
        }
        .frame(width: 650)
        .zIndex(.infinity)
    }
}

每个TrainingCell都有一个按钮,可在其侧面打开一个额外的面板。为了指示面板打开了哪一行,按钮将更改其样式:

struct TrainingCell: View {
    
    @EnvironmentObject var trainingVM: TrainingViewModel
    @State var showEvents = false
    
    let training: Training

    var body: some View {
        HStack(spacing: 0) {
            ZStack(alignment: .top) {
                RoundedRectangle(cornerRadius: 10, style: .continuous)
                    .fill(Color(.sRGB, red: 41/255, green: 41/255, blue: 41/255))
                VStack {
                    HStack(spacing: 10) {
                        VStack(alignment: .leading, spacing: 5) {
                            HStack{
                                Text(training.readableDate, style: .date)
                                    .font(.system(size: 25, weight: .semibold, design: .default))
                                    .foregroundColor(.white)
                                Text(" | ")
                                Text(training.readableDate, style: .time)
                                    .font(.system(size: 25, weight: .semibold, design: .default))
                                    .foregroundColor(.white)
                            }
                            VStack(alignment: .leading,spacing: 5){
                                HStack {
                                    HStack(spacing: 5) {
                                        Image(systemName: "person.text.rectangle.fill")
                                            .foregroundColor(Color(.sRGB, red: 10/255, green: 90/255, blue: 254/255))
                                        Text(training.instructor.fullName)
                                            .foregroundColor(.white)
                                    }
                                }
                                HStack{
                                    ForEach(training.students){ student in
                                        HStack(spacing: 5) {
                                            Image(systemName: "person")
                                                .imageScale(.medium)
                                                .foregroundColor(Color(.sRGB, red: 10/255, green: 90/255, blue: 254/255))
                                            Text(student.fullName_shortenedFirstName)
                                                .foregroundColor(.white)
                                        }
                                    }
                                }
                            }
                            .font(.system(size: 20, weight: .regular, design: .default))
                            .foregroundColor(.primary)
                        }
                        .frame(maxHeight: .infinity, alignment: .center)
                        .clipped()
                        Spacer()
                        View_Close_Button(showEvents: $showEvents)
                        
                    }
                    .frame(maxWidth: .infinity, maxHeight: 80, alignment: .top)
                    .padding(.all)
                    .background {
                        RoundedRectangle(cornerRadius: 0, style: .continuous)
                            .fill(Color(.sRGB, red: 41/255, green: 44/255, blue: 49/255))
                            .shadow(color: .black.opacity(1), radius: 5, x: 0, y: 5)
                    }
                }
            }
        }
    }
}

按钮代码:

struct View_Close_Button: View {
    
    @EnvironmentObject var trainingVM: TrainingViewModel
    @Binding var showEvents: Bool
    
    var body: some View {
        HStack
        {
            Image(systemName: showEvents ? "xmark" : "eye")
                .imageScale(.large)
                .padding(.horizontal, 5)
                .font(.system(size: 17, weight: .regular, design: .default))
            Text(showEvents ? "Close" : "View")
                .padding(.all, 10)
                .font(.system(size: 25, weight: .regular, design: .default))
                .multilineTextAlignment(.leading)
        }
        .onTapGesture {
            withAnimation(.easeIn(duration: 0.3)) {
                showEvents.toggle()
                if(showEvents) {
                    trainingVM.showingEvents = true
                }else{
                    trainingVM.showingEvents = false
                }
            }
        }
        .foregroundColor(.white)
        .background {
            Capsule(style: .continuous)
                .foregroundColor(showEvents ? Color(.sRGB, red: 253/255, green: 77/255, blue: 77/255) : Color(.sRGB, red: 10/255, green: 90/255, blue: 254/255))
                .clipped()
                .frame(maxWidth: 180)
        }
    }
}

结果应该是:

我唯一的问题是所有的按钮都可以同时激活。当一个按钮被点击时,我如何去禁用其余的按钮呢?
我需要用户只能将其中一个按钮显示为“X关闭”
我想过在激活一个被点击的按钮之前,通过其他按钮的循环来取消激活它们,但我不知道如何去做

eufgjt7s

eufgjt7s1#

您可以在父视图中跟踪激活的按钮。
如果每个按钮都有某种唯一标识符,则可以在包含活动标识符的父视图中创建一个变量。
您可以将该变量作为绑定传递到按钮视图中,并根据该绑定更改视图外观。
这样,始终只有一个活动按钮。当单击按钮时,您可以使用该按钮的唯一标识符设置按钮视图中绑定变量的值,其他视图将自动更改。
在TrainingList上,您可以使用活动选项卡定义变量:

@State var activeTab: Int = 0

在TrainingCell上,您可以将此变量添加为绑定。

@Binding var activeTab: Int

然后你就这样传过去:

TrainingCell(training: training, activeTab: $activeTab)

然后,在View_Close_Button上,您可以添加两个变量:

@Binding var activeTab: Int
@State var training: Training

并在TrainingCell上这样传递它:

View_Close_Button(showEvents: $showEvents, activeTab: $activeTab, training: training)

在View_Close_Button中,您可以使用此选项获取值并相应地设置样式:

Image(systemName: activeTab == training.id ? "xmark" : "eye")
Text(activeTab == training.id ? "Close" : "View")

您可以设置它何时按下按钮:

.onTapGesture {
    withAnimation(.easeIn(duration: 0.3) {
        activeTab = training.id
    }
}

相关问题