第十二章 TextField|EmptyView|SecureField

调用 PopMenuButton

对于 PopMenuButton 的封装已经完毕,我都迫不及待的想要添加到服务器选择上面。

我们新增一个属性获取当前可以选择服务器的数据源。

swift 复制代码
private var serverUrls:[String] = [
    AppServer.debug.rawValue,
    AppServer.release.rawValue
]

我们将 PopMenuButton 添加进 ServerSelectMenuView 里面。

swift 复制代码
var body: some View {
    LoginValueContentView(left: leftView,
                          center: centerView,
                          right: rightView)
        .popMenuButton(items: serverUrls,
                       currentItem: $viewModel.currentAppServer)
}

服务器选择组件终于做完了,没想到费了我们这么多的时间,主要我觉得是从之前自动布局换成这种线性布局,包括一些数据交互的处理发生了变化,导致我们没有完全适应。

使用 TextField 输入内容

接下来就是登陆页面输入用户名的界面,我们新建在 LoginPage 的 View中新建一个 UserNameValueContentView.swift,用来封装用户输入用户名。

swift 复制代码
struct UserNameValueContentView: View {
    @EnvironmentObject private var viewModel:LoginPageViewModel
    var body: some View {
        LoginValueContentView(left: icon,
                              center: userNameField,
                              right: EmptyView())
    }
    
    private var icon: some View {
        Image("user_icon_34_34")
    }
    
    private var userNameField:some View {
        TextField("请输入用户名", text: $viewModel.userName)
    }
}

界面十分的简单,我们用到了 TextField。 其实使用 TextField 非常的简单,我们传入一个 提示语和一个接受变更文本的 @Binding变量即可。

除了 TextField,我们还用到了一个 EmptyView 的空试图。这个 EmptyView 没有任何意思,只是作为语法里面的占位符而已,比如你不能传入空对象的时候。

为了可以接受到输入框输入的用户名,我们在 LoginPageViewModel 新增一个变量。

swift 复制代码
@Published var userName:String = ""

@Published这个我们也接触到一个陌生的属性包装器,和@State有什么区别呢?@State只能在视图的内部使用,虽然可以通过 @Binging进行传递使用,但是需要一层层的传递。但是@Published就不一样,只要两个视图拿到同一个对象,那么就通过 @Published 监听和修改对应的值,这就是做 MVVM的核心所在。

使用 SecureField 作为密码输入框

我们在 LoginPage View 文件夹创建一个 PasswordValueContentView.swift用户组件输入密码的组件。

swift 复制代码
struct PasswordValueContentView: View {
    @EnvironmentObject private var viewModel:LoginPageViewModel
    var body: some View {
        LoginValueContentView(left: icon,
                              center: passwordField,
                              right: EmptyView())
    }
    
    private var icon:some View {
        Image("password_icon_34x34")
    }
    
    private var passwordField:some View {
        SecureField("请输入密码", text: $viewModel.password)
    }
}

我们在封装输入密码的组件里面用到了 SecureFieldSecureFieldTextField 的区别在于,输入的密码是明文还是密文。

我们将 UserNameValueContentViewPasswordValueContentView.swift 添加到 LoginPage中。

swift 复制代码
ServerSelectMenuView()
    .padding(.leading,45)
    .padding(.trailing,45)
Spacer()
    .frame(height:30)
UserNameValueContentView()
    .padding(.leading,45)
    .padding(.trailing,45)
Spacer()
    .frame(height:30)
PasswordValueContentView()
    .padding(.leading,45)
    .padding(.trailing,45)

虽然我们得到我们想要的界面效果,但是我们的代码感觉很重复,每个组件都需要设置 Padding进行对其,并且组件和组件之间还要设置间隙。这个不就是VStack该做的事情吗?我们修改代码如下。

swift 复制代码
VStack(spacing:30) {
    ServerSelectMenuView()
    UserNameValueContentView()
    PasswordValueContentView()
}
.padding(.leading,45)
.padding(.trailing,45)

我们将代码精简了需求,同时一样的效果,所以在后续代码的增多,合理的利用组件精简代码。

相关推荐
君赏4 小时前
第八章 封装MVVM|onTapGesture|AppStorage
swiftui
君赏4 小时前
第四章 Preview Device|Expand|Alignment|LineLimit|Rectangle|ForegroundColor
swiftui
君赏4 小时前
第七章 组件提炼|代码清爽|Padding
swiftui
君赏4 小时前
第五章 如何使用Xcode Package Injection加速依赖Swift Package Manager
swiftui
君赏4 小时前
第十章 ScrollView|Top布局|SF符号|@StateObject|@State|@Binding
swiftui
君赏4 小时前
第三章 初见VStack|Image|Spacer|.Frame
swiftui
君赏6 小时前
第一章 前言
swiftui
君赏6 小时前
第二章 创建项目
swiftui
qAICHjag4 天前
MATLAB Simulink主动均衡电路模型下的汽车级锂电池动力模组管理 基于模糊控制策略...
swiftui