Swift UI Update a view by doing something in another view - view

In my code, I have a value which counts calls from Navigation Links. This works fine but I want that if this count is over 1, the ContentView updates and add a cell. At the moment, I have to restart the app and then I have the new cell, but I want, that it updates directly. Is this possible? This is my code:
struct Website : Identifiable, Hashable, Comparable{
static func < (lhs: Website, rhs: Website) -> Bool {
lhs.name < rhs.name
}
var id = UUID()
var url : String
var name : String
var image : String
var calls : Int
}
struct websiteCallsCell : View{
var website : Website
#State var press = false
#State var tap = false
#State var isPresented = false
var body: some View{
NavigationLink(destination: WebView(website: website, url: URL(string: website.url)), label: {
Text(website.name)
.font(.system(size: 20, weight: .semibold, design: .rounded))
.frame(width: UIScreen.main.bounds.width*0.85, height: 60)
.background(
ZStack {
Color(press ? colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) : colorLiteral(red: 0.7608050108, green: 0.8164883852, blue: 0.9259157777, alpha: 1))
RoundedRectangle(cornerRadius: 16, style: .continuous)
.foregroundColor(Color(press ? colorLiteral(red: 0.7608050108, green: 0.8164883852, blue: 0.9259157777, alpha: 1) : colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)))
.blur(radius: 4)
.offset(x: -8, y: -8)
RoundedRectangle(cornerRadius: 16, style: .continuous)
.fill(
LinearGradient(gradient: Gradient(colors: [Color( colorLiteral(red: 0.9019607843, green: 0.9294117647, blue: 0.9882352941, alpha: 1)), Color.white]), startPoint: .topLeading, endPoint: .bottomTrailing)
)
.padding(2)
.blur(radius: 2)
}
)
.clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
.overlay(
HStack {
AnimatedImage(url: URL(string: website.image))
.font(.system(size: 24, weight: .light))
.foregroundColor(Color.white.opacity(press ? 0 : 1))
.frame(width: press ? 220 : 54, height: press ? 4 : 50)
.background(Color( colorLiteral(red: 0.3647058904, green: 0.06666667014, blue: 0.9686274529, alpha: 1)))
.clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
.shadow(color: Color( colorLiteral(red: 0.3647058904, green: 0.06666667014, blue: 0.9686274529, alpha: 1)).opacity(0.3), radius: 10, x: 10, y: 10)
.offset(x: press ? 70 : -10, y: press ? 16 : 0)
Spacer()
}
)
.shadow(color: Color(press ? colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) : colorLiteral(red: 0.7608050108, green: 0.8164883852, blue: 0.9259157777, alpha: 1)), radius: 20, x: 20, y: 20)
.shadow(color: Color(press ? colorLiteral(red: 0.7608050108, green: 0.8164883852, blue: 0.9259157777, alpha: 1) : colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)), radius: 20, x: -20, y: -20)
.scaleEffect(tap ? 1.2 : 1)
})
}
}
List{
ForEach(websites){ website in
if UserDefaults.standard.integer(forKey: "calls\(website.name)") > 0 && (UserDefaults.standard.integer(forKey: "lastCallsCount") < 8) {
VStack{
websiteCallsCell(website: website)
lineSpacing(20)
Spacer(minLength: 5)
}
}
}
}

You are checking on UserDefaults , Which is not a publisher
I have two solutions fir that :
1- use #Environmentobject with a #Published var for clicks count , then check on it , in your ContentView
2- pass the State variable to the navigation link , and in the navigation link destination declare #Binding variable , and change it in each press , then check on it in your ContentView
struct websiteCallsCell : View {
var website : Website
#Binding var pressCount : Int
// other code
}
//
struct ContentView : View {
#State var pressCount = 0
}
//
List{
ForEach(websites){ website in
if pressCount > 0 && pressCount< 8 {
VStack{
websiteCallsCell(website: website, pressCount: self.$pressCount)
lineSpacing(20)
Spacer(minLength: 5)
}
}
}
}

