SwiftUI View scrolls horizontal and vertical as well, instead of scrolling only vertically - swift

I am building an app as a learning project. I ran into a problem, where one of my tabs scrolls vertically and horizontally for no reason.
There is no content outside the safe-area, and i can´t think of a reason for it to be scrolling sideways.
I already tried different things, replacing the GeometryReader with a VStack, specifying that i want it to be a vertical ScrollView. Adding .clipped to the end of the View as well as removing or replacing several other views
But nothing worked.
About the project:
The View is wrapped in a TabView and a NavigationView. All of the other tabs were wrapped the same way, and one also uses a ScrollView, yet does not have this problem.
The main Code:
struct InformationView: View {
#EnvironmentObject var model: ViewModel
var radialColor1 = Color.init(red: 225/255, green: 210/255, blue: 164/255)
var radialColor2 = Color.init(red: 233/255, green: 222/255, blue: 188/255)
var isShowingWarning = true
var body: some View {
GeometryReader { geo in
ScrollView(.vertical) {
VStack(alignment: .leading) {
Text("Here is a Text")
.padding(.vertical)
// W-fragen Stack
W_FragenCardView()
Text("Here is another Text")
.padding(.vertical)
Text("Kontakt:")
.font(.title3)
.bold()
ContactView()
}
.padding(.horizontal)
if isShowingWarning {
ZStack {
Rectangle()
.foregroundColor(Color.customRed())
Text("Here is a third Text")
.minimumScaleFactor(0.1)
.lineLimit(10)
.padding()
}
.frame(height: geo.size.height/5)
// .frame(height: 100)
}
Text("Current Theme: \(model.themes[1]!)")
}
}
.navigationBarTitle("Informationen", displayMode: .automatic)
}
}
This is were its wrapped:
struct ContentView: View {
#EnvironmentObject var model: ViewModel
var body: some View {
TabView {
NavigationView {
AnmeldungsView()
}
.tabItem {
Image(systemName: "square.and.pencil")
Text("Anmelden")
}
NavigationView {
FotosView()
}
.tabItem {
Image(systemName: "photo.fill.on.rectangle.fill")
Text("Fotos")
}
NavigationView {
InformationView()
}
.tabItem {
Image(systemName: "info.circle")
Text("Informationen")
}
}
}
}
And here an Image of how it looks when scrolling.
I hope this is sufficent to understand my problem. Any help or ideas are greatly appreciated.
P.S.: I´m new to stack overflow, so if a violated any rules please tell me :)

You should write an array([.horizontal, .vertical]) in ScrollView instead of .vertical.
change your code to this:
GeometryReader { geo in
ScrollView([.horizontal, .vertical]) {
VStack(alignment: .leading) {
Text("Here is a Text")
.padding(.vertical)
W_FragenCardView()
Text("Here is another Text")
.padding(.vertical)
Text("Kontakt:")
.font(.title3)
.bold()
ContactView()
}
.padding(.horizontal)
if isShowingWarning {
ZStack {
Rectangle()
.foregroundColor(Color.red)
Text("Here is a third Text")
.minimumScaleFactor(0.1)
.lineLimit(10)
.padding()
}
.frame(height: geo.size.height/5)
// .frame(height: 100)
}
}
And I hope it will works :)

It was a problem between geo.size.height/5 and the navigationBarTitle being on displayMode: .automatic.
This resulted in the available height changing and somehow bugged out. Either changing displayMode: to .inline or .large, or you replace the geo.size.height/5 w/ a hardcoded Int, i used 150.

Related

Gab being caused by unknown element in swift design

