Why is there a Gap between VStacks in SwiftUI? - ios

A whiteness is seen in the area drawn with the red line. If I change the background color of the most inclusive Vstack, that white area changes.
Deleting spacer() lines doesn't work.
Why is there a gap even though there is no space in between?
struct TabbarView: View {
var body: some View {
VStack{
Spacer()
ZStack{
Color.orange.opacity(0.5)
VStack(spacing: 0){
Text("Home")
.padding()
}
}
Spacer()
HStack{
VStack{
Image(systemName: "homekit")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: UIScreen.main.bounds.size.width / 15, height: UIScreen.main.bounds.size.height / 25)
}
}
.frame(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height / 13)
.background(Color.purple)
}
.ignoresSafeArea()
// .background(Color.purple.shadow(radius: 2))
}
}
enter image description here

you can add for VStack:
VStack {}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
updated:
struct ContentView: View {
var body: some View {
ZStack {
Color.orange.opacity(0.5)
VStack {
Spacer()
VStack(spacing: 0){
Text("Home")
.padding()
}
Spacer()
HStack {
VStack {
Image(systemName: "homekit")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 25, height: 25, alignment: .center)
.frame(width: UIScreen.main.bounds.size.width / 15, height: UIScreen.main.bounds.size.height / 25)
}
}
.frame(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height / 13)
.background(Color.purple)
}
}
.ignoresSafeArea()
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
}
}
you used nesting incorrectly and there is a native TabView for tabs
result:

Related

How do I make my logo into a button in swiftUI?

I'm trying to get an image of a logo to be a button. I'm new to Swift/SwiftUI and the resources I've found so far seem to be outdated information. I have the image loaded in to see that I can get the image in there, and I've created a button in the location I want it, I just want to combine the two. Code is below.
struct ContentView: View {
var body: some View {
VStack {
Image("logo1024")
.resizable()
.padding()
.frame(width: 120, height: 120)
Group{
Button(action: {
print("tapped!")
}, label: {
Text("+")
.foregroundColor(.white)
.frame(width: 40, height: 40)
.background(Color.green)
.cornerRadius(15)
.padding()
})
}.frame(maxHeight: .infinity, alignment: .bottom)
}
}
}
Just place image instead of Text into button (all other modifiers on your needs), like
Group{
Button(action: {
print("tapped!")
}, label: {
Image("logo1024")
.resizable()
.padding()
.frame(width: 120, height: 120)
.foregroundColor(.white)
.frame(width: 40, height: 40)
.background(Color.green)
.cornerRadius(15)
.padding()
})
}.frame(maxHeight: .infinity, alignment: .bottom)

How to shape an Image into an circle