Related

SwiftUI - Animating HUD / Pop Over like iOS Silent Mode

I'm trying to clone the following animation from iOS:
Here's my code. I'm stuck with the animation of the star. I'd for example like to shake it a little bit or rotate it around it's y-axis.
Here's my code:
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
PopOver(image: "star.fill", color: .primary, title: "Thank You!")
}
}
struct PopOver: View{
var image: String
var color: Color
var title: String
#Environment(\.colorScheme) var scheme
var body: some View{
HStack(spacing: 10){
Image(systemName: image)
.font(.title3)
.foregroundColor(color)
Text(title)
.foregroundColor(.primary)
}
.padding(.vertical,10)
.padding(.horizontal)
.background(
scheme == .dark ? Color.black : Color.white
)
.clipShape(Capsule())
.shadow(color: Color.primary.opacity(0.1), radius: 5, x: 1, y: 5)
.shadow(color: Color.primary.opacity(0.03), radius: 5, x: 0, y: -5)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
.offset(y: 0)
}
}
Can you tell me how this can be achieved?
Many Thanks!
you could try something like this approach:
struct ContentView: View {
#State var popUpPresented = false
var body: some View {
Button(action: {popUpPresented = true}) {
Text("click me")
}
.popover(isPresented: $popUpPresented, arrowEdge: .top) {
PopOver(image: "star.fill", color: .primary, title: "Thank You!")
}
}
}
struct PopOver: View{
var image: String
var color: Color
var title: String
#State var rotate = 0.0 // <-- here
#Environment(\.colorScheme) var scheme
var body: some View{
HStack(spacing: 10){
Image(systemName: image).font(.title3).foregroundColor(color)
// --- here ---
.rotation3DEffect(Angle.degrees(rotate), axis: (x: 0, y: 1, z: 0))
.task {
withAnimation(Animation.default.speed(0.3).delay(0).repeatForever(autoreverses: false)){
rotate = 360.0
}
}
Text(title).foregroundColor(.primary)
}
.padding(.vertical,10)
.padding(.horizontal)
.background(scheme == .dark ? Color.black : Color.white)
.clipShape(Capsule())
.shadow(color: Color.primary.opacity(0.1), radius: 5, x: 1, y: 5)
.shadow(color: Color.primary.opacity(0.03), radius: 5, x: 0, y: -5)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
.offset(y: 0)
}
}

SwiftUI - Move and rotate an Image when a button is pressed

I have an Image, and I want it to rotate on the y axis, and move towards the bottom of the View when I press a Button. I tried using the .onChange, but I get the error "Result of call to 'animation' is unused", of which I understand the meaning, but I don't understand neither why it comes up nor how can I fix it.
Here's my code:
import SwiftUI
struct ContentView : View {
#State var animateCoin = false
#Environment(\.colorScheme) var colorScheme
var body: some View {
Rectangle()
.foregroundColor(colorScheme == .dark ? .white : .black)
.frame(width: 150, height: 150, alignment: .center)
.offset(y: -60)
.mask(Image("Coin") //That's the name of the Image I have in the assets
.resizable()
.onChange(of: animateCoin, perform: { value in
self.animation(.easeIn) //I put .easeIn just as an example, because the .rotation3DEffect gives me a red warning
}))
Button(action: { animateCoin = true } ) {
ZStack {
RoundedRectangle(cornerRadius: 10)
.foregroundColor(.green)
.frame(width: 100, height: 40, alignment: .center)
.shadow(radius: 10)
Text("Animate")
.foregroundColor(.white)
.shadow(radius: 20)
}
}
}}
The Image is set as a mask so that I can easily control its color depending on the light or dark mode.
Thank to everyone who will help me!
How about doing it like this:
#State var animateCoin = false
#Environment(\.colorScheme) var colorScheme
var body: some View {
VStack {
Rectangle()
.foregroundColor(colorScheme == .dark ? .white : .black)
.frame(width: 150, height: 150, alignment: .center)
.offset(y: -60)
.mask(Image(systemName: "car.fill")
.resizable()
.aspectRatio(contentMode: .fit)
.rotation3DEffect(
Angle(degrees: self.animateCoin ? 360 : 0),
axis: (x: 0, y: self.animateCoin ? 360 : 0, z: 0)
)
)
.offset(y: self.animateCoin ? 600 : 0)
.animation(.linear(duration: 1))
ZStack {
Button(action: { self.animateCoin.toggle() } ) {
ZStack {
RoundedRectangle(cornerRadius: 10)
.foregroundColor(.green)
.frame(width: 100, height: 40, alignment: .center)
.shadow(radius: 10)
Text("Animate")
.foregroundColor(.white)
.shadow(radius: 20)
}
}
}
}
}
As you asked:
Rotate on Y axis.
Move the image to the buttom.

