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

SwiftUI:自定义原生导航栏复刻Apple TV应用样式与动画(iOS 16)

在SwiftUI中用原生导航栏实现Apple TV风格滚动动态效果

1. 解决导航栏完全透明的问题

你遇到设置透明度为0仍有残留背景的问题,是因为原生导航栏默认带有系统模糊背景层。要实现完全透明,需要同时隐藏系统默认背景并设置自定义背景为透明:

.toolbarBackground(.clear, for: .navigationBar)
.toolbarBackground(.hidden, for: .navigationBar)

.toolbarBackground(.hidden)会移除系统自带的模糊背景,配合.clear可以确保导航栏初始状态完全透明。

2. 监听滚动偏移(iOS17+ 推荐方案)

利用iOS17新增的scrollPosition修饰符,无需嵌套GeometryReader就能直接获取滚动偏移量:

@State private var scrollOffset: CGFloat = 0
@State private var scrollPosition: Anchor<CGRect>?

var body: some View {
    NavigationStack {
        ScrollView {
            VStack(spacing: 20) {
                // 页面核心内容(比如顶部大图)
                Color.red.frame(height: 300)
                // 下方列表内容
                ForEach(0..<20) { _ in
                    Text("示例内容行")
                        .frame(maxWidth: .infinity, minHeight: 50)
                        .background(.gray.opacity(0.1))
                }
            }
            .scrollTargetLayout()
        }
        .scrollPosition(id: $scrollPosition)
        .onChange(of: scrollPosition) { _, newValue in
            if let rect = newValue?.bounds {
                scrollOffset = rect.minY
            }
        }

3. 动态控制导航栏背景与工具栏色调

根据滚动偏移量计算过渡值,借助SwiftUI内置动画实现平滑切换:

.navigationTitle("详情页")
        .toolbar {
            ToolbarItem(placement: .navigationBarTrailing) {
                Button(action: {}) {
                    Image(systemName: "heart")
                }
                .tint(scrollOffset < -100 ? .white : .black) // 滚动超过阈值后切换按钮色调
            }
        }
        .toolbarBackground(
            // 滚动超过100pt后,背景从透明渐变为黑色
            Color.black.opacity(max(0, (-scrollOffset - 100) / 100)),
            for: .navigationBar
        )
        .toolbarBackground(.hidden, for: .navigationBar) // 保持系统背景隐藏
        .animation(.easeInOut(duration: 0.3), value: scrollOffset) // 绑定动画到滚动偏移
    }
}

核心逻辑说明:

  • 当页面向下滚动超过100pt(scrollOffset < -100),导航栏背景逐渐从透明变为不透明,工具栏按钮色调同步从黑色切换为白色
  • 所有过渡动画由SwiftUI内置引擎处理,无需手动编写动画逻辑

4. iOS16及以下兼容方案

如果需要支持iOS16,改用GeometryReader结合PreferenceKey监听滚动:

ScrollView {
    // 隐藏的监听视图
    GeometryReader { proxy in
        Color.clear.preference(key: ScrollOffsetKey.self, value: proxy.frame(in: .named("scroll")).minY)
    }
    .frame(height: 0)
    
    // 页面内容(和iOS17版本一致)
}
.coordinateSpace(name: "scroll")
.onPreferenceChange(ScrollOffsetKey.self) { offset in
    scrollOffset = offset
}

// 自定义PreferenceKey
struct ScrollOffsetKey: PreferenceKey {
    static var defaultValue: CGFloat = 0
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {}
}

后续的导航栏动态控制逻辑和iOS17版本完全一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 02:45:33