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

SwiftUI如何实现图标与标题对齐的App Store风格滚动导航栏

SwiftUI 实现类App Store自适应滚动标题栏

效果参考:

  • 初始状态(大标题+右侧功能按钮):
    初始状态效果
  • 滚动后状态(内嵌标题+按钮隐藏):
    滚动后效果

核心实现思路

完全基于系统原生导航组件实现,不需要自定义导航栏就能匹配App Store的原生交互和对齐规则:

  • 监听ScrollView纵向滚动偏移,判断是否达到大标题折叠阈值
  • 动态切换导航标题的显示模式(大标题/内嵌标题)
  • 同步控制右侧工具栏按钮的显隐,加平滑过渡动画避免布局跳动
  • 沿用系统导航栏默认布局规则,不需要手动调整标题、图标位置,自动完成对齐适配

具体实现代码

  1. 首先定义滚动偏移读取工具,通过SwiftUI的PreferenceKey传递滚动位置:
struct ScrollOffsetPreferenceKey: PreferenceKey {
    static var defaultValue: CGFloat = 0
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value = nextValue()
    }
}
  1. 页面核心实现:
import SwiftUI

struct AppStoreStyleNavBar: View {
    // 存储当前滚动偏移值
    @State private var scrollOffset: CGFloat = 0
    // 大标题折叠阈值,可根据实际场景微调,35-45区间基本匹配系统触发时机
    private let foldTriggerOffset: CGFloat = 40
    
    var body: some View {
        NavigationStack {
            ScrollView {
                // 顶部插入零高度探测视图,用于读取滚动偏移
                GeometryReader { proxy in
                    Color.clear
                        .preference(
                            key: ScrollOffsetPreferenceKey.self,
                            value: proxy.frame(in: .named("scrollView")).minY
                        )
                }
                .frame(height: 0)
                
                // 此处放置页面实际滚动内容,比如应用介绍、截图、评价模块
                // VStack(spacing: 16) { ... }
            }
            .coordinateSpace(name: "scrollView")
            .onPreferenceChange(ScrollOffsetPreferenceKey.self) { newValue in
                // 偏移取反,向下滚动时offset为正值
                scrollOffset = -newValue
            }
            // 动态切换标题显示模式
            .navigationTitle("应用详情")
            .toolbarTitleDisplayMode(
                scrollOffset > foldTriggerOffset ? .inline : .large
            )
            .toolbar {
                // 右侧功能按钮,用透明度控制显隐比直接条件移除更顺滑,不会导致布局跳变
                ToolbarItem(placement: .topBarTrailing) {
                    Button {
                        // 分享按钮逻辑
                    } label: {
                        Image(systemName: "square.and.arrow.up")
                    }
                    .opacity(scrollOffset > foldTriggerOffset ? 0 : 1)
                    .disabled(scrollOffset > foldTriggerOffset)
                    .animation(.easeOut(duration: 0.15), value: scrollOffset)
                }
                
                ToolbarItem(placement: .topBarTrailing) {
                    Button {
                        // 更多操作按钮逻辑
                    } label: {
                        Image(systemName: "ellipsis.circle")
                    }
                    .opacity(scrollOffset > foldTriggerOffset ? 0 : 1)
                    .disabled(scrollOffset > foldTriggerOffset)
                    .animation(.easeOut(duration: 0.15), value: scrollOffset)
                }
            }
            // 隐藏导航栏默认纯色背景,匹配App Store的透明/毛玻璃滚动效果
            .toolbarBackground(.hidden, for: .navigationBar)
        }
    }
}

适配注意点

  • 不要手动给标题或者按钮加额外边距、位置偏移,系统原生Toolbar布局会自动处理大标题、右侧按钮的基线对齐,手动调整反而会出现错位
  • 如果需要适配iOS15及以下版本,把.toolbarTitleDisplayMode替换成.navigationBarTitleDisplayMode即可,逻辑完全一致
  • 折叠阈值可以根据页面实际大标题样式微调,如果使用了自定义字体的大标题,适当调整foldTriggerOffset数值,保证和系统折叠时机同步

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 02:39:09