Problem with formatting LazyHGrid - SwiftUI

I am trying to create a basic lazyHGrid but after looking at a couple of different tutorials online I still can't manage to build it properly. I am trying to make a grid that is filled with rectangles with symbols and text inside those rectangles. See image below:
If I make this in a HStack all the rectangles are presented correctly, but as soon as I put it into a LazyHGrid I get this problem. Any ideas?
let rows = [
GridItem(.fixed(200)),
GridItem(.fixed(200)),
]
var product: ProductModel
var body: some View {
LazyHGrid(rows: rows, alignment: .center) {
ForEach(0..<product.imageStack01Image.count, id: \.self) { item in
ZStack(alignment: .top){
RoundedRectangle(cornerRadius: 25, style: .continuous)
.fill(Color.white)
.frame(width: 200, height: 200)
.shadow(color: Color.black.opacity(0.08), radius: 20, x: 0, y: 5)
VStack(alignment: .leading) {
Image(systemName:product.imageStack01Image[item])
.font(.system(size: 40.0))
.frame(height: 40)
.foregroundColor(.red)
.padding(.top, 40)
.padding(.leading, 10)
Text(product.imageStack01Text[item])
.font(.title2)
.fontWeight(.medium)
.multilineTextAlignment(.trailing)
.padding(10)
}
}
}
}
}
As far as I understood your try to put image and text into rectangle, so try to use overlay instead of ZStack
ForEach(0..<product.imageStack01Image.count, id: \.self) { item in
RoundedRectangle(cornerRadius: 25, style: .continuous)
.fill(Color.white)
.frame(width: 200, height: 200)
.shadow(color: Color.black.opacity(0.08), radius: 20, x: 0, y: 5)
.overlay(
VStack(alignment: .leading) {
Image(systemName:product.imageStack01Image[item])
.font(.system(size: 40.0))
.frame(height: 40)
.foregroundColor(.red)
.padding(.top, 40)
.padding(.leading, 10)
Text(product.imageStack01Text[item])
.font(.title2)
.fontWeight(.medium)
.multilineTextAlignment(.trailing)
.padding(10)
})
}
}
It might have to do with the hardcoded frame in your square. Try using aspectRatio if you just want a square or frame each layer of the ZStack or frame the ZStack depending on what you want to achieve.
import SwiftUI
struct LazyGridSample: View {
///Sample Products to reproduce
#State var products = ["0xxxxxxxxxx0xxxxxxxxxx","1xxxxxxxxxx0xxxxxxxxxx","2xxxxxxxxxx0xxxxxxxxxx","3xxxxxxxxxx0xxxxxxxxxx","4xxxxxxxxxx0xxxxxxxxxx","5xxxxxxxxxx0xxxxxxxxxx","6xxxxxxxxxx0xxxxxxxxxx","7xxxxxxxxxx0xxxxxxxxxx","8xxxxxxxxxx0xxxxxxxxxx","9xxxxxxxxxx0xxxxxxxxxx"]
let rows = [
GridItem(.fixed(200)),
GridItem(.fixed(200)),
]
let squareSize: CGSize = CGSize(width: 200, height: 200)
var body: some View {
//ScrollView(.horizontal){
LazyHGrid(rows: rows, alignment: .center) {
//HStack{
ForEach(0..<products.count, id: \.self) { idx in
ZStack(alignment: .top){
RoundedRectangle(cornerRadius: 25, style: .continuous)
.fill(Color.white)
//.frame(width: squareSize.width, height: squareSize.height)
//.aspectRatio(1, contentMode: .fill)
.shadow(color: Color.black.opacity(0.08), radius: 20, x: 0, y: 5)
VStack(alignment: .leading) {
//Removed Image
Text(products[idx].description)
.font(.title2)
.fontWeight(.medium)
.multilineTextAlignment(.trailing)
.padding(10)
}//.frame(width: squareSize.width, height: squareSize.height, alignment: .center)
//.aspectRatio(1, contentMode: .fill)
}//Adjusts the the entire ZStack
//.frame(width: squareSize.width, height: squareSize.height, alignment: .center)
.aspectRatio(1, contentMode: .fill)
}
}
//}//ScrollView
}
}
struct LazyGridSample_Previews: PreviewProvider {
static var previews: some View {
LazyGridSample()
}
}

