SwiftUI 登录页面布局

2023-12-03

我正在探索 SwiftUI,因为我正在尝试构建登录视图,现在我面临一个问题

这就是我想要实现的目标:

What I already achieved

正如你所看到的,我已经达到了这一点,但我不喜欢我的实现

struct ContentView : View {
@State var username: String = ""
var body: some View {
    VStack(alignment: .leading) {
        Text("Login")
            .font(.title)
            .multilineTextAlignment(.center)
            .lineLimit(nil)
            Text("Please")
                .font(.subheadline)

        HStack {
            VStack (alignment: .leading, spacing: 20) {
                Text("Username: ")
                Text("Password: ")

            }
            VStack {
                TextField($username, placeholder: Text("type something here..."))
                .textFieldStyle(.roundedBorder)
                TextField($username, placeholder: Text("type something here..."))
                    .textFieldStyle(.roundedBorder)
                }
            }
        }.padding()
    }
}

因为为了使用户名和密码文本在文本字段的中间精确对齐,我必须将文字间距值设置为20 in the VStack我不喜欢它,因为它很可能无法在不同的设备尺寸上工作。

有人看到更好的方法来达到相同的结果吗?

Thanks


我们将实施两个新的View修饰符方法,这样我们就可以这样写:

struct ContentView: View {
    @State var labelWidth: CGFloat? = nil
    @State var username = ""
    @State var password = ""

    var body: some View {
        VStack {
            HStack {
                Text("User:")
                    .equalSizedLabel(width: labelWidth, alignment: .trailing)
                TextField("User", text: $username)
            }
            HStack {
                Text("Password:")
                    .equalSizedLabel(width: labelWidth, alignment: .trailing)
                SecureField("Password", text: $password)
            }
        }
        .padding()
        .textFieldStyle(.roundedBorder)
        .storeMaxLabelWidth(in: $labelWidth)
    }
}

两个新的修饰符是equalSizedLabel(width:alignment:) and storeMaxLabelWidth(in:).

The equalSizedLabel(width:alignment)修改器做了两件事:

  1. 它应用了width and alignment其内容(Text(“User:”) and Text(“Password:”) views).
  2. 它测量其内容的宽度并将其传递给任何需要它的祖先视图。

The storeMaxLabelWidth(in:)修饰符接收由以下测量的宽度equalSizedLabel并将最大宽度存储在$labelWidth我们将绑定传递给它。

那么,我们如何实现这些修饰符呢?我们如何将值从后代视图传递到祖先视图?在 SwiftUI 中,我们使用(当前未记录的)“偏好”系统来做到这一点。

为了定义一个新的首选项,我们定义一个符合以下条件的类型PreferenceKey。为符合PreferenceKey,我们必须定义我们的偏好的默认值,并且我们必须定义如何组合多个子视图的偏好。我们希望我们的偏好是所有标签的最大宽度,因此默认值为零,我们通过取最大值来组合偏好。这是PreferenceKey我们将使用:

struct MaxLabelWidth: PreferenceKey {
    static var defaultValue: CGFloat { 0 }
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value = max(value, nextValue())
    }
}

The preference修饰符函数设置一个偏好,所以我们可以说.preference(key: MaxLabelWidth.self, value: width)设置我们的偏好,但我们必须知道什么width设置。我们需要使用一个GeometryReader来获得宽度,正确地做到这一点有点棘手,所以我们将它包裹在一个ViewModifier像这样:

extension MaxLabelWidth: ViewModifier {
    func body(content: Content) -> some View {
        return content
            .background(GeometryReader { proxy in
                Color.clear
                    .preference(key: Self.self, value: proxy.size.width)
            })
    }
}

上面发生的事情是我们附加一个背景View到内容,因为背景始终与其附加的内容具有相同的大小。的背景View is a GeometryReader,其中(通过proxy) 提供对其自身大小的访问。我们必须给予GeometryReader它自己的内容。由于我们实际上不想显示原始内容背后的背景,因此我们使用Color.clear as the GeometryReader的内容。最后,我们使用preference修饰符将宽度存储为MaxLabelWidth偏爱。

现在可以定义equalSizedLabel(width:alignment:) and storeMaxLabelWidth(in:)修改方法:

extension View {
    func equalSizedLabel(width: CGFloat?, alignment: Alignment) -> some View {
        return self
            .modifier(MaxLabelWidth())
            .frame(width: width, alignment: alignment)
    }
}

extension View {
    func storeMaxLabelWidth(in binding: Binding<CGFloat?>) -> some View {
        return self.onPreferenceChange(MaxLabelWidth.self) {
            binding.value = $0
        }
    }
}

结果如下:

