Main Content View:
struct ContentView: View {
@State var editing: Bool = false
@State var inputText: String = ""
@State var vOffset: CGFloat = 0
@State var hOffset: CGFloat = 0
@State private var activeField: Int = 0
var body: some View {
GeometryReader { geometry in
ScrollView {
ZStack(alignment: .top) {
if activeField == 1 {
SuggestionTextFieldMenu(editing: $editing, text: $inputText)
.zIndex(1)
.offset(y: geometry.size.height * 0.57 - 70)
}
TextField("Placeholder", text: $inputText, onEditingChanged: { edit in
self.editing = edit
self.activeField = 1
})
.padding(.horizontal, 10)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 50, alignment: .center)
.background(Color.init(red: 0.98, green: 0.98, blue: 0.98))
.cornerRadius(14)
.shadow(radius: 4)
.padding(.horizontal, 20)
.offset(y: geometry.size.height * 0.5 - 70)
if activeField == 2 {
SuggestionTextFieldMenu(editing: $editing, text: $inputText)
.zIndex(1)
.offset(y: geometry.size.height * 0.5)
}
TextField("Placeholder", text: $inputText, onEditingChanged: { edit in
self.editing = edit
self.activeField = 2
})
.padding(.horizontal, 10)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 50, alignment: .center)
.background(Color.init(red: 0.98, green: 0.98, blue: 0.98))
.cornerRadius(14)
.shadow(radius: 4)
.padding(.horizontal, 20)
.offset(y: geometry.size.height * 0.5)
}
}
}
}
}
import SwiftUI
public struct SuggestionTextFieldMenu: View {
@State var names: [String] = ["Apple","Peach","Orange","Banana", "Melon", "Watermelon","Mandarin","Mulberries","Lemon","Lime","Loquat","Longan","Lychee","Grape","Pear","Kiwi","Mango"]
@Binding var editing: Bool
@Binding var inputText: String
private var filteredTexts: Binding<[String]> { Binding (
get: {
return inputText.isEmpty ? names : names.filter { $0.contains(inputText) }
},
set: { _ in })
}
public init(editing: Binding<Bool>, text: Binding<String>) {
self._editing = editing
self._inputText = text
}
public init(editing: Binding<Bool>, text: Binding<String>, verticalOffset: CGFloat, horizontalOffset: CGFloat) {
self._editing = editing
self._inputText = text
}
public var body: some View {
ScrollView {
LazyVStack(spacing: 0) {
ForEach(filteredTexts.wrappedValue, id: \.self) { textSearched in
Text(textSearched)
.padding(.horizontal, 25)
.padding(.vertical, 25)
.frame(minWidth: 0,
maxWidth: .infinity,
minHeight: 0,
maxHeight: 50,
alignment: .leading)
.contentShape(Rectangle())
.onTapGesture(perform: {
inputText = textSearched
editing = false
self.endTextEditing()
})
Divider()
.padding(.horizontal, 10)
}
}
}.background(Color.white)
.cornerRadius(15)
.foregroundColor(Color(.black))
.ignoresSafeArea()
.frame(maxWidth: .infinity,
minHeight: 0,
maxHeight: 50 * CGFloat( (filteredTexts.wrappedValue.count > 3 ? 3: filteredTexts.wrappedValue.count)))
.shadow(radius: 4)
.padding(.horizontal, 25)
.isHidden(!editing, remove: !editing)
}
}
import SwiftUI
public extension View {
@ViewBuilder func isHidden(_ hidden: Bool, remove: Bool = false) -> some View {
if hidden {
if !remove {
self.hidden()
}
} else {
self
}
}
func endTextEditing() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder),
to: nil, from: nil, for: nil)
}
}
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
public struct StatefulPreviewWrapper<Value, Content: View>: View {
@State var value: Value
var content: (Binding<Value>) -> Content
public var body: some View {
content($value)
}
public init(_ value: Value, content: @escaping (Binding<Value>) -> Content) {
self._value = State(wrappedValue: value)
self.content = content
}
}
I tired to use vstack but that push the elements downwards when dropdown appear. I cannot use Overlay because that not supported in IOS 14.0. I change the position of ScrollView does change any thing. right now i cant even tap on my textfields.I want to display dropdown menu right under the textField when i click on textField and dropDown Menu should above the View and doesn't change the position of other view inside the body.
As mentioned in a comment, you can use overlays in iOS 14, but the syntax is a little different. However, since a suggestion menu is taller than the
TextField
it is shown against, it is not a bad idea to use aZStack
.The big change I would suggest is not to use offset for layout. Instead, use padding.
It seems that you were using a
GeometryReader
to define the position of the views based on a fraction of the total display height. This is probably not a very reliable way to get a consistent layout across different sizes of display. But if you really want to do it this way, you could apply padding to theScrollView
based on the excess height.Here is an updated version of your
ContentView
body. The suggestion layers appear below the other layers, this way there is no need to apply.zIndex
. Padding is used to position the views relative to the top of theZStack
. I have left out theGeometryReader
since I didn't see that it was serving any useful purpose.