Ok I have tried previous suggestions of just placing it in another vstack but still my view is showing the rectangle at the mid of the screen is their any reason why, also the edges have no padding around them making it edge to edge which I don't want?
struct ProfileView : View
{
var body: some View {
GeometryReader{ geo in
VStack {
VStack(alignment: .trailing, spacing: 10) {
RoundedRectangle(cornerRadius: 20)
.stroke(Color.primary, lineWidth: 2)
.frame(width: geo.size.width, height: 200)
.padding(.horizontal)
}.frame(width: geo.size.width, height: geo.size.height) // <<=== Here }
}
}
}
My Views are being injected into the content area via this page
struct ContentView: View {
var body: some View {
GeometryReader { geometry in
TabView{
HomeView().tabItem {
Image(systemName: "house")
Text("Home")
}
ProfileView()
.tabItem {
Image(systemName: "person.circle.fill")
Text("Profile")
}
ZStack {
StatsView()
.tabItem {
Image(systemName: "murry").renderingMode(.original).padding()
Text("Plus")
}
}
StatsView()
.tabItem {
Image(systemName: "dumbbell.fill").renderingMode(.original).padding()
Text("Stats")
}
StatsView()
.tabItem {
Image(systemName: "dumbbell.fill").renderingMode(.original).padding()
Text("Notes")
}
}
}.safeAreaInset(edge: .bottom, alignment: .center, spacing: 0) {
Color.clear
.frame(height: 20)
.background(Material.bar)
}
}}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.previewInterfaceOrientation(.landscapeLeft)
}
}
On Simlualtor and real device its placing it in the middle of the screen.
I want this frame so that I can place other elements in side it is a rounded rectangle the best way to go for this?
You are using GeometryReader as the outer most view in the ProfileView, and GeometryReader has the behavior to take as much space as there is available, if you want your rectangle to show in the top or bottom of the screen consider using a Spacer() and if you want to add padding to your rectangle so it does not go to the edges of the screen try removing the .frame(width: geo.size.width) because you are forcing the rectangle to be the width of the screen, in nature the rectangle will take as much space as it can so you do not have to specify that.
This is your code but with some tweaks:
struct ProfileView : View {
var body: some View {
VStack {
RoundedRectangle(cornerRadius: 20)
.stroke(Color.primary, lineWidth: 2)
.frame(height: 200)
.padding(.horizontal)
Spacer()
}
}
}

How to make a List background black in SwiftUI?

What I did to make the entire screen black is to use this construction in my view:
ZStack {
Color.black.ignoresSafeArea() }
And for the List modifiers I used the following two:
.listRowBackground(Color.black)
.listStyle(.plain)
This works great.
But then I want to add a view on top of my List (like a header) and some white space appears around it ? Where does that come from ? And how can I change it to black ?
Here is my complete code:
struct WorkoutView: View {
var body: some View {
ZStack {
Color.black.ignoresSafeArea()
List {
TempView()
ForEach(1..<30) { index in
VStack(alignment: .leading, spacing: 4) {
Text("one line")
.foregroundColor(.white)
.font(.title)
.fontWeight(.bold)
}
.padding(.vertical)
}
.listRowBackground(Color.black)
}
.listStyle(.plain)
}
}
}
struct TempView: View {
var body: some View {
ZStack(alignment: .leading) {
Color.black.ignoresSafeArea()
Text("Hello World")
.foregroundColor(.red)
.font(.largeTitle)
.bold()
}
}
}
Just do the same thing you did for the ForEach: add a .listBackground() modifier. Like this:
TempView()
.listRowBackground(Color.black)

NavigationBarTitle automatic display mode doesn't work

I am unsure how to fix this. I have implemented a ScrollView and a NavigationView with ZStacks. However, the automatic display mode doesn't work and the ScrollView sits behind it, with the Title overlapping.
https://i.stack.imgur.com/KPkGh.png
https://i.stack.imgur.com/H8NwS.png
Here is my current code:
struct Overview: View {
var body: some View {
ZStack{
NavigationView {
ZStack {
Color.init("Background")
.navigationBarHidden(false)
.navigationBarTitle("Overview", displayMode: .automatic)
.edgesIgnoringSafeArea(.top)
ScrollView(showsIndicators: false) {
VStack(spacing: 10) {
ForEach(0..<10) {
Text("Item \($0)")
.foregroundColor(.white)
.font(.largeTitle)
.frame(width: 340, height: 200)
.background(ColorManager.BoxColor)
.cornerRadius(10)
}
}
.frame(maxWidth: .infinity)
}
}
}
}
}
}
var body: some View {
NavigationView {
ScrollView(showsIndicators: false) {
VStack(spacing: 10) {
ForEach(0..<10) {
Text("Item \($0)")
.foregroundColor(.blue)
.font(.largeTitle)
.frame(width: 340, height: 200)
.background(Color(.gray))
.cornerRadius(10)
}
}
.frame(maxWidth: .infinity)
}
.navigationBarHidden(false)
.navigationBarTitle("Overview", displayMode: .automatic)
}
}
You had the navigation item in a ZStack. A ZStack is used to display overlapping views on top of each other.
I believe what you really were looking to achieve stacking the title above the scrollView. That would be achieved with VStack. That however, would still be wrong.
Because it's a navigational setting, it goes inline with the NavigationView. So it can be displayed in the NavigationBar. It doesn't need to be apart of any Stacks.

Modal picker not scrolling right SwiftUI

I created a modal but it seems to have a bug on the selection. When scrolling the left, it scrolls the right, I have to go to the very edge of the left to be able to scroll, this is how it looks:
import SwiftUI
struct ContentView: View {
#State var showingModal = false
#State var hours: Int = 0
#State var minutes: Int = 0
var body: some View {
ZStack {
VStack {
Button("Show me"){
self.showingModal = true
}
if $showingModal.wrappedValue {
VStack(alignment: .center) {
ZStack{
Color.black.opacity(0.4)
.edgesIgnoringSafeArea(.vertical)
// this one is it
VStack(spacing: 20) {
Text("Time between meals")
.bold().padding()
.frame(maxWidth: .infinity)
.background(Color.yellow)
.foregroundColor(Color.white)
HStack {
Spacer()
VStack {
Picker("", selection: $hours){
ForEach(0..<4, id: \.self) { i in
Text("\(i) hours").tag(i)
}
}
.frame(width: 150, height: 120)
.clipped()
}
VStack {
Picker("", selection: $minutes){
ForEach(0..<60, id: \.self) { i in
Text("\(i) min").tag(i)
}
}
.frame(width: 150, height: 120)
.clipped()
}
}
Spacer()
Button(action: {
self.showingModal = false
}){
Text("Close")
} .padding()
}
.frame(width:300, height: 300)
.background(Color.white)
.cornerRadius(20).shadow(radius: 20)
}
}
}
}
}
}
}
How can I fix that little bug? I tried playing around with the layout but no use... any help would be appreciated
What if I told you the reason your Picker not working was this line?
.cornerRadius(20).shadow(radius: 20)
Unfortunately, SwiftUI is still quite buggy and sometimes it doesn't do what it is supposed to do and especially Pickers are not that reliable. I guess we'll need to wait and see the next iteration of SwiftUI, but for now you can replace that line with the code below:
.mask(RoundedRectangle(cornerRadius: 20))
.shadow(radius: 20)
There are just modifiers which affect all view hierarchy (ie. all subviews) that can change resulting layout/presentation/behaviour. And .cornerRadius and .shadow are such type modifiers.
The solution is to apply (as intended) those modifiers only to entire constructed view, and here it is
.compositingGroup() // <<< fix !!
.cornerRadius(20).shadow(radius: 20)
where .compositionGroup is intended to make above view hierarchy flat rendered and all below modifiers applied to only to that flat view.

How can I fit a shape in swift ui to accommodate the length and width of a text view

ZStack {
RoundedRectangle(cornerRadius: 8)
.foregroundColor(.red)
.scaledToFit() //.frame(width: 200, height: 25)
HStack {
Image(systemName: "tag.fill")
.foregroundColor(.white)
Text("Tickets Not Available")
.font(.headline)
.foregroundColor(.white)
.fixedSize(horizontal: true, vertical: false)
}
}
.scaledToFit()
As you can see my views are placed in a zstack so that the rounded rectangle can be the background of the text view. I've tried so many different things like where to put the .scaledtofit and it just gives me wack results each time.
is this what you're after (note the Image.resizable):
import SwiftUI
struct ContentView: View {
var body: some View {
ZStack{
RoundedRectangle(cornerRadius: 8).foregroundColor(.blue)
HStack{
Image(systemName: "tag.fill").resizable().padding(4).foregroundColor(.white).scaledToFit()
Text("Get Tickets").font(.headline).foregroundColor(.white)
}
}.fixedSize()
}
The question is a bit unclear but if you are trying to fit a shape inside the text view, and you are fine with getting rid of scaledToFit, then the code should be:
RoundedRectangle(cornerRadius: 8).foregroundColor(.red).frame(width: textView.width, height: textView.height)
Hope this helps, and hopefully you didn't need to use scaledToFit.
If you did tell me in comments.
A reusable ButtonStyle might be helpful here. Instead of a ZStack, using the .background modifier helps to keep the size of the Button contents:
struct RoundedButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
ZStack {
configuration.label
.font(.headline)
.padding()
.background(RoundedRectangle(cornerRadius: 8).foregroundColor(Color.blue))
}
}
}
Usage example:
Button(
action: {
print("Button Tapped")
},
label: {
HStack {
Image(systemName: "tag.fill")
Text("Tickets")
}
}
)
.buttonStyle(RoundedButtonStyle())