21

I've a array of items displayed using List in my SwiftUI View. I tired to add a contextMenu to delete individual items in the List. The following is the result.

delteing items from list

The animation is not what is expected. The row blinks before moving the next one. How to set animation.right or something like that so that there is no UI glitch and looks like the default behavior which happens at onDelete.

PS: I can't use onDelete because, in my app, swiping right and left has other functions.

Here is the code.


struct ListDelete: View {
    
    @State var cars = ["Tesla", "Mercedes", "Audi", "Tata", "Jaguar"]
    
    var body: some View {
        List(cars, id: \.self) { car in
            Text(car).contextMenu {
                Button(action: {
                    if let index = self.cars.firstIndex(of: car) {
//                        self.cars.remove(at: index)
                        self.cars.remove(atOffsets: [index])
                    }
                }, label: {
                    HStack {
                        Text("Delete")
                        Spacer()
                        Image(systemName: "trash")
                    }
                })
            }
        }
    }
}

The two approaches used to remove the items from the array, resulted in this same behavior.

1
  • 1
    This is an interesting problem. Consider putting bounty if no one answers this. I tried looking for solutions actually, but to no avail. Commented Feb 23, 2020 at 5:17

3 Answers 3

22

It’s an issue with SwiftUI, hopefully Apple fix it in the next major release. For now you can solve the issue by adding a small delay before actions are performed in your context button action:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.7){
    //delete row
}
Sign up to request clarification or add additional context in comments.

1 Comment

It is a very ugly way to fix it but I found no alternative..
3

It goes from List, unfortunately ListStyle protocol has any public API. The only way I see now, is mimic List with ScrollView

import SwiftUI

struct ContentView: View {

    @State var cars = ["Tesla", "Mercedes", "Audi", "Tata", "Jaguar"]
    var body: some View {
        ScrollView {
            ForEach(cars, id: \.self) { car in
                VStack(alignment: .leading, spacing: 0) {
                    HStack {
                        Text(car).padding()
                        Spacer()
                    }
                    .contextMenu {
                        Button(action: {
                            if let index = self.cars.firstIndex(of: car) {
                                    self.cars.remove(at: index)
                            }
                        }, label: {
                            HStack {
                                Text("Delete")
                                Spacer()
                                Image(systemName: "trash")
                            }
                        })
                    }
                    Divider().padding(.leading)
                }.padding(.bottom, 0) // set -4 to be symetric
            }
        }
    }
}

with the following result

enter image description here

5 Comments

Your answers fits the question I've asked. But in the requirement of the real app I'm building, we've a section header and a title which goes from large to inline as we scroll. When I implement ScrollView instead of a List with the header above the ForEach, then the header also scrolls along with the ForEach, which is not the desired behavior. If I use VStack and put the header and ScrollView inside it, then the title stays the same when we scroll. Anyways to achieve both?
is you "list" part of Form ?
@Imthath you better ask again with simplified snippet which reflect your needs. (I red few seconds before about Section header :-))
no, my list is not part of a Form. I will post a separate question.
@Imthath let me know (put the link here)
-1

It is an issue with contextMenu,The blinks is the white background of list item above contextMenu。So you can solve it by make the contextMenu yourSelf

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.