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

SwiftUI实现ScrollView包裹垂直堆叠的Table与TextEditor

解决方案

更优实现方案(推荐)

直接禁用Table的内部滚动,让它自适应内容高度,外层ScrollView负责整体滚动。这种方式无需手动计算高度,代码更简洁:

import SwiftUI
struct Person: Identifiable {
    let givenName: String
    let familyName: String
    let emailAddress: String
    let id = UUID()
}
struct PeopleTable: View {
    @State private var people = [
        Person(givenName: "Juan", familyName: "Chavez", emailAddress: "juanchavez@icloud.com"),
        Person(givenName: "Mei", familyName: "Chen", emailAddress: "meichen@icloud.com"),
        Person(givenName: "Tom", familyName: "Clark", emailAddress: "tomclark@icloud.com"),
        Person(givenName: "Gita", familyName: "Kumar", emailAddress: "gitakumar@icloud.com"),
        Person(givenName: "Juan", familyName: "Chavez", emailAddress: "juanchavez@icloud.com"),
        Person(givenName: "Mei", familyName: "Chen", emailAddress: "meichen@icloud.com"),
        Person(givenName: "Tom", familyName: "Clark", emailAddress: "tomclark@icloud.com"),
        Person(givenName: "Gita", familyName: "Kumar", emailAddress: "gitakumar@icloud.com")
    ]

    @State private var text: String = loremIpsum
    var body: some View {
        ScrollView {
            Table(people) {
                TableColumn("Given Name", value: \.givenName)
                TableColumn("Family Name", value: \.familyName)
                TableColumn("E-Mail Address", value: \.emailAddress)
            }
            .scrollDisabled(true) // 禁用表格内部滚动,使其自适应内容高度
            TextEditor(text: $text).font(Font.system(size: 14))
        }
    }
}
#Preview {
    PeopleTable()
}

let loremIpsum = """
Pariatur neque enim occaecati ut inventore odio. Eius earum cumque ea placeat debitis nobis eos. Doloremque eum consectetur quos quia. Optio dignissimos quis iste. Nostrum animi vel doloribus et. Non delectus odio dolor in.

Eos ea aperiam est cupiditate eius quibusdam nulla. Sed sed aut labore blanditiis temporibus dolores. Doloribus vel expedita et possimus rerum. Doloribus ut vel nisi debitis molestias.

Pariatur quia eligendi et. Ipsa quae enim fugiat modi odit voluptatibus est. Officiis non impedit repellat omnis quod labore. Ratione ut iste ab ratione atque atque.

Quos nesciunt aut quos autem aut iusto repellendus. Error ex labore ad eaque dolorem. Laborum sed et ut incidunt mollitia omnis molestias. Reiciendis officiis alias quos expedita asperiores et culpa. Reiciendis nihil minima qui consequuntur. Maiores sint ut numquam facere ullam temporibus ea officiis.
"""

说明:scrollDisabled(true) 是iOS 16+、macOS Ventura+ 提供的API,能直接禁用Table的内部滚动,让它自动扩展高度以显示所有行,外层ScrollView会包含整个Table和TextEditor,实现滚动完表格才看到编辑器的效果。


兼容旧版本的动态高度方案

如果需要支持更早的系统版本,可以通过PreferenceKey监听Table的实际高度,动态更新frame:

import SwiftUI
struct Person: Identifiable {
    let givenName: String
    let familyName: String
    let emailAddress: String
    let id = UUID()
}

// 定义偏好键用于传递高度值
private struct TableHeightPreferenceKey: PreferenceKey {
    static var defaultValue: CGFloat = 0
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value = nextValue()
    }
}

struct PeopleTable: View {
    @State private var people = [
        Person(givenName: "Juan", familyName: "Chavez", emailAddress: "juanchavez@icloud.com"),
        Person(givenName: "Mei", familyName: "Chen", emailAddress: "meichen@icloud.com"),
        Person(givenName: "Tom", familyName: "Clark", emailAddress: "tomclark@icloud.com"),
        Person(givenName: "Gita", familyName: "Kumar", emailAddress: "gitakumar@icloud.com"),
        Person(givenName: "Juan", familyName: "Chavez", emailAddress: "juanchavez@icloud.com"),
        Person(givenName: "Mei", familyName: "Chen", emailAddress: "meichen@icloud.com"),
        Person(givenName: "Tom", familyName: "Clark", emailAddress: "tomclark@icloud.com"),
        Person(givenName: "Gita", familyName: "Kumar", emailAddress: "gitakumar@icloud.com")
    ]

    @State private var tableContentHeight: CGFloat = 0
    @State private var text: String = loremIpsum
    
    var body: some View {
        ScrollView {
            Table(people) {
                TableColumn("Given Name", value: \.givenName)
                TableColumn("Family Name", value: \.familyName)
                TableColumn("E-Mail Address", value: \.emailAddress)
            }
            .background(
                // 通过GeometryReader获取Table的实际高度
                GeometryReader { proxy in
                    Color.clear
                        .preference(key: TableHeightPreferenceKey.self, value: proxy.size.height)
                }
            )
            .onPreferenceChange(TableHeightPreferenceKey.self) { newHeight in
                tableContentHeight = newHeight
            }
            .frame(height: tableContentHeight)
            
            TextEditor(text: $text).font(Font.system(size: 14))
        }
    }
}
#Preview {
    PeopleTable()
}

let loremIpsum = """
Pariatur neque enim occaecati ut inventore odio. Eius earum cumque ea placeat debitis nobis eos. Doloremque eum consectetur quos quia. Optio dignissimos quis iste. Nostrum animi vel doloribus et. Non delectus odio dolor in.

Eos ea aperiam est cupiditate eius quibusdam nulla. Sed sed aut labore blanditiis temporibus dolores. Doloribus vel expedita et possimus rerum. Doloribus ut vel nisi debitis molestias.

Pariatur quia eligendi et. Ipsa quae enim fugiat modi odit voluptatibus est. Officiis non impedit repellat omnis quod labore. Ratione ut iste ab ratione atque atque.

Quos nesciunt aut quos autem aut iusto repellendus. Error ex labore ad eaque dolorem. Laborum sed et ut incidunt mollitia omnis molestias. Reiciendis officiis alias quos expedita asperiores et culpa. Reiciendis nihil minima qui consequuntur. Maiores sint ut numquam facere ullam temporibus ea officiis.
"""

说明:通过GeometryReader读取Table的高度,再用PreferenceKey将高度传递给父视图,动态更新Table的frame高度,实现自适应效果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 08:29:55