iam unsing a UiKit Image picker and trying to setup an Profil Pic for the User. Everything's works fine, the image gets displayed. But iam trying to make it into a Circle. I Tried using clipShape with an circle but it doesn't work. i followed the tutorial "My Images 1: Photo Picker and Camera in SwiftUI"
struct ProfileView: View {
#EnvironmentObject var appUser: User
#EnvironmentObject var appInfo: AppInformation
var body: some View {
ZStack {
Rectangle()
.frame(width: 400, height: 720)
.cornerRadius(50)
.foregroundColor(.gray)
.overlay(
HStack {
if let image = appUser.profilBild {
Image(uiImage: image)
.resizable()
.frame(width: 100, height: 100)
.scaledToFill()
.clipShape(RoundedRectangle(cornerRadius: 15))
.overlay(Circle().stroke(Color.orange, lineWidth: 10))
.onTapGesture {
appInfo.source = .library
appInfo.showPicker = true
}
.padding(20)
.shadow(radius: 10)
.overlay(
ZStack{
Rectangle()
.frame(width: 20, height: 20)
.offset(x: 35, y: -35)
.foregroundColor(.white)
Image(systemName: "plus.circle.fill")
.resizable()
.frame(width: 30, height: 30)
.offset(x: 35, y: -35)
.foregroundColor(.blue)
.shadow(radius: 10)
}
)
}
else {
Image(systemName: "person.circle")
.resizable()
.frame(width: 100, height: 100)
.onTapGesture {
appInfo.source = .library
appInfo.showPicker = true
}
.padding(20)
.shadow(radius: 10)
.overlay(
ZStack{
Rectangle()
.frame(width: 20, height: 20)
.offset(x: 35, y: -35)
.foregroundColor(.white)
Image(systemName: "plus.circle.fill")
.resizable()
.frame(width: 30, height: 30)
.offset(x: 35, y: -35)
.foregroundColor(.blue)
.shadow(radius: 10)
}
)
}
VStack {
Text(appUser.username)
.font(.largeTitle)
.frame(width: 240 ,alignment: .leading)
.offset(x: -10, y: -25)
.lineLimit(1)
Text(appUser.name)
.frame(width: 220, alignment: .leading)
.offset(x: -15,y: -20)
.lineLimit(1)
}
}
.frame(width: 400, height: 720, alignment: .topLeading)
)
.padding()
ZStack {
Rectangle()
.foregroundColor(.secondary)
.frame(width: 380, height: 510)
.cornerRadius(45)
}
.frame(width: 400, height: 700, alignment: .bottom)
.padding()
}
.sheet(isPresented: $appInfo.showPicker) {
ImagePicker(sourceType: appInfo.source == .library ? .photoLibrary : .camera, selectedImage: $appUser.profilBild)
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
}
}
You were almost there :)
Your only mistake was the order you placed your modifiers. ORDER MATTERS!!
Place scaledToFill() and clipShape() before the frame modifier.
Like such:
.resizable()
.scaledToFill()
.clipShape(Circle())
.frame(width: size, height: size)

SwiftUI View is taking exceeding edges

I am learning SwiftUI and was trying to replicate an app. I ran into a problem where the view is taking up space outside the frame as well.
It looks like this:
My code for the view is:
struct LessonsScreen: View {
var body: some View {
VStack (alignment: .leading) {
HStack {
Image(systemName: "arrow.left")
.font(.system(size: 30))
Spacer()
Image(systemName: "slider.horizontal.3")
.font(.system(size: 30))
}
Text("A2 - Elementary")
.font(.system(size: 28, weight: .semibold))
.padding()
LessonCompletion(lessonNum: 1, text: "How are you?", color: .purple)
Image("discussion")
.cornerRadius(20)
.frame(width: UIScreen.main.bounds.width, alignment: .center)
LessonCompletion(lessonNum: 2, text: "Pronunciation", color: .green)
LessonCompletion(lessonNum: 3, text: "Demonstrative pronouns", color: .red)
LessonCompletion(lessonNum: 4, text: "Present continuous", color: .yellow)
Button(action: {}, label: {
Text("Get started")
.foregroundColor(.white)
.frame(width: UIScreen.main.bounds.width - 150, height: 70, alignment: .center)
.background(Color.black)
.cornerRadius(10)
.frame(width: UIScreen.main.bounds.width, alignment: .center)
.padding()
})
}
}
}
Can anyone tell me where I messed up the formatting?
If you like to align the button in center in native SwiftUI way, you can use view modifier Spacer() inside HStack() instead of .frame, like this: (and same with 'discussion' Image)
...
Button(action: {}, label: {
HStack{
Spacer()
Text("Get started")
.foregroundColor(.white)
.frame(width: UIScreen.main.bounds.width - 150, height: 70, alignment: .center)
.background(Color.black)
.cornerRadius(10)
.padding()
Spacer()
}
})
...
In your button replace
.frame(width: UIScreen.main.bounds.width, alignment: .center)
with
.frame(maxWidth: .infinity, alignment: .center)

Stacking a HStack below a ZStack in SwiftUI

