'SwiftUI overlay dropdown without exceeding bounds of parentView
I want to create a dropdown component in SwiftUI that overlays over other random components but at the same time to not exceed the bounds of the parent view that contains all the components. I have tried 2 versions so far. In the first attempt I created the dropdown within an overlay modifier. But it exceeds the bounds. Here is the code for this:
var body: some View {
HStack(spacing: 8) {
Text("TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST")
.frame(width: preTextWidth, alignment: .leading)
HStack {
Text(optionChosen ? input : "Choose an option")
.fontWeight(.bold)
Image(systemName: expand ? "chevron.up" : "chevron.down")
.resizable()
.frame(width: 14, height: 6)
}
.padding()
.background(isEnabled ? cellColor : .gray)
.cornerRadius(15)
.onTapGesture {
if isEnabled {
self.expand.toggle()
}
}
.overlay(
ZStack{
if expand {
Spacer().frame(height: 30)
VStack(alignment: .center) {
ForEach(dropDownList, id: \.self) { text in
Button(action: {
self.expand.toggle()
optionChosen = true
input = text
onSelectedInput(text)
}) {
Text(text)
.padding(10)
.foregroundColor(Color.black)
}
Divider()
}
}
.background(cellColor)
.cornerRadius(15)
}
}.frame(width: 200).animation(.spring(), value: expand)
, alignment: .topLeading)
}
}`
Here is the 2nd attempt and the problem is that the dropdown doesn't come as an overlay over the other components and pushes them.
var body: some View {
HStack(alignment: .top) {
Text("TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST")
.frame(width: preTextWidth, alignment: .leading)
Spacer()
VStack {
VStack(spacing: 8) {
HStack {
Text(optionChosen ? input : "Choose an option")
.fontWeight(.bold)
Image(systemName: expand ? "chevron.up" : "chevron.down")
.resizable()
.frame(width: 14, height: 6)
}
.background(isEnabled ? .clear : .gray)
.onTapGesture {
if isEnabled {
self.expand.toggle()
}
}
if expand {
ForEach(dropDownList, id: \.self) { text in
Button(action: {
self.expand.toggle()
optionChosen = true
input = text
onSelectedInput(text)
}) {
Text(text)
.padding(10)
}.foregroundColor(.black)
Divider()
}
}
}
.padding()
.background(cellColor)
.cornerRadius(15)
.animation(.spring(), value: expand)
}
}
}
}
Solution 1:[1]
First the design you are trying to mimic is somewhat similar to web/Android. Doing it in iOS way:-
- You can push a view controller containing all your options.
-OR-
- You can have a PickerView with pickerStyle(.wheel) which will Automatically manage its bounds.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Suraj Mirajkar |


