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

如何在SwiftUI中实现文本内容的展开/收起功能

SwiftUI实现文本超过指定高度时的展开/收起功能

要实现这个需求,核心是先测量文本的实际高度,判断是否超过阈值后再决定是否显示切换按钮,同时通过状态控制文本的折叠/展开状态,具体实现如下:

第一步:定义状态变量

在视图中添加两个@State变量,分别控制文本的折叠状态,以及是否需要显示切换按钮:

@State private var isCollapsed = true
@State private var shouldShowToggleButton = false
private let maxCollapsedHeight: CGFloat = 200 // 设定折叠状态的最大高度

第二步:完整视图实现

把文本和按钮整合到VStack中,通过GeometryReader测量文本高度,控制显示逻辑:

var body: some View {
    VStack(alignment: .leading) {
        Text(message)
            .font(.light16)
            .foregroundColor(.black)
            .multilineTextAlignment(.leading)
            .padding(.bottom, 8)
            // 控制文本的高度:折叠时限制最大高度,展开时不限制
            .frame(maxHeight: isCollapsed ? maxCollapsedHeight : .infinity)
            .clipped() // 超出部分截断
            // 通过背景的GeometryReader测量文本实际高度
            .background(
                GeometryReader { proxy in
                    Color.clear
                        .onAppear {
                            // 文本渲染完成后,判断实际高度是否超过阈值
                            shouldShowToggleButton = proxy.size.height > maxCollapsedHeight
                        }
                        .onChange(of: message) { _ in
                            // 如果文本内容变化,重新判断高度
                            shouldShowToggleButton = proxy.size.height > maxCollapsedHeight
                        }
                }
            )
        
        // 只有当文本高度超过阈值时,才显示切换按钮
        if shouldShowToggleButton {
            Button {
                isCollapsed.toggle()
            } label: {
                Text(isCollapsed ? "展开全文" : "收起全文")
                    .font(.bold14)
                    .foregroundColor(.blue)
                    .padding(.bottom, 8)
            }
        }
        
        // 原视图中的其他内容...
        // ...
    }
}

关键逻辑说明

  • 测量文本高度:利用GeometryReader作为文本的背景,因为背景会完全贴合文本的实际尺寸,所以能准确获取文本的高度。在onAppear和文本内容变化时(onChange(of: message)),判断高度是否超过设定的200px,从而决定是否显示切换按钮。
  • 控制文本折叠/展开:通过frame(maxHeight:)来限制文本高度,折叠时设置为200px,同时用.clipped()把超出部分截断;展开时设为.infinity,让文本完整显示。
  • 按钮显示逻辑:只有当文本实际高度超过阈值时,才渲染切换按钮,避免内容较短时出现多余按钮。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 10:40:25