Reputation: 221
I'd like to find out whether my view is currently selected or not. I have a rectangle which represents a card. Once I tap the card, the card should go into the selected state and change properties like the color.
But once I tap somewhere else, the card should not be in that state anymore.
So far, I did not manage to figure this out as I tried with the onTapGesture
property but with that I run into the problem that when I tap outside that card, the card does not change the state to false unless I tap the card again, which makes sense but it seems to be the wrong choice in this case.
import SwiftUI
struct CardView: View {
@State var selected = false
let rectangle = Rectangle()
@State var rectangleColor: Color = .purple
var body: some View {
GeometryReader { g in
self.rectangle
.foregroundColor(self.rectangleColor)
.frame(width: g.size.width / 2, height: g.size.width / 2)
.onTapGesture {
self.selected.toggle()
self.modifyColors()
}
}
}
func modifyColors() {
if selected {
rectangleColor = .red
} else {
rectangleColor = .purple
}
}
}
The selected state is the red color, the unselected one the purple color. So I want that the color becomes red when I tap into the rectangle but not if I tap outside it. It should become purple only again when I tap outside the rectangle but not inside it. Example: Card is purple. I select it and it becomes red. When I then tap it again, it should stay red. It should become only purple (unselected) when I tap somewhere outside the card but not inside it.
View that contains this rectangle:
import SwiftUI
struct ContentView: View {
var body: some View {
CardView()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
It shouldn't matter where the view is actually - I want to know weather the space around that view is tapped. So if it is inside a modal, or the top view on a ZStack, the behavior should be the same.
Upvotes: 5
Views: 3295
Reputation: 14428
The way to achieve this is by having the parent view manage both the selection and the gestures.
The CardView just takes a @Binding to isSelected and changes the colour accordingly:
struct CardView: View {
@Binding var isSelected: Bool
var body: some View {
Rectangle()
.fill(self.isSelected ? Color.red : Color.purple)
.aspectRatio(1.0, contentMode: .fit)
}
}
While the parent manages the @State and updates it using gestures.
struct ContentView: View {
@State var isCardSelected = false
var body: some View {
ZStack {
Color.white
.onTapGesture {
self.isCardSelected = false
}
CardView(isSelected: $isCardSelected)
.onTapGesture {
self.isCardSelected = true
}
}
}
}
Upvotes: 2