Home > Enterprise >  How to toggle a button when another is clicked
How to toggle a button when another is clicked

Time:06-16

I have a view that generates multiple rows in a list. Each row - I append a button that creates a pop out of sorts over the row. My issue is since the button is being generated separately on each row, when I toggle another button on a different row, the previous button I opened remains open until I click it again.

Is there a way I can have the rows communicate with each other so if another button is clicked, the button previously clicked disappears?

struct RecipeFullListRow: View {
   var body: some View {
                    ZStack{
                        Text("Cheese Omelette")
                            .font(.body)
                  
                        Text("10g 25g 88g")
                            .foregroundColor(.gray)
                            .padding(.top, 80)
                            .padding(.bottom, 10)
                            .padding(.trailing, 10)
                            .frame(height:90)
                        
                        if showRecipeOptions{
                            ReditorPopUp(shown: $showRecipeOptions)
                                    .padding(.top, 20)
                                    .padding(.leading, 15)
                        }
                    }
                        .padding(.top, -10)
                        .padding(5)
                    
                   
                    Button(action: {
                      
                        
                    }){
                        Image(systemName: "slider.horizontal.3")
                            .padding(.top, 10)
                            .foregroundColor(.black)
                            .onTapGesture{
                                showRecipeOptions.toggle()
                            }
                    }
                    .buttonStyle(BorderlessButtonStyle())
                   
   
     
    }
}

**BUTTON ATTACHED TO EACH ROW

struct ReditorPopUp: View {
    @Binding var shown: Bool
    @State var showEditRecipe = false
    
    var body: some View {
        if shown{
            ZStack{
                VStack (alignment: .leading, spacing: 20){
                    HStack(spacing:12){
                        Image(systemName: "pencil")
                            .font(.title2)
                        Button(action:{
                            showEditRecipe.toggle()
                               
                        }){
                            Text("Edit")
                                .foregroundColor(.black)
                        } .buttonStyle(BorderlessButtonStyle())
                        //present editor
                            .fullScreenCover(isPresented: $showEditRecipe){
                                    RecipeEditor()
                                }
                    }
                    HStack(spacing: 12){
                        Image(systemName: "trash")
                            .font(.title2)
                            .foregroundColor(.red)
                        Button(action: {
                            
                        }){
                            Text("Delete")
                                .foregroundColor(.black)
                        } .buttonStyle(BorderlessButtonStyle())
                    }
                }
            }
            
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(Color.white)
            ///art of animation
            .transition(.backslide)
            .animation(.easeInOut(duration: 0.25))
        }
        
    }
}

struct RecipeFullListView: View {
    @Environment(\.dismiss) var dismiss
    @State var listofRecipes: [RecipeListModel] = RecipeList.recipes
    @State private var active = false
  
   
    
    init(){
        UITableView.appearance().backgroundColor = .clear
    }
    
    var body: some View {
        let withIndex = listofRecipes.enumerated().map({ $0 })
        ZStack{
            VStack{
                Text("Recipes")
                    //.padding(.bottom, -20)
                    //.padding(.top, 40)
                    .font(.title2)
               
                List{
                    ForEach(withIndex, id: \.element.name){ index, recipe in
                        RecipeFullListRow(recipe: recipe, recipeName: recipe.name, index: index)
                    }
                }
              
            }//end of VStack
        }
        
    }

}

I have also attached a gif of the issue below

enter image description here

CodePudding user response:

Instead of Bool make it index or row item type, so when button clicked instead of toggle assign current row/item, this will close previous automatically before show current. Of course you need to inject into the view index/item from ForEach level.

1)

    if showRecipeOptions == index {  // index of current row, ...
//    if showRecipeOptions == item { // or item of current row
        ReditorPopUp(shown: $showRecipeOptions)
                .padding(.top, 20)
                .padding(.leading, 15)
    }
  1.   Button(action:{
          showEditRecipe = index    // index of tapped row
    

    // showEditRecipe = index // or item of tapped row

      }){
    

CodePudding user response:

In your data model (ObservableObject) holding data for each row, you could add a variable holding the index of the row being selected for editing with @Published wrapper. Changing it would redraw the list with the edit view for new row.

  • Related