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

SwiftUI技巧:滚动手势下实现ZStack覆盖上方视图

需求实现:滚动时让ZStack覆盖顶部视图

我有一个包含两部分的界面:

  • 第一部分:"For You"标题、用户头像,搭配搜索栏
  • 第二部分:嵌套ForEach的ZStack,展示多个重叠的彩色矩形

期望效果:向上滚动矩形区域时,ZStack能向上移动并覆盖第一部分视图。

修改后的完整可运行代码

import SwiftUI

// 补充代码中缺失的Tag结构体
struct Tag: Identifiable {
    let id: UUID
    let name: String
    let color: String
}

// 补充HEX颜色转换扩展
extension Color {
    init(hex: String) {
        let cleanHex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
        var hexValue: UInt64 = 0
        Scanner(string: cleanHex).scanHexInt64(&hexValue)
        
        let a, r, g, b: UInt64
        switch cleanHex.count {
        case 3:
            (a, r, g, b) = (255, (hexValue >> 8) * 17, (hexValue >> 4 & 0xF) * 17, (hexValue & 0xF) * 17)
        case 6:
            (a, r, g, b) = (255, hexValue >> 16, hexValue >> 8 & 0xFF, hexValue & 0xFF)
        case 8:
            (a, r, g, b) = (hexValue >> 24, hexValue >> 16 & 0xFF, hexValue >> 8 & 0xFF, hexValue & 0xFF)
        default:
            (a, r, g, b) = (1, 1, 1, 0)
        }
        
        self.init(
            .sRGB,
            red: Double(r) / 255,
            green: Double(g) / 255,
            blue: Double(b) / 255,
            opacity: Double(a) / 255
        )
    }
}

struct Playground4: View {
    var controlPoint = 0.0
    @State private var bookTags = [
        Tag(id: UUID(), name: "Adventure", color: "6d7aef"),
        Tag(id: UUID(), name: "Drama", color: "c096f2"),
        Tag(id: UUID(), name: "Romance", color: "d681b0"),
        Tag(id: UUID(), name: "Discover", color: "8ad5e0"),
        Tag(id: UUID(), name: "Design", color: "db6446"),
        Tag(id: UUID(), name: "Action", color: "e8d272"),
        Tag(id: UUID(), name: "History", color: "8fb1e1"),
        Tag(id: UUID(), name: "Recommended", color: "325eb5"),
    ]
    
    var body: some View {
        ZStack(alignment: .top) {
            // 滚动的矩形区域(第二部分)
            ScrollView {
                ZStack(alignment: .top) {
                    ForEach(Array(bookTags.enumerated()), id: \.element.id) { index, tag in
                        Rectangle()
                            .frame(height: 300)
                            .foregroundColor(Color(hex: tag.color))
                            .shadow(color: .black.opacity(0.1), radius: 5, x: 5, y: 5)
                            .shadow(color: .black.opacity(0.1), radius: 5, x: -5, y: -5)
                            .overlay(alignment: .topLeading) {
                                Text(tag.name)
                                    .font(.system(size: 30, weight: .bold, design: .rounded))
                                    .foregroundColor(.white)
                                    .padding(.horizontal, 30)
                                    .padding(.top, 30)
                            }
                            .padding(.top, index != 0 ? CGFloat(index) * 75 : 0)
                    }
                }
                .padding(.top, 160) // 预留顶部视图高度,初始不遮挡
                .edgesIgnoringSafeArea(.bottom)
            }
            
            // 顶部固定视图(第一部分)
            VStack(alignment: .leading, spacing: 0) {
                HStack {
                    Text("For You")
                        .font(.system(size: 28, weight: .black, design: .rounded))
                    
                    Spacer()
                    
                    Image(systemName: "person.circle.fill")
                        .foregroundColor(.gray)
                        .font(.system(size: 30))
                }
                .padding(30)
                
                HStack {
                    Image(systemName: "magnifyingglass")
                    Text("Book or author")
                        .opacity(0.8)
                        .font(.system(size: 16, weight: .heavy, design: .rounded))
                        .kerning(1)
                        .foregroundColor(.gray)
                        .padding(.leading, 10)
                }
                .padding(30)
                .background(Color.white) // 初始状态遮挡下方内容
            }
        }
    }
}

struct Playground4_Previews: PreviewProvider {
    static var previews: some View {
        Playground4()
    }
}

核心改动说明

  • 整体结构改为ZStack包裹顶部视图和ScrollView,让滚动内容可以在顶部视图下方滚动并覆盖它
  • 给ScrollView内的ZStack添加顶部内边距,预留出顶部视图的高度,保证初始状态下矩形不会遮挡顶部内容
  • 顶部搜索栏添加白色背景,确保初始状态下能完全遮挡下方的矩形区域
  • 优化Overlay布局,简化代码结构

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 08:39:54