导航视图中视图之间的突然转换
Posted
技术标签:
【中文标题】导航视图中视图之间的突然转换【英文标题】:Abrupt transition between views within a Navigation View 【发布时间】:2021-09-05 19:57:53 【问题描述】:我无法弄清楚如何从我的 SignInView() 顺利导航到我的 FirstView()。我的 FirstView() 在 Navigation Stack 中,但是视图之间的转换非常突然,并且没有通常使用 NavigationLink 获得的转换。我怎样才能让过渡工作?
非常感谢!
这里是相关代码...
struct ContentView: View
@EnvironmentObject var viewModel: AppViewModel
var body: some View
VStack
NavigationView
if viewModel.signedIn
FirstView()
.transition(.slide)
else
//.onAppear method is used for keyboard management (See Misc Functions...)
SignInView()
.onAppear(perform: UIApplication.shared.addTapGestureRecognizer)
.navigationBarHidden(true)
.onAppear
viewModel.listen()
class AppViewModel: ObservableObject
private var db = Firestore.firestore()
@Published var userInfo: User?
@Published var signedIn: Bool = false
var handle: AuthStateDidChangeListenerHandle?
let authRef = Auth.auth()
var authHandle : AuthStateDidChangeListenerHandle?
var rootInfoCollection : CollectionReference!
var userIdRef = ""
func fetchUserData()
db.collection("Users").document("\(userIdRef)").getDocument document, error in
// Check for error
if error == nil
// Check that this document exists
if document != nil && document!.exists
self.userInfo = document.map (documentSnapshot) -> User in
let data = documentSnapshot.data()
let uid = data?["uid"] as? UUID ?? UUID()
let company = data?["company"] as? String ?? ""
let name = data?["name"] as? String ?? ""
let admin = data?["admin"] as? Bool ?? false
let photo = data?["photo"] as? String ?? ""
return User(uid: uid, company: company, name: name, admin: admin, photo: photo)
withAnimation
self.signedIn = true
func listen()
handle = authRef.addStateDidChangeListener( auth, user in
print(user?.email ?? "No User Found")
if let user = auth.currentUser
self.userIdRef = user.uid
self.rootInfoCollection = Firestore.firestore().collection("/Users/")
DispatchQueue.main.async
self.fetchUserData()
else
self.signedIn = false
)
func signIn(email: String, password: String)
authRef.signIn(withEmail: email, password: password) result, error in
guard result != nil, error == nil else
return
struct SignInView: View
@EnvironmentObject var viewModel: AppViewModel
@State private var username : String = ""
@State private var password : String = ""
@State private var shouldShowLoginAlert: Bool = false
@State var selectedImageArray : [Image] = []
var disableLoginButton : Bool
return self.username.isEmpty || self.password.isEmpty
var body: some View
VStack
Image(uiImage: #imageLiteral(resourceName: "awText"))
.resizable()
.frame(width: 180, height: 100)
.padding(.bottom, 50)
TextField("Email", text: $username)
.padding(.leading)
.disableAutocorrection(true)
.autocapitalization(.none)
Rectangle().fill(Color.gray.opacity(0.25)).frame(height: 1, alignment: .center).padding(.bottom)
.padding(.bottom)
.onChange(of: self.username, perform: value in
if value.count > 10
self.username = String(value.prefix(20)) //Max 10 Characters for Username.
)
SecureField("Password", text: $password)
.padding(.leading)
.disableAutocorrection(true)
.autocapitalization(.none)
Rectangle().fill(Color.gray.opacity(0.25)).frame(height: 1, alignment: .center)
.onChange(of: self.username, perform: value in
if value.count > 10
self.username = String(value.prefix(10)) //Max 10 Characters for Password.
)
//SignIn Button
Button(action:
viewModel.signIn(email: username, password: password)
, label:
Text("Sign In")
.disabled(disableLoginButton)
.frame(width: 300, height: 50)
.background(Color.green)
.clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous))
.padding()
)
【问题讨论】:
您可以尝试使用FirstView().transition(.slide)
吗?你怎么看?
不幸的是这没用..
oups 是的,你需要使用withAnimation
,有人在下面发布了答案
【参考方案1】:
用您自己的动画替换默认的NavigationView
行为并不一定很简单。我将列出一种可能性,但另一种可能是使用真正的NavigationView
转换,但是一旦您使用FirstView
,只需隐藏后退按钮。
要自己进行转换,您需要 一个 到NavigationView
的根元素、一个if
子句、一个transition(.slide)
和withAnimation
。这是您的代码的简化版本,仅显示了这些元素:
class AppViewModel: ObservableObject
@Published var signedIn = false
struct FirstView : View
var body: some View
Text("Signed in")
struct ContentView: View
@StateObject var viewModel = AppViewModel()
var body: some View
NavigationView
VStack
if viewModel.signedIn
FirstView()
.transition(.slide)
else
Button("Sign me in")
withAnimation
viewModel.signedIn = true
.frame(maxWidth: .infinity, maxHeight: .infinity)
.navigationBarHidden(true)
【讨论】:
不幸的是,这也不起作用:( @RapsIn4 如果您将我提供的代码复制并粘贴到 Xcode 中,它就可以工作。你能确定你的实施有什么不同吗? 我更新了上面的代码以反映您的建议。除了使用 Firebase 之外,我看不出代码有任何差异。 有很大的不同——看VStack
和NavigationView
的顺序
哈哈,就是这样!不敢相信我错过了。我真的很感谢你帮我解决这个问题。谢谢!以上是关于导航视图中视图之间的突然转换的主要内容,如果未能解决你的问题,请参考以下文章