Disclaimer: New to SwiftUI
I know a ZStack() view allows me to overlap views, which is what I want for the heading section of the app.
I set the ZStack() to not take up the entire height and had expected an HStack(), placed after the ZStack() to do just that, appear after. Instead it also overlaps with the ZStack.
I'm sure it's a simple solution to co-exist. Image and code below.
var body: some View {
GeometryReader { geometry in
ZStack(alignment: .topLeading) {
Ellipse()
.fill(self.bgColor)
.frame(width: geometry.size.width * 1.4, height: geometry.size.height * 0.28)
.position(x: geometry.size.width / 2.35, y: geometry.size.height * 0.1)
.shadow(radius: 3)
.edgesIgnoringSafeArea(.all)
HStack(alignment: .top) {
VStack(alignment: .leading) {
Text(self.title)
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color.white)
Text(self.subtitle)
.font(.subheadline)
.fontWeight(.regular)
.foregroundColor(Color.white)
}
.padding(.leading, 25)
.padding(.top, 20)
Spacer()
VStack(alignment: .trailing) {
Image("SettingsIcon")
.resizable()
.scaledToFit()
.frame(width: 30, height: 30)
}
.padding(.top, 20)
.padding(.trailing, 25)
}
}
.fixedSize(horizontal: false, vertical: true)
HStack(alignment: .top) {
Text(self.title)
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color.white)
}
}
}
Try the following code using a top VStack and closing the GeometryReader before the last HStack:
var body: some View {
VStack { // <-- here
GeometryReader { geometry in
ZStack(alignment: .topLeading) {
Ellipse()
.fill(self.bgColor)
.frame(width: geometry.size.width * 1.4, height: geometry.size.height * 0.28)
.position(x: geometry.size.width / 2.35, y: geometry.size.height * 0.1)
.shadow(radius: 3)
.edgesIgnoringSafeArea(.all)
HStack(alignment: .top) {
VStack(alignment: .leading) {
Text(self.title)
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color.white)
Text(self.subtitle)
.font(.subheadline)
.fontWeight(.regular)
.foregroundColor(Color.white)
}
.padding(.leading, 25)
.padding(.top, 20)
Spacer()
VStack(alignment: .trailing) {
Image("SettingsIcon")
.resizable()
.scaledToFit()
.frame(width: 30, height: 30)
}
.padding(.top, 20)
.padding(.trailing, 25)
}
}.fixedSize(horizontal: false, vertical: true)
} // <-- here end GeometryReader
HStack(alignment: .top) {
Text(self.title)
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color.white)
}
} // <-- here end VStack
}

SwiftUI onTapGesture tappable area is larger than shape

I'm learning SwiftUI and had a very simple view with only one shape with a onTapGesture. What I'm expecting the onTapGesture should be called only when I click on the shape. However I've noticed that when I click outside of the shape (not too far away) the onTapGesture is also fired. Any one has any idea why this is happening?
struct ContentView: View {
var body: some View {
RoundedRectangle(cornerRadius: 10)
.fill(Color.yellow)
.frame(width: 100, height: 100, alignment: .leading)
.onTapGesture {
print("Clicked")
}
}
}
Update:
I've tried having multiple element inside a Vstack. When you try to click on the very bottom of test view2 you can see in the console that it prints click on view 3.
var body: some View {
VStack {
ZStack {
RoundedRectangle(cornerRadius: 20)
.foregroundColor(.red)
Text("test view1")
}
.frame(width: 200, height: 100, alignment: .center)
ZStack {
RoundedRectangle(cornerRadius: 20)
.foregroundColor(.blue)
Text("test view2")
}
.frame(width: 200, height: 100, alignment: .center)
.onTapGesture {
print("click on view 2")
}
ZStack {
RoundedRectangle(cornerRadius: 20)
.foregroundColor(.green)
Text("test view3")
}
.frame(width: 200, height: 100, alignment: .center)
.onTapGesture {
print("click on view 3")
}
}
.frame( maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
.background(Color.black)
}

Resources