继续
续接上篇文章,我们在一个简单的登陆界面中实现了表单提示,然后再自动聚焦到输入框中。
那么按照正常的登陆流程,接下来我们应该是进行跳转,然后展示一个带有底部导航栏的的页面
最终的结果如下:
重新整理逻辑
按照原定计划,我现在要做的是一个todolist的小app
那么我们重新整理一下初次进入的交互逻辑
- 打开是首页
- 发现没有登陆
- 弹出提示框请登录,这个框只有一个按钮,名为去登录
- 点击后弹出一个登陆界面,即我们之前编写的那个
- 登陆完成后关闭自己即可,即返回首页
一个新的页面
我们新建一个文件 IndexView.swift
这个文件为首页,除了上述的首页的登陆判断逻辑以及弹出登陆表单之外
它应该具有一个底部的tabbar
既然作为首页,首先就要修改入口文件处的引用
将 helloworldApp.swift 文件中的 ContentView() 改为 IndexView()
IndexView.swift 内容如下:
import SwiftUI
// 假设这里是 todo list 的页面
struct TodoView:View{
var body:some View{
Text("这里是todo页面")
}
}
// 假设这里是 设置的页面
struct SettingView:View{
var body:some View{
Text("这里是设置页面")
}
}
struct IndexView: View{
// 是否已经登陆
@State private var isLogin:Bool = false;
// 显示提示登陆
@State private var showAlert:Bool = true;
// 显示登陆表单
@State private var showLogin:Bool = false;
var body: some View{
VStack{
// 一个简单的tabview,底部导航栏
TabView {
TodoView()
.tabItem {
Image(systemName: "list.dash")
Text("TODO")
}
SettingView()
.tabItem {
Image(systemName: "gear.circle")
Text("设置")
}
}
.font(.headline)
}.alert(isPresented: $showAlert){
// 提示登陆的Alert
Alert(
title: Text("提示"),
message: isLogin ? Text("您已登录!") : Text("您尚未登陆,请登录!"),
dismissButton: isLogin ? .default(Text("好的")):.destructive(Text("去登录")){
// 显示login表单
showLogin = true;
}
)
}
// .sheet 会弹出一个类似vue中模态框的东西
// .sheet(isPresented:$showLogin,onDismiss: {
// // 避免被手动下滑关闭
// showLogin = true;
// } ,content: {
// ContentView()
// })
// 这种会直接弹出页面占据全屏
.fullScreenCover(isPresented: $showLogin ,content: {
ContentView()
})
}
}
struct IndexView_Previews: PreviewProvider {
static var previews: some View {
IndexView()
}
}
以下将 .fullScreenCover 和 .sheet 两种形式的结果都展示出来
ContentView 中新增如下代码
struct ContentView: View {
@Environment(\.presentationMode) var presentationMode;
// ... 省略部分代码、
if(res == "登陆成功" || res == "请输入。。。"){
focus = .clear
// 这里需要返回首页,登陆成功后销毁本页面
self.presentationMode.wrappedValue.dismiss()
}
}
总结
- 这里只涉及到了跳转的 sheet 和 fullscreencover 两种形式
- 还有navigationView 后续在其他功能中介绍
- 登陆的状态没有被传递,导致了一些问题
- 如果类比vue组件的话,这里应该有组件间传值才更合理