最近尝试使用 SwiftUI 。 使用导航时,从一个屏幕转到另一个屏幕时,UI 会不断中断。 我在从一个屏幕导航到另一个屏幕时使用 NavigationStack 和 NavigationLink。
原始登录屏幕/从 GetStarted 屏幕导航后的登录屏幕的屏幕截图:
import SwiftUI
struct GetStartedScreen: View {
var body: some View {
NavigationStack {
GeometryReader { geometry in
VStack {
HStack {
Text("Your Thoughts")
.font(.system(size: 30))
Text("Cleaner")
.foregroundColor(Color(red: 0.0, green: 0.545, blue: 0.545))
.font(.system(size: 30))
.bold()
}
.padding(.top, 40)
.frame(maxWidth: .infinity, alignment: .center)
Text("Let the music take control!")
.font(.system(size: 20))
.padding(.top, 16)
.frame(maxWidth: .infinity, alignment: .center)
Image("Yoga")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: geometry.size.width * 0.90, height: geometry.size.height * 0.66)
Spacer()
NavigationLink(destination: LoginScreen()) {
Text("Get Started →")
.frame(width: geometry.size.width * 0.70)
.font(.system(size: 20))
.bold()
.foregroundColor(.white)
.padding()
.background(Color(red: 0.0, green: 0.545, blue: 0.545))
.cornerRadius(10)
}
.padding(.bottom , 40)
}
}
}
}
}
struct ForgotUsername: View {
@State private var username: String = ""
@State private var phoneNumber: String = ""
@State private var email: String = ""
@State private var isPhoneNumber: Bool = true
@FocusState private var isUsernameFieldFocused: Bool
@FocusState private var isPhonenumberFieldFocused: Bool
@FocusState private var isEmailFieldFocused: Bool
var body: some View {
GeometryReader { geometry in
NavigationStack {
VStack {
Image("SignIn")
.padding(EdgeInsets(top: 100, leading: 0, bottom: 10, trailing: 0))
VStack {
Text("Login")
.font(.system(size: 28))
.bold()
.padding(EdgeInsets(top: 16, leading: 0, bottom: 4, trailing: 0))
HStack {
Text("Welcome To")
.font(.system(size: 26))
Text("Soundly")
.foregroundColor(Color(red: 0.0, green: 0.545, blue: 0.545))
.font(.system(size: 26))
.bold()
}
Text("Enter your registered \n \(isPhoneNumber ? "Phone Number" : "Email")")
.font(.system(size: 22))
.multilineTextAlignment(.center)
.padding(EdgeInsets(top: 4, leading: 16, bottom: 0, trailing: 16))
VStack(alignment: .leading) {
HStack(alignment: .center) {
Text(isPhoneNumber ? "Phone Number" : "Email")
.font(.system(size: 14))
Spacer()
Button(action: {
isPhoneNumber.toggle()
}) {
Text("via \(isPhoneNumber ? "Email" : "Phone")")
.foregroundColor(.teal)
.bold()
.font(.system(size: 10))
}
}
if isPhoneNumber {
TextField("Enter your phone number", text: $phoneNumber)
.padding()
.background(Color.clear)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(!isPhonenumberFieldFocused ? Color.gray : Color.black, lineWidth: 1)
)
.cornerRadius(10)
.padding(.bottom, 10)
.focused($isPhonenumberFieldFocused)
} else {
TextField("Enter your email", text: $email)
.padding()
.background(Color.clear)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(!isEmailFieldFocused ? Color.gray : Color.black, lineWidth: 1)
)
.cornerRadius(10)
.padding(.bottom, 10)
.focused($isEmailFieldFocused)
}
}
.padding(EdgeInsets(top: 10, leading: 16, bottom: 0, trailing: 16))
NavigationLink(destination: OTPScreen(isPhoneNumber: isPhoneNumber, contactInfo: isPhoneNumber ? phoneNumber : email)) {
Text("Continue")
.frame(width: geometry.size.width * 0.85)
.font(.system(size: 20))
.bold()
.foregroundColor(.white)
.padding()
.background(Color(red: 0.0, green: 0.545, blue: 0.545))
.cornerRadius(10)
}
Spacer()
}
.frame(width: geometry.size.width, height: geometry.size.height * 0.62)
.background(Color(red: 213/255, green: 234/255, blue: 234/255, opacity: 1.0))
.cornerRadius(50)
.padding()
}
.toolbar {
ToolbarItem(placement: .automatic) {
HStack {
Spacer()
Image("S")
Text("Soundly")
.font(.system(size: 28))
Button {
// action
} label: {
Text("Login")
.foregroundColor(Color(red: 0.0, green: 0.545, blue: 0.545))
.bold()
.font(.system(size: 20))
}
.padding(.leading, 40)
}
}
}
}
.ignoresSafeArea(.keyboard)
}
}
}
感谢您的帮助!
尝试过视频教程但没有效果
在
GetStartedScreen
中,有一个 NavigationLink
将您带到 LoginScreen
,这可能就是您正在显示的屏幕截图。但是,您似乎提供了 ForgotUsername
而不是 LoginScreen
的代码。
无论如何,假设
LoginScreen
和ForgotUsername
相似,我建议对ForgotUsername
进行这些更改:
GeometryReader
。您可以使用它来查找屏幕的尺寸。如果您让组件适合可用空间,而不是强制它们的大小,那么效果可能会更好。Image("SignIn")
.resizable()
.scaledToFit()
// .padding(EdgeInsets(top: 100, leading: 0, bottom: 10, trailing: 0))
.padding(.top, 100)
Image("S")
.resizable()
.scaledToFit()
.frame(height: 50)
maxWidth: .infinity
。如果您想要侧面有一些空间,只需添加填充即可。顺便说一句,.cornerRadius
已弃用,最好使用 .clipShape
代替:Text("Continue")
// .frame(width: geometry.size.width * 0.85)
.frame(maxWidth: .infinity)
.font(.system(size: 20))
.bold()
.foregroundColor(.white)
.padding()
.background(Color(red: 0.0, green: 0.545, blue: 0.545))
.clipShape(RoundedRectangle(cornerRadius: 10))
.padding(.horizontal)
maxHeight: .infinity
来使用完整高度,或者如果您想确保面板至少达到一定高度,则可以使用 minHeight
,并在需要时添加填充:VStack {
Text("Login")
// ...
}
// .frame(width: geometry.size.width, height: geometry.size.height * 0.62)
.frame(maxWidth: .infinity, minHeight: 380)
.background(Color(red: 213/255, green: 234/255, blue: 234/255, opacity: 1.0))
.clipShape(RoundedRectangle(cornerRadius: 50))
.padding()
.padding(.bottom, 20)
希望这可以帮助您入门并解决内容不合适的主要问题。仅通过上述更改,
ForgotUsername
看起来像这样: