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

如何仅让VStack中的最后一个视图忽略键盘安全区域?

解决SwiftUI中仅让BannerAd忽略键盘安全区域的问题

问题场景:键盘弹出时,VStack底部的BannerAd会被一并抬起;单独给BannerAd加.ignoresSafeArea(.keyboard)没效果;给VStack加该修饰符的话,ItemsView的焦点状态会异常,所有视图都被键盘顶起。

解决方案:用ZStack分离布局层级

核心思路是让ItemsView正常响应键盘安全区域,BannerAd脱离父布局的键盘影响,固定在屏幕底部。同时给ItemsView添加底部内边距,避免列表内容被BannerAd遮挡。

步骤1:获取BannerAd的高度(可选,若高度固定可跳过)

先定义一个PreferenceKey用来传递BannerAd的高度:

struct BannerHeightKey: PreferenceKey {
    static var defaultValue: CGFloat = 0
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value = nextValue()
    }
}

步骤2:修改BannerAd,传递高度信息

给BannerAd添加一个背景用来计算自身高度:

struct BannerAd: View {
    var body: some View {
        Text("Banner ad")
            .padding()
            .frame(maxWidth: .infinity)
            .background(Color.green)
            .background(
                GeometryReader { proxy in
                    Color.clear
                        .preference(key: BannerHeightKey.self, value: proxy.size.height)
                }
            )
    }
}

步骤3:重构ContentView布局

用ZStack将ItemsView和BannerAd分层,让BannerAd固定在底部并忽略键盘安全区域,同时给ItemsView设置底部内边距:

struct ContentView: View {
    
    @FocusState var focusedId: ObjectId?
    @State private var bannerHeight: CGFloat = 0
    
    var body: some View {
        NavigationStack {
            ZStack(alignment: .bottom) {
                // 列表视图正常响应键盘,添加底部内边距避免被Banner遮挡
                ItemsView(focusedId: $focusedId)
                    .padding(.bottom, bannerHeight)
                
                // Banner固定在底部,忽略键盘安全区域
                BannerAd()
                    .ignoresSafeArea(.keyboard)
                    .onPreferenceChange(BannerHeightKey.self) {
                        bannerHeight = $0
                    }
            }
        }
    }
}

简化方案(Banner高度固定时)

如果BannerAd的高度是固定值(比如50),可以直接省略PreferenceKey的步骤,给ItemsView加固定内边距:

struct ContentView: View {
    
    @FocusState var focusedId: ObjectId?
    
    var body: some View {
        NavigationStack {
            ZStack(alignment: .bottom) {
                ItemsView(focusedId: $focusedId)
                    .padding(.bottom, 50) // 固定Banner高度
                
                BannerAd()
                    .ignoresSafeArea(.keyboard)
            }
        }
    }
}

这样修改后,键盘弹出时,ItemsView会正常滚动以保证焦点TextField可见,而BannerAd会留在屏幕底部,不会被键盘抬起。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 10:52:28