"Type '()' cannot conform to 'View'; only struct/enum/class types can conform to protocols"

EDIT: Explanation to the problem
This code is producing an error where the poster doesn't know how to solve it.
This is a new edit of the previous post.
I received the error on >Geometry Reader. This post includes all of the code. This new post includes the Sign-Up and Login code as requested. I hope that it is in a readable format. I made some corrections that I hope will help. The code is listed below:
import SwiftUI
struct ContentView: View {
var body: some View {
Home()
// for light status bar...
.preferredColorScheme(.dark)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct Home : View {
#State var index = 0
var body: some View{
GeometryReader{ _ in // ( ERROR MESSAGE OCCURS HERE)--> ("Type '()' cannot conform to'View'; only struct/enum/class types can conform to protocols" and "Required by generic struct 'GeometryReader' where 'Content' = '()'")
VStack{
Image("logo")
.resizable()
.frame(width:60, height: 60)
ZStack{
SignUp(index: self.$index)
*// changing view order...*
.zIndex(Double(self.index))
Login(index: self.$index)
}
HStack(spacing: 15){
Rectangle()
.fill(Color("Blue"))
.frame(height: 1)
Text("OR")
Rectangle()
.fill(Color("Blue"))
.frame(height: 1)
}
.padding(.horizontal, 20)
.padding(.top, 50)
*// because login button is moved 25 in y axis and 25 padding = 50*
.background(Color("Orange").edgesIgnoringSafeArea(.all))
//Curve...
HStack(spacing: 25){
Button(action: {
}) {
Image("Unknown")
.resizable()
.renderingMode(.original)
.frame(width: 50, height: 50)
.clipShape(Circle())
}
Button(action: {
}) {
Image("fb")
.resizable()
.renderingMode(.original)
.frame(width: 50, height: 50)
.clipShape(Circle())
}
Button(action: {
}) {
Image("instagram")
.resizable()
.renderingMode(.original)
.frame(width: 50, height: 50)
.clipShape(Circle())
}
}
.padding(.top, 30)
}
.padding(.vertical)
struct CShape: Shape {
func path(in rect: CGRect) -> Path {
return Path {path in
*//right side curve...*
path.move(to: CGPoint(x: rect.width, y: 100))
path.addLine(to: CGPoint(x: rect.width, y: rect.height))
path.addLine(to: CGPoint(x: 0, y: rect.height))
path.addLine(to: CGPoint(x: 0, y: 0))
}
}
}
struct CShape1: Shape {
func path(in rect: CGRect) -> Path {
return Path {path in
*//left side curve...*
path.move(to: CGPoint(x: 0, y: 100))
path.addLine(to: CGPoint(x: 0, y: rect.height))
path.addLine(to: CGPoint(x: rect.width, y: rect.height))
path.addLine(to: CGPoint(x: rect.width, y: 0))
}
}
}
struct Login : View {
#State var email = ""
#State var pass = ""
#Binding var index : Int
var body : some View {
ZStack(alignment: .bottom) {
VStack{
HStack{
VStack(spacing:10){
Text("Login")
.foregroundColor(self.index == 0 ? .white : .gray)
.font(.title)
.fontWeight(.bold)
Capsule()
.fill(self.index == 0 ? Color.blue : Color.clear)
.frame(width:100, height: 5)
}
Spacer(minLength:0)
}
.padding(.top, 30)// for top curve...
VStack{
HStack(spacing:15){
Image(systemName: "envelope")
.foregroundColor(Color("Blue"))
TextField("Email Adress", text: self.$email)
}
Divider().background(Color.white.opacity(0.5))
}
.padding(.horizontal)
.padding(.top, 40)
VStack{
HStack(spacing:15){
Image(systemName: "eye")
.foregroundColor(Color("Orange"))
SecureField("Password", text: self.$pass)
}
Divider().background(Color.white.opacity(0.5))
}
.padding(.horizontal)
.padding(.top, 30)
HStack{
Spacer(minLength: 0)
Button(action: {
}) {
Text("Forget Password?")
.foregroundColor(Color.white.opacity(0.6))
}
}
.padding(.horizontal)
.padding(.top, 30)
}
.padding()
// bottom padding...
.padding(.bottom, 65)
.background(Color("LightBlue"))
.clipShape(CShape())
.contentShape(CShape())
.shadow(color: Color.black.opacity(0.3), radius: 5, x: 0, y: -5)
.onTapGesture{
self.index = 0
}
.cornerRadius(35)
.padding(.horizontal,20)
// Button...
Button(action: {
}) {
Text("LOGIN")
.foregroundColor(.white)
.fontWeight(.bold)
.padding(.vertical)
.padding(.horizontal, 50)
.background(Color("LightBlue"))
.clipShape(Capsule())
// shadow ...
.shadow(color: Color.white.opacity(0.1), radius: 5, x: 0, y: 5)
}
// moving view down...
.offset(y: 25)
.opacity(self.index == 0 ? 1 : 0)
}
}
}
// SignUp Page...
struct SignUp : View {
#State var email = ""
#State var pass = ""
#State var Repass = ""
#Binding var index: Int
var body : some View {
ZStack(alignment: .bottom) {
VStack{
HStack{
Spacer(minLength:0)
VStack(spacing: 10){
Text("SignUp")
.foregroundColor(self.index == 1 ? .white : .gray)
.font(.title)
.fontWeight(.bold)
Capsule()
.fill(self.index == 1 ? Color.blue : Color.clear)
.frame(width:100, height: 5)
}
}
.padding(.top, 30)// for top curve...
VStack{
HStack(spacing:15){
Image(systemName: "envelope")
.foregroundColor(Color("Orange"))
TextField("Email Adress", text: self.$email)
}
Divider().background(Color.white.opacity(0.5))
}
.padding(.horizontal)
.padding(.top, 40)
VStack{
HStack(spacing:15){
Image(systemName: "eye")
.foregroundColor(Color("Orange"))
SecureField("Password", text: self.$pass)
}
Divider().background(Color.white.opacity(0.5))
}
.padding(.horizontal)
.padding(.top, 30)
// replacing forget password with reenter password...
// so same height will be maintained...
VStack{
HStack(spacing:15){
Image(systemName: "eye")
.foregroundColor(Color("Orange"))
SecureField("Password", text: self.$Repass)
}
Divider().background(Color.white.opacity(0.5))
}
.padding(.horizontal)
.padding(.top, 30)
}
.padding()
// bottom padding...
.padding(.bottom, 65)
.background(Color("Blue"))
.clipShape(CShape1())
//clipping the content shape also for tap gesture...
.contentShape(CShape1())
// shadow...
.shadow(color: Color.black.opacity(0.3), radius: 5, x: 0, y: -5)
.onTapGesture {
self.index = 1
}
.cornerRadius(35)
.padding(.horizontal,20)
*// Button...*
Button(action: {
}) {
Text("SIGNUP")
.foregroundColor(.white)
.fontWeight(.bold)
.padding(.vertical)
.padding(.horizontal, 50)
.background(Color("Blue"))
.clipShape(Capsule())
*// shadow ...*
.shadow(color: Color.white.opacity(0.1), radius: 5, x: 0, y: 5)
}
*// moving view down...*
.offset(y: 25)
*// hiding view when its in background...*
*// only button...*
.opacity(self.index == 1 ? 1 : 0)
}
}
}
}
}
}
So the problem in your code is that you are defining views inside a GeomtryReader and that's a big no no. So a fix would be to move the Login and Singup outside the GeomtryReader or even better and better practice is just create a new file for each view and add it's code in that file. For example one file for Login.swift and another for Register.swift and maybe another called Shapes which includes multiple shapes and exports them.
What you were doing is something similar to this
struct ContentView: View {
var body: some View {
GeomtryReader { _ in
Text("test")
// Here is where the bug would happen
struct NewView: View {
var body: some View {
Text("Second View")
}
}
//////////////////////////////////////
}
}
}
You can see if you copy and paste the above code it will generate the same error. What you should do is move NewView outside of GeomtryReader
Something like this
struct ContentView: View {
var body: some View {
return GeomtryReader { _ in
Text("test")
}
// This will fix the error
struct NewView: View {
var body: some View {
Text("Second View")
}
}
//////////////////////////////////////
}
}
Notice where I have moved the code. Also pay attention I have added Return to the GeomtryReader and that's because body is a computed property that expects to have a value of View but in this case we are confusing the compiler as to which View we want it to be the returned value so we have to manually specify it. If you don't want to include return then you would have to move NewView outside body or even better outside ContentView all together.
In any case here is your code working 100%, you can copy and paste it.
import SwiftUI
struct ContentView: View {
var body: some View {
Home()
// for light status bar...
.preferredColorScheme(.dark)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct Home : View {
#State var index = 0
var body: some View{
return GeometryReader{ _ in // ( ERROR MESSAGE OCCURS HERE)--> ("Type '()' cannot conform to'View'; only struct/enum/class types can conform to protocols" and "Required by generic struct 'GeometryReader' where 'Content' = '()'")
VStack{
Image("logo")
.resizable()
.frame(width:60, height: 60)
ZStack{
SignUp(index: self.$index)
// changing view order...*
.zIndex(Double(self.index))
Login(index: self.$index)
}
HStack(spacing: 15){
Rectangle()
.fill(Color("Blue"))
.frame(height: 1)
Text("OR")
Rectangle()
.fill(Color("Blue"))
.frame(height: 1)
}
.padding(.horizontal, 20)
.padding(.top, 50)
// because login button is moved 25 in y axis and 25 padding = 50*
.background(Color("Orange").edgesIgnoringSafeArea(.all))
// Curve...
HStack(spacing: 25){
Button(action: {
}) {
Image("Unknown")
.resizable()
.renderingMode(.original)
.frame(width: 50, height: 50)
.clipShape(Circle())
}
Button(action: {
}) {
Image("fb")
.resizable()
.renderingMode(.original)
.frame(width: 50, height: 50)
.clipShape(Circle())
}
Button(action: {
}) {
Image("instagram")
.resizable()
.renderingMode(.original)
.frame(width: 50, height: 50)
.clipShape(Circle())
}
}
.padding(.top, 30)
}
.padding(.vertical)
}
struct Login : View {
#State var email = ""
#State var pass = ""
#Binding var index : Int
var body : some View {
ZStack(alignment: .bottom) {
VStack{
HStack{
VStack(spacing:10){
Text("Login")
.foregroundColor(self.index == 0 ? .white : .gray)
.font(.title)
.fontWeight(.bold)
Capsule()
.fill(self.index == 0 ? Color.blue : Color.clear)
.frame(width:100, height: 5)
}
Spacer(minLength:0)
}
.padding(.top, 30)// for top curve...
VStack{
HStack(spacing:15){
Image(systemName: "envelope")
.foregroundColor(Color("Blue"))
TextField("Email Adress", text: self.$email)
}
Divider().background(Color.white.opacity(0.5))
}
.padding(.horizontal)
.padding(.top, 40)
VStack{
HStack(spacing:15){
Image(systemName: "eye")
.foregroundColor(Color("Orange"))
SecureField("Password", text: self.$pass)
}
Divider().background(Color.white.opacity(0.5))
}
.padding(.horizontal)
.padding(.top, 30)
HStack{
Spacer(minLength: 0)
Button(action: {
}) {
Text("Forget Password?")
.foregroundColor(Color.white.opacity(0.6))
}
}
.padding(.horizontal)
.padding(.top, 30)
}
.padding()
// bottom padding...
.padding(.bottom, 65)
.background(Color("LightBlue"))
.clipShape(CShape())
.contentShape(CShape())
.shadow(color: Color.black.opacity(0.3), radius: 5, x: 0, y: -5)
.onTapGesture{
self.index = 0
}
.cornerRadius(35)
.padding(.horizontal,20)
// Button...
Button(action: {
}) {
Text("LOGIN")
.foregroundColor(.white)
.fontWeight(.bold)
.padding(.vertical)
.padding(.horizontal, 50)
.background(Color("LightBlue"))
.clipShape(Capsule())
// shadow ...
.shadow(color: Color.white.opacity(0.1), radius: 5, x: 0, y: 5)
}
// moving view down...
.offset(y: 25)
.opacity(self.index == 0 ? 1 : 0)
}
}
}
//SignUp Page...
struct SignUp : View {
#State var email = ""
#State var pass = ""
#State var Repass = ""
#Binding var index: Int
var body : some View {
ZStack(alignment: .bottom) {
VStack{
HStack{
Spacer(minLength:0)
VStack(spacing: 10){
Text("SignUp")
.foregroundColor(self.index == 1 ? .white : .gray)
.font(.title)
.fontWeight(.bold)
Capsule()
.fill(self.index == 1 ? Color.blue : Color.clear)
.frame(width:100, height: 5)
}
}
.padding(.top, 30)// for top curve...
VStack{
HStack(spacing:15){
Image(systemName: "envelope")
.foregroundColor(Color("Orange"))
TextField("Email Adress", text: self.$email)
}
Divider().background(Color.white.opacity(0.5))
}
.padding(.horizontal)
.padding(.top, 40)
VStack{
HStack(spacing:15){
Image(systemName: "eye")
.foregroundColor(Color("Orange"))
SecureField("Password", text: self.$pass)
}
Divider().background(Color.white.opacity(0.5))
}
.padding(.horizontal)
.padding(.top, 30)
// replacing forget password with reenter password...
// so same height will be maintained...
VStack{
HStack(spacing:15){
Image(systemName: "eye")
.foregroundColor(Color("Orange"))
SecureField("Password", text: self.$Repass)
}
Divider().background(Color.white.opacity(0.5))
}
.padding(.horizontal)
.padding(.top, 30)
}
.padding()
// bottom padding...
.padding(.bottom, 65)
.background(Color("Blue"))
.clipShape(CShape1())
//clipping the content shape also for tap gesture...
.contentShape(CShape1())
// shadow...
.shadow(color: Color.black.opacity(0.3), radius: 5, x: 0, y: -5)
.onTapGesture {
self.index = 1
}
.cornerRadius(35)
.padding(.horizontal,20)
// Button...*
Button(action: {
}) {
Text("SIGNUP")
.foregroundColor(.white)
.fontWeight(.bold)
.padding(.vertical)
.padding(.horizontal, 50)
.background(Color("Blue"))
.clipShape(Capsule())
// shadow ...*
.shadow(color: Color.white.opacity(0.1), radius: 5, x: 0, y: 5)
}
// moving view down...*
.offset(y: 25)
// hiding view when its in background...*
// only button...*
.opacity(self.index == 1 ? 1 : 0)
}
}
}
struct CShape: Shape {
func path(in rect: CGRect) -> Path {
return Path {path in
//right side curve...*
path.move(to: CGPoint(x: rect.width, y: 100))
path.addLine(to: CGPoint(x: rect.width, y: rect.height))
path.addLine(to: CGPoint(x: 0, y: rect.height))
path.addLine(to: CGPoint(x: 0, y: 0))
}
}
}
struct CShape1: Shape {
func path(in rect: CGRect) -> Path {
return Path {path in
//left side curve...*
path.move(to: CGPoint(x: 0, y: 100))
path.addLine(to: CGPoint(x: 0, y: rect.height))
path.addLine(to: CGPoint(x: rect.width, y: rect.height))
path.addLine(to: CGPoint(x: rect.width, y: 0))
}
}
}
}
}

SwiftUI animations of elements in a scrollview doesn't work ? Xcode GM update

I just switched to the GM version of xcode and since then I have a problem that I did not have before it seems to me.
I created a simplified version of the problem:
I have a scrollview with several elements inside.
I add animations states on the blue square but I have the impression the elements have no animations and changes state brutally.
I tried with an element outside the scrollview (purple square) and it works
I don't see why animations do not work someone has an idea?
#State var Enter = false
var body: some View {
VStack {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 15) {
Rectangle()
.foregroundColor(Color.red)
.frame(width: 80, height: 80, alignment: .center)
Button(action: {
withAnimation(.easeInOut(duration: 1.12)) {
self.Enter = true
}
}) {
Rectangle()
.foregroundColor(Color.blue)
.frame(width: 80, height: 80, alignment: .center)
.opacity(self.Enter ? 0 : 1)
}
//.padding(.horizontal, self.Enter ? 50 : 10)
Rectangle()
.foregroundColor(Color.green)
.frame(width: 80, height: 80, alignment: .center)
.offset(x: self.Enter ? 30 : 0 , y: 0)
Rectangle()
.foregroundColor(Color.red)
.frame(width: 80, height: 80, alignment: .center)
}
.padding(.leading, 67 )
.padding(.trailing, 110)
// .padding(.top, (screen.height)/81.2)
.padding(.bottom, 10)
}
HStack {
Rectangle()
.foregroundColor(Color.purple)
.frame(width: 80, height: 80, alignment: .center)
.offset(x: self.Enter ? 80 : 0 , y: 0)
}
}
}
Using implicit vice explicit animation often works for me in these situations. This should accomplish what you were looking for: (works in the Xcode 11 GM seed)
Update: GM seed is apparently not passing the animation inside the scroll view. Edited to apply animation to both the HStack and the lone purple box
struct Square: View {
let color: Color
var body: some View {
Rectangle()
.fill(color)
.frame(width: 80, height: 80)
}
}
struct SquareAnimation: View {
#State private var enter = false
var body: some View {
VStack {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 15) {
Square(color: .red)
Square(color: .blue)
.opacity(self.enter ? 0.25 : 1)
.onTapGesture {
self.enter.toggle()
}
Square(color: .green)
.offset(x: self.enter ? 30 : 0)
Square(color: .red)
}
.animation(.easeInOut)
}
Square(color: .purple)
.offset(x: self.enter ? 80 : 0)
.animation(.easeInOut)
}
}
}
I am stuck with same problem. Solution by smr has helped. However, I was not able to get show/hide view animation. Following is an example:
struct Test: View {
#State var showView = false
var body: some View {
ScrollView {
Button(action: {
self.showView.toggle()
}) {
Text("Toggle View")
}
if showView {
Text("Some View")
}
}
.animation(.easeInOut)
}
}

Resources