问题
This post is related to this. After making rows on 3-column-buttons, when 'Delete Button' is hit, the first 3 buttons are not deletable when the 'trash' image is hit. However, the second row buttons( i.e. tag4) can be deleted. Any idea what went wrong here? All buttons should be deletable.
Here's the code
class SomeData: ObservableObject{
@Published var buttonObjects: [ButtonObject] = [ButtonObject(name: "tag1", isSelected: false),
ButtonObject(name: "tag2", isSelected: false), ButtonObject(name: "tag3", isSelected: false), ButtonObject(name: "tag4", isSelected: false)]
}
struct someData3: View {
@Environment(\.editMode) var mode
@ObservedObject var someData = SomeData()
@State var newButtonTitle = ""
@State var isEdit = false
var body: some View {
NavigationView{
// List{ // VStack
VStack{
// Spacer()
VStack(alignment: .leading){//
ForEach(0..<someData.buttonObjects.count/3+1) { row in // create number of rows
HStack{
ForEach(0..<3) { column in // create 3 columns
self.makeView(row: row, column: column)
// makeView2(row: row, column: column, someData: self.someData, isEdit: self.$isEdit)
}
}
}.id(UUID())
}
HStack{
TextField("Enter new button name", text: $newButtonTitle){
let newObject = ButtonObject(name: self.newButtonTitle, isSelected: false)
self.someData.buttonObjects.append(newObject)
self.newButtonTitle = ""
}
}
Spacer()
HStack{
Text("isEdit is ")
Text(String(self.isEdit))
}
}
.navigationBarItems(leading: Button(action: {self.isEdit.toggle()}){Text("Delete Button")},
trailing: EditButton())
}
}
func makeView(row: Int, column: Int) -> some View{
let ind = row * 3 + column
return Group{
if ind<self.someData.buttonObjects.count {
Button(action: {
self.someData.buttonObjects[ind].isSelected = !self.someData.buttonObjects[ind].isSelected
print("Button pressed! buttonKeyName is: \(self.someData.buttonObjects[ind].name) Index is \(ind)")
print("bool is \(self.someData.buttonObjects[ind].isSelected)")
}) {
Text(self.someData.buttonObjects[ind].name)
}
.buttonStyle(GradientBackgroundStyle(isTapped: self.someData.buttonObjects[ind].isSelected))
.overlay(Group {
if self.isEdit {
ZStack {
Button(action: {self.deleteItem(ind: ind)}) {
Image(systemName: "trash")
.foregroundColor(.red).font(.title)
}.padding(.trailing, 3)
.alignmentGuide(.top) { $0[.bottom] }
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing) //topTrailing
}
}
)
.padding(.bottom, 20)
}
else{
EmptyView()
}
}
}
func deleteItem(ind: Int) {
let name = someData.buttonObjects[ind].name
print(" deleting ind \(ind), key: \(name)")
self.someData.buttonObjects.remove(at: ind)
}
}
回答1:
The problem you have may occur because your top button's overlay overlaps with the NavigationView
title bar which will block input for the button.
If you add some background colour to your VStack
you'll see your top buttons' trash buttons are actually outside the VStack:
NavigationView {
VStack {
...
}
.background(Color.red)
}
One of the solutions is to move the trash image closer to the middle of the button by removing this line:
.alignmentGuide(.top) { $0[.bottom] }
Alternatively you can make sure your trash buttons will not overlap with the NavigationView
title bar. As an example you can add a small space above your VStack
to make your trash buttons fit inside:
NavigationView {
VStack {
Spacer()
.frame(height: 10)
VStack {
...
}
}
You can also get the same result with .padding
:
Button(action: { }) {
...
}
.buttonStyle(...)
.overlay(...)
.padding(.top, 20)
来源:https://stackoverflow.com/questions/62392177/tried-to-make-rows-of-3-column-deletable-buttons-but-the-first-row-of-the-butto