result screenshot

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SwiftUI 登录页面布局 的相关文章

  • 如何开始复杂级别的跨平台移动应用开发? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 为什么performSegueWithIdentifier在viewDidLoad中不起作用?

    我试图在视图控制器上调用 viewDidLoad 后立即触发故事板转场 Segue 附加了一个标识符 当从链接到按钮或其他控件的方法内部调用时 它可以正常工作 但它在 viewDidLoad 内部不起作用 它只是默默地失败了 viewDid
  • iOS、通用链接、Swift。 continueUserActivity 未调用

    我正在为我们的 iOS 应用程序实现通用链接 这是我的一小部分 AppDelegate private func application application UIApplication openURL url URL sourceApp
  • 将自定义数据包含到 iOS 故障转储中

    你好 堆栈溢出 有一个简单的问题要问您 当我的应用程序在用户的设备上崩溃时 是否可以将自定义错误数据嵌入到自动生成的 iOS 故障转储中 例如 我的 SQlite 数据库由于某种原因无法运行 例如 数据库文件已损坏 我无法从这个错误中恢复
  • 错误域=kAFAssistantErrorDomain 代码=209“(空)”

    我面临着一个问题SFSpeechRecognizer 启动应用程序几秒钟后 我开始收到错误消息 错误域 kAFAssistantErrorDomain 代码 209 空 和 错误 域 kAFAssistantErrorDomain 代码 2
  • iOS:生成pdf时绘制文本时如何设置字体?

    我在ios应用程序中使用drawpdf函数生成pdf 同时调用nsobject类中的drawtext函数 它根据我指定的框架和字符串清楚地绘制文本 我的代码是 void drawText NSString textToDraw inFram
  • Swift,以编程方式更改 UICollectionViewCell 和 UILabel(单元格内)的宽度

    我已将单元格 UICollectionViewCell 的宽度设置为等于 UICollectionView 的宽度 并且我尝试对该单元格中包含的 UILabel 执行完全相同的操作 我认为下面的代码准确地解释了我想要实现的目标 所以我在这里
  • 为什么 iOS 启动屏幕很慢?

    我的 iOS 应用程序启动屏幕大约需要 3 5 秒 我有一张将在启动屏幕后加载的地图 我的用户必须等待启动屏幕加载 然后再等待 3 秒才能加载地图 有没有办法最大限度地减少启动屏幕时间 基本上这种延迟意味着you在启动过程中做了一些非常错误
  • 如何让UITextView背景线与文字对齐?

    我正在尝试绘制 UITextView 的背景线 这是我用来画这些线的代码 CGContextBeginPath context CGContextSetStrokeColorWithColor context self horizontal
  • Swift - 元类型 .Type 和 .self 之间有什么区别?

    元类型有什么区别 Type and self在斯威夫特 Do self and Type返回一个struct 我明白那个 self可以用来检查dynamicType 你如何使用 Type 首先也是最重要的是查看 Apple 文档type o
  • ReactiveCocoa 将 SignalProducers 合二为一

    我正在使用 ReactiveCocoa 并且我有几个 SignalProducers let center NSNotificationCenter defaultCenter let signalProducer1 center rac
  • 贴纸包会在模拟器上使 iMessage 崩溃,但在 iPhone 上不会崩溃

    按照 Apple 的在线说明和视频在 Xcode 中创建了一个贴纸包 所有图像的尺寸均正确且远低于文件大小阈值 如果我在我的实体 iPhone 上构建并运行贴纸包 一切都会完美运行 如果我在模拟器上构建并运行贴纸包 对于任何模拟的 iPho
  • watchOS 错误:控制器接口描述中的未知属性

    我将 WKInterfacePicker 添加到情节提要中 并将其连接到界面控制器中的 IBOutlet 运行应用程序时 它在控制台中显示一条错误消息 控制器的接口描述 watchPicker 中的未知属性 Code interface I
  • 如何在button.addTarget操作中发送多个按钮?斯威夫特3

    如何将button和button2发送到我的pressButton2函数中 当用户触摸按钮2时 我需要更改按钮和按钮2的颜色 当我的 button2 addTarget 看起来像这样时 我收到错误 表达式列表中存在预期表达式 import
  • UItextView 背景颜色 Linespacing 区域太

    我正在尝试在 UITextView 中复制文本突出显示 不是搜索文本突出显示 但我也被行间距的颜色所困扰 我该如何纠正这个问题 现在的情况 期望的结果 我已将以下属性添加到我的 UiTextview 的属性文本中 对于段落行间距 我使用了以
  • 在实例化对象之前是否可以检查故事板中是否存在标识符?

    在我的代码中我有这一行 但我想知道是否有办法检查是否 一些控制器 在我将它与 一起使用之前就存在实例化ViewControllerWithIdentifier 方法 如果标识符不存在 则应用程序崩溃 如果没有好的方法 这并不是一个大问题 我
  • 使用 MapKit 的地形和卫星视图

    我是 Mapkit View 的新手 当我给出没有目的地的纬度和经度时 我想显示 MapKit中是否可以通过地形 卫星视图来显示地图 有教程链接吗 我看过一些访问 Google 地图 API html 文件 的示例 有必要吗 或者您可以通过
  • SpriteKit的更新函数:时间与帧率

    一般来说 我对编程和 Spritekit 很陌生 并且有兴趣探索毫秒和帧率之间的关系 以及如何使用更新函数作为两者之间的中介 帧率与毫秒 从本质上讲 帧速率和时间之间的主要区别在于时间始终一致 而帧速率则不然 由于密集的图形程序 它可能会下
  • 是否可以跨 2 个不同的 iOS 应用程序访问数据?

    假设我在 App1 中存储了一些 ID 数据 并希望在同一设备上的 App2 中访问它 平台上可以这样吗 如果没有的话有什么解决方法吗 您可以使用iOS 钥匙扣 http developer apple com library ios do
  • 像 TraceGL 一样分析 Objective C 中的代码路径?

    TraceGL 是一个非常简洁的项目 它允许 JS 程序员跟踪 Javascript 中的代码路径 它看起来像这样 我想为 Objective C 构建类似的东西 我知道运行时使跟踪方法调用变得相当容易 但是我如何跟踪控制流 例如 在上面的

随机推荐