Removing initial space from ScrollView in swift UI - ios

I'm having trouble with the initial position of a Scroll View in my iOS app:there's a toolbar and my scroll view is wrapped inside the NavigationView.I would like to remove the spacing between "Testo 1" and the top navigation bar.I've searched on the internet but I've only found something about ScrollViewReader,but actually I need to remove the space when the view loads. Is it possible to remove that space?
In the first image you'll see what happen when I open the app, then what appears when I scroll down
That's my code:
import SwiftUI
struct ProvaScrollView: View {
var body: some View {
NavigationView(){
ScrollView{
Text("Testo 1")
VStack{
CardView(title: "Title", text: "Card Text", colore:.blue)
Spacer(minLength: 10)
Title(testo: "Titolo 2")
Spacer(minLength: 3)
Text("Descrizione ")
.multilineTextAlignment(.center)
dishImage()
}}
.padding().toolbar(){
ToolbarItem(placement:.navigation){
NavigationLink(destination: ListOfRecipes()){
Text("Back")
}
}
ToolbarItem(placement:.principal){
Text("Prova Scroll View")
.font(.system(size: 20))
.fontWeight(.black)
}
}
.ignoresSafeArea(.all, edges: .bottom)
}.navigationBarBackButtonHidden()
}
}
Thanks in advance

Related

SwiftUI ScrollView extra padding when go to another screen with showed keyboard

The default "Keyboard Avoidance" SwiftUI is used.
First GIF
If you put the code in VStack and add another View to it, then the container rises
Second GIF
I don't want to delete Keyboard Avoidance. I need to remove extra spacing
scrollDismissesKeyboard for ScrollView is not an option
minimal iOS version is iOS 16
struct ContentView: View {
#State var text: String = "Bu bu?"
var body: some View {
NavigationStack {
ScrollViewReader { proxy in
VStack {
ScrollView(showsIndicators: false) {
VStack(spacing: 0) {
Spacer()
.frame(height: 500)
TextField("", text: $text)
.padding(.bottom, 70)
.frame(height: 40)
.frame(maxWidth: .infinity)
.background(Color.red)
NavigationLink("Screen 2", destination: {
Text("SwiftUI - Nice to meet you, let's never meet again")
})
}
}
Text("I'm in VSTack after scroll view")
}
}
}
}
}
I looked it up with a hierarchy view, and noticed that a UIInputSetHostView is created with a height of 216
View hierarchy 1
View hierarchy 2
disableAutocorrection not working

SwiftUI - How to prevent keyboard in a sheet to push up my main UI

I'm using sheets (SwiftUI) during an onboarding to let people enter text, however whenever the sheet is dismissed, the elements in the background move, as if the keyboard was pushing them up and down. If the keyboard is not on screen, the elements in the background don't move when the sheet is dismissed. I've tried to use .ignoresSafeArea(.keyboard, edges: .bottom) but it doesn't seem to work.
Any idea regarding how to "fix" the background elements while a sheet with a keyboard is dismissed?
private var welcomeSection5: some View {
ZStack {
VStack {
// This is the part that moves up and down
TellSlideView(text: "And what's your age \(userName) if I may?")
Spacer()
Button(action: {
displaySheet.toggle()
}, label: {
Text("Enter age")
.padding()
.foregroundColor(Color.white)
.frame(maxWidth: .infinity)
.background(Color.MyTheme.Purple)
.cornerRadius(15)
.padding(.horizontal)
.padding(.bottom, 40)
})
}.sheet(isPresented: $displaySheet) {
AddUserAgeView(onboardingState: $onboardingState)
}.ignoresSafeArea(.keyboard, edges: .bottom)
}
}
I had a similar problem once. I can't reproduce your code, but you might try using GeometryRadar like this:
GeometryReader { geometry in
ZStack {
VStack {
// This is the part that moves up and down
}
}
}
.ignoresSafeArea(.keyboard, edges: .bottom)

SwiftUI onTapGuesture not working using offset inside ZStack?

