You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI:如何对齐HStack内银行营业时间并修复多时段间距问题

问题描述

我有一个SwiftUI视图用来展示银行营业时间,日期在左侧、时段在右侧,功能正常但存在问题:单个日期对应多个时段时,第二个时段会和下一个日期的内容错位。需求是同一日期的多个时段之间无间距,仅不同日期的内容之间添加间距。

原代码

struct OpeningHours: View {
    let titles: [String]
    let hours: [String]
    
    init(titles: [String], hours: [String]) {
        self.titles = titles
        self.hours = hours
    }
    
    var body: some View {
        HStack(alignment: .top, spacing: .zero) {
            VStack(alignment: .leading,spacing: .zero) {
                ForEach(titles, id: \.self) { title in
                    Text(title)
                        .rchFont(.rchBody)
                        .fixedSize(horizontal: false, vertical: true)
                        .multilineTextAlignment(.leading)
                        .padding(.trailing, .md)
                        .padding(.bottom, RCHPadding.xs.size + RCHPadding.sm.size)
                }
            }
            Spacer()
            
            VStack(alignment: .trailing, spacing: .zero) {
                ForEach(hours, id: \.self) { hour in
                    Text(hour)
                        .fixedSize(horizontal: false, vertical: true)
                        .multilineTextAlignment(.trailing)
                        .rchFont(.rchBodyBold)
                        .padding(.bottom, RCHPadding.xs.size + RCHPadding.sm.size)
                }
            }
        }
        .padding(.top, .xs)
    }
}

数据源示例

"specialOpeningTimes": [
    {
        "openingTimeType": "ONE_DATE",
        "fromDate": "2023-10-09",
        "toDate": null,
        "timeRanges": [
            {
                "fromTime": "09:00",
                "toTime": "12:00"
            },
            {
                "fromTime": "09:00",
                "toTime": "12:00"
            }
        ]
    }
]
解决方案

问题根源在于原视图将日期和时段拆分为两个独立的VStack,当单个日期对应多个时段时,左右条目数量不匹配,叠加的padding导致错位。我们需要重构数据结构和视图层级来解决:

1. 定义分组数据模型

先把日期和对应的多个时段封装成一个模型,确保数据结构和展示逻辑匹配:

// 对应数据源的解析模型
struct SpecialOpeningTime: Decodable {
    let openingTimeType: String
    let fromDate: String
    let toDate: String?
    let timeRanges: [TimeRange]
}

struct TimeRange: Decodable {
    let fromTime: String
    let toTime: String
}

// 用于视图展示的分组模型
struct OpeningTimeGroup: Identifiable {
    let id = UUID()
    let dateTitle: String
    let timeRanges: [String]
}

2. 修改OpeningHours视图

调整视图层级,按日期分组展示,同一日期的时段无间距,不同日期组之间添加间距:

struct OpeningHours: View {
    let timeGroups: [OpeningTimeGroup]
    
    var body: some View {
        // 外层VStack控制不同日期组之间的间距
        VStack(spacing: RCHPadding.xs.size + RCHPadding.sm.size) {
            ForEach(timeGroups) { group in
                HStack(alignment: .top, spacing: .zero) {
                    // 左侧日期:每个组仅显示一次
                    Text(group.dateTitle)
                        .rchFont(.rchBody)
                        .fixedSize(horizontal: false, vertical: true)
                        .multilineTextAlignment(.leading)
                        .padding(.trailing, .md)
                    
                    Spacer()
                    
                    // 右侧时段列表:同一日期的时段之间无间距
                    VStack(alignment: .trailing, spacing: .zero) {
                        ForEach(group.timeRanges, id: \.self) { time in
                            Text(time)
                                .fixedSize(horizontal: false, vertical: true)
                                .multilineTextAlignment(.trailing)
                                .rchFont(.rchBodyBold)
                        }
                    }
                }
            }
        }
        .padding(.top, .xs)
    }
}

3. 数据源转换

将原始JSON数据转换为视图所需的分组模型:

// 假设已解析得到specialOpeningTimes数组
let specialTimes: [SpecialOpeningTime] = ...
let timeGroups = specialTimes.map { time in
    // 可根据需求格式化日期字符串,比如转为"10月09日"
    let dateTitle = time.fromDate
    // 把每个时段转为字符串格式
    let timeStrings = time.timeRanges.map { range in
        "\(range.fromTime)-\(range.toTime)"
    }
    return OpeningTimeGroup(dateTitle: dateTitle, timeRanges: timeStrings)
}

// 使用视图
OpeningHours(timeGroups: timeGroups)

思路说明

  • 数据驱动视图:通过分组模型确保每个日期和其对应的时段绑定,避免左右视图条目数量不一致的问题。
  • 分层控制间距:外层VStack负责不同日期之间的间距,内部VStack负责同一日期时段的无间距展示,精准控制间距位置。
  • 移除冗余padding:把原单个Text的bottom padding转移到组与组之间,避免不必要的空隙叠加。

内容的提问来源于stack exchange,提问作者user20273483

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 20:13:17