Swiftui Pick a Value from a List with Ontap Gesture

SwiftUI: Menu inside list cell with onTapGesture triggers gesture

Alternatively, you can override Menu onTapGesture:

struct ContentView: View {
var body: some View {
List {
HStack {
Text("Cell content")
Spacer()
Menu(content: {
Button(action: {}) {
Text("Menu Item 1")
Image(systemName: "command")
}
Button(action: {}) {
Text("Menu Item 2")
Image(systemName: "option")
}
Button(action: {}) {
Text("Menu Item 3")
Image(systemName: "shift")
}
}) {
Image(systemName: "ellipsis")
.imageScale(.large)
.padding()
}
.onTapGesture {} // override here
}
.contentShape(Rectangle())
.onTapGesture {
print("Cell tapped")
}
}
}
}

Also, there's no need to use .background(Color(.systemBackground)) to tap on spacers. This is not really flexible - what if you want change background color?

You can use contentShape instead:

.contentShape(Rectangle())

List Item with Toggle subview and selection gesture

First, your [ItemDataModel] array should be moved outside the body, so it's not recreated every time:

struct ListView: View {
@State var selected = Set<Int>()
let items = (1...10).map(ItemDataModel.init) // move outside the `body`

var body: some View {
VStack {
Text(String(describing: selected))
List(items) { item in
ListItemView(dataModel: item)
.onTapGesture { if !(selected.remove(item.id) != .none) { selected.insert(item.id) }}
}
}
}
}

Then, make sure that the Toggle in your ListItemView doesn't take all the space (that's the default behaviour) and attach onTapGesture to override the parent's gesture:

struct ListItemView: View {
@ObservedObject var dataModel: ItemDataModel

var body: some View {
HStack {
Text(dataModel.title)
// Text("toggle") // if necessary add Toggle's label as `Text`
Spacer()
Toggle("", isOn: $dataModel.isOn) // use another initialiser
.fixedSize() // limit Toggle's width
.background(Color.red) // debug-only, to see the real frame
.onTapGesture {} // override tap gestures
}
.contentShape(Rectangle()) // make empty space *clickable*
}
}

SwiftUI using ForEach and onTapGesture to update selected element causing crash

Your problem is likely due to the view diffing algorithm having a different outcome if you have the text value present, since that would be a difference in the root view. Since you have two pieces of state that represent the sheet, and you are force unwrapping one of them, you're leaving yourself open to danger.

You should get rid of showingSheet, then use the item binding of sheet instead. Make Cards conform to Identifiable, then rewrite the sheet modifier as:

.sheet(item: $selectedCard) { SpecificCardView(card: $0) } 

This will also reset your selected card to nil when the sheet is dismissed.

Swiftui How can you use on Tap Gesture for entire row in a foreach loop

It only works for the highlighted text because the onTapGesture is on the Text view.

1. Using a HStack()


I would embed the VStack in a HStack and add a Spacer() to fill the entire area, then place the onTapGesture to the HStack, like this:

    ForEach(model) { value in
HStack{
VStack(alignment: .leading) {
HStack {
Text(value.name)
.font(.system(size: 15))
.background(Color.red)
.padding(.trailing, 10.0)
}
HStack {
Text(value.statelong)
.foregroundColor(Color.gray)
.font(.system(size: 13))
Spacer()
}

}
Spacer()
}.contentShape(Rectangle())
.onTapGesture {
isOpen = true
defaults.setValue(value.name, forKey: "location")
}.fullScreenCover(isPresented: $isOpen, content: MainView.init)
}

2. Using a ZStack()

Or you could use a ZStack to make a full view background and place the onTapGesture on the ZStack, add .frame(maxWidth: .infinity) to the ZStack to fill the entire available width, like this:

 ForEach(model) { value in
ZStack {
VStack(alignment: .leading) {
HStack {
Text(value.name)
.font(.system(size: 15))
.background(Color.red)
.padding(.trailing, 10.0)
}
HStack {
Text(value.statelong)
.foregroundColor(Color.gray)
.font(.system(size: 13))
Spacer()
}

}
Spacer()
}.contentShape(Rectangle())
.frame(maxWidth: .infinity)
.onTapGesture {
isOpen = true
defaults.setValue(value.name, forKey: "location")
}.fullScreenCover(isPresented: $isOpen, content: MainView.init)
}

Swift UI @State does get set on the first tap

In iOS 14, in order to get the .sheet to be presented with up-to-date data, you must use sheet(item:) instead of .sheet(isPresented:)

You can see another one of my answers here: https://stackoverflow.com/a/66190152/560942
and
SwiftUI: Switch .sheet on enum, does not work

In your specific case, it's hard to tell since I don't have your UserProfile code, but I suggest that you:

  1. Get rid of your showDetail state variable
  2. Make sure that UserProfile conforms to Identifiable
  3. Change your sheet(isPresented:) to:
.sheet(item: $selectedListener) { listener in 
ListenerDetailView(listener: listener)
}


Related Topics



Leave a reply



Submit