I have a Mapbox map view and a search bar and activate button (HStack) inside a ZStack and using an offset modifier to position them at the top of the screen.
For some reason the offset is preventing the onTapGesture from working for the activate button, if I comment out the offset it will work but will be placed at the bottom of the screen.
I tried adding the offset to each element individually inside the HStack but that did not work...
How can I make the onTapGesture functionality work with offset?
Thank you
struct MapScreen: View {
var body: some View {
NavigationView {
ZStack(alignment: .bottom) {
HStack(spacing: 10) {
SearchBar()
.padding(.leading, 5)
.onTapGesture {
print("search pressed")
}
ActivateButton()
.onTapGesture {
print("activate pressed")
}
}.zIndex(2)
.offset(y: -770)
MapView(locations: $locations)
.edgesIgnoringSafeArea([.top, .bottom])
BottomNavBar().zIndex(1)
.edgesIgnoringSafeArea(.all).offset(y: 35)
}
.navigationViewStyle(StackNavigationViewStyle())
.fullScreenCover(isPresented: $presentSearchView, content: {
SearchView()
})
}
}
}
There's a couple problems here:
.offset(y: -770)
If you're trying to use an offset so large, you shouldn't be using offset at all. offset is usually for fine-tune adjustments and doesn't work great with big values. And also, 770 is hardcoded. What happens when you use another device with a different screen size? Don't hardcode or do calculations yourself — SwiftUI can do it for you!
Instead, use a VStack + Spacer() to push the search bar up.
ZStack(alignment: .bottom) {
VStack { /// here!
HStack(spacing: 10) {
SearchBar()
.padding(.leading, 5)
.onTapGesture {
print("search pressed")
}
ActivateButton()
.onTapGesture {
print("activate pressed")
}
}
Spacer() /// push the `HStack` to the top of the screen
}
.zIndex(2)
MapView(locations: $locations)
.edgesIgnoringSafeArea([.top, .bottom])
BottomNavBar().zIndex(1)
.edgesIgnoringSafeArea(.all).offset(y: 35)
}

SwiftUI iOS 14/15 Can't tap Button underneath Spacer in ScrollView

In SwiftUI, I have a Button that's underneath the Spacer within a ScrollView. The ScrollView steals the tap gesture, so the Button never sees the tap.
So, for example, the button in this example does not work:
struct DoesNotWork: View {
var body: some View {
ZStack {
VStack {
// Button doesn't work
Button("Tap This") {
print("Tapped")
}
Spacer()
}
VStack {
ScrollView {
Spacer()
.frame(height: 150)
Rectangle()
.foregroundColor(.blue)
.frame(height: 150)
Spacer()
}
}
}
}
}
This version -- with everything else the same except no ScrollView -- works fine:
struct ThisWorks: View {
var body: some View {
ZStack {
VStack {
// Button works normally
Button("Tap This") {
print("Tapped")
}
Spacer()
}
VStack {
Spacer()
.frame(height: 150)
Rectangle()
.foregroundColor(.blue)
.frame(height: 150)
Spacer()
}
}
}
}
So that rules out the VStack, ZStack, and the Spacer.
I've tried using .allowsHitTesting(false) on the Spacer that's within the ScrollView, and also tried .disabled(true) (and in combination). Adding .allowsHitTesting(false) to the ScrollView makes the button works but of course breaks the ScrollView.
I also tried setting .foregroundColor(.clear) on the Spacer.
For what it's worth, I'm having the same behavior with both Xcode 13.0 Beta 5 testing with iOS 15.0 beta 7, as well as with Xcode 12.5.1 with iOS 14.7.1.
I'm out of ideas. It seems like it should be the simplest thing in the world, but I can't figure out a way around this.
Any help is greatly appreciated!

Possible to allowsHitTesting on part of view?

I have a button behind a ScrollView, but cannot tap it since it's under it. I have a Spacer at the top of the scroll view that shows the button. I tried putting allowsHitTesting(false) on the Spacer, but this is still not letting it pass underneath the ScrollView.
This is what the `ScrollView looks like, I cannot tap the "Press" button:
This is the code, notice the button is in the ZStack, and the Spacer in the ScrollView has the allowsHitTesting(false):
struct ContentView: View {
#State private var isPresented = false
var body: some View {
ZStack(alignment: .top) {
Button("Press") {
isPresented = true
}
.frame(maxWidth: .infinity, maxHeight: 200)
.background(Color(.label).ignoresSafeArea())
ScrollView {
Spacer()
.frame(height: 200)
.allowsHitTesting(false) // <---- Will not tap thru ScrollView!!
VStack {
Button("Another Press") {
isPresented = true
}
.padding(50)
ForEach((0...50), id: \.self) {
Text("Some text \($0)")
}
}
.frame(maxWidth: .infinity)
.background(Color(.white))
}
}
.navigationBarHidden(true)
.alert(isPresented: $isPresented) {
Alert(title: Text("Button tapped"))
}
}
}
Tapping the button in the background under the Spacer doesn't work. Is there a way to apply the allowsHitTesting(false) to part of the ScrollView that the Spacer occupies? I obviously don't want to apply allowsHitTesting(false) on the entire ScrollView because this is a simplistic example but a real app would have tons of interaction views within the ScrollView. Thanks for any help or insight!

Resources