I have a View within a View within a View within a View. I am trying to create a popup view within the deepest nested view that darkens the entire screen behind it, but it only darkens the bounds of the view that it is nested in, which makes sense. How do I override this, though?
Here is the condition clause that triggers the popup:
if isSelect {
GeometryReader { _ in
SelectView()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.padding(.horizontal, 35)
}
.background(
Color.black.opacity(0.65)
.edgesIgnoringSafeArea(.all)
.onTapGesture {
withAnimation {
self.isSelect.toggle()
}
}
)
} // end overlay
CodePudding user response:
Just to make sure that I understand this completely, you effectively have a bunch of nested views, and you want to darken the background of the view that is hosting your lowest level. In other words the view that triggers the background dimming, is all the way at the bottom of the hierarchy, whereas the view just above, should be darkened.
The simplest way is to pass your isSelect
through the parent view, down to the child view and handle it there. It's passed by reference, so any change to it would cause it to be passed up the view hierarchy. For example.
//Some View
var body: some View {
@Binding var value: Bool = false
VStack{
ViewA(someValue: $valueA)
}.opacity(someValue ? 0 : 1)
}
//Child View aka ViewA
@Binding var someValue: Bool
var body: some View {
Button(action: { someValue.toggle() }, label: { Text("Some Button")
}
Notice that in the first view, we create the value, which we want to watch for changes, so it's setup as an Binding
, when it's state changes, the view will be redrawn. The second view, gets the reference to value
from the first view, so it's not created anew, instead it merely looks at the memory pointer for it to know it's the same object.
The concept at play here is called Passing By Reference
whereas there is another type of concept called Passing By Value
, both of which work completely differently.