繁体   English   中英

动态列表中只有一个按钮处于活动状态 | SwiftUI

[英]Only have one button active in dynamic list | SwiftUI

我有一个从 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)
        }
    }
}

这应该导致: 代码结果

我唯一的问题是所有按钮都可以同时激活。 go 如何在点击按钮时禁用按钮的 rest?

我需要用户只能打开显示为“X Close”的按钮

我想在激活被点击的按钮之前循环通过其他按钮以编程方式停用它们,但我不知道如何

代码有问题

您可以跟踪父视图中激活的按钮。

如果每个按钮都有某种唯一标识符,则可以在包含活动标识符的父视图中创建一个变量。

您可以将该变量作为绑定传递到按钮视图中,并根据它更改视图外观。

这样一来,始终只有一个活动按钮。 单击按钮时,您可以使用此按钮的唯一标识符在按钮视图中设置绑定变量的值,其他视图会自动更改。

在 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 中,您可以使用它来获取值并相应地设置 styles:

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

你可以在点击按钮时设置它:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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