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

SwiftUI中ScrollTab初始化至第2标签后切换第1标签失效问题求助

问题原因与修复方案

核心问题分析

  1. 多余的Spacer()导致内容被挤出可视区域:ScrollTab的body最顶部添加的Spacer()会将整个VStack推至屏幕底部,初始化currentTab=0时,View1的内容被顶出屏幕,因此无法看到文本;而currentTab=1时的显示属于巧合性渲染,并非正常逻辑。
  2. 冗余的onAppear状态设置:TabView标签页内的onAppear代码块强制设置currentTab是多余操作,TabView已通过selection与currentTab绑定,该代码会造成状态冲突。

修复步骤

  • 移除ScrollTab中body最顶部的Spacer()
  • 删除TabView每个标签页内的onAppear代码块

修改后的完整代码

ScrollTab.swift

struct ScrollTab: View {
    @State private var currentTab: Int = 0
    
    init(currentTab: Int) {
        _currentTab = State(initialValue: currentTab)
    }
    
    var body: some View {
        VStack(alignment: .center, spacing: 0) {
            TabBarView(currentTab: self.$currentTab)
            
            TabView(selection: self.$currentTab) {
                Text("This is view 1").tag(0)
                Text("This is view 2").tag(1)
            }
            .tabViewStyle(.page(indexDisplayMode: .never))
            .background(Color.secondary)
        }
        .edgesIgnoringSafeArea(.all)
    }
}

struct TabBarView: View {
    @Binding var currentTab: Int
    @Namespace var namespace
    
    var tabBarOptions: [String] = ["View 1", "View 2"]
    var body: some View {
        HStack(spacing: 20) {
            ForEach(Array(zip(self.tabBarOptions.indices,
                              self.tabBarOptions)),
                    id: \.0,
                    content: {
                index, name in
                TabBarItem(currentTab: self.$currentTab,
                           namespace: namespace.self,
                           tabBarItemName: name,
                           tab: index)
                
            })
        }
        .padding(.horizontal)
        .background(Color.orange)
        .frame(height: 80)
    }
}

struct TabBarItem: View {
    @Binding var currentTab: Int
    let namespace: Namespace.ID
    
    var tabBarItemName: String
    var tab: Int
    
    var body: some View {
        Button {
            self.currentTab = tab
        } label: {
            VStack {
                Spacer()
                Text(tabBarItemName)
                if currentTab == tab {
                    Color.black
                        .frame(height: 2)
                        .matchedGeometryEffect(id: "underline",
                                               in: namespace,
                                               properties: .frame)
                } else {
                    Color.clear.frame(height: 2)
                }
            }
            .animation(.spring(), value: self.currentTab)
        }
        .buttonStyle(.plain)
    }
}

ContentView.swift(无需修改)

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationStack {
            HStack {
                NavigationLink {
                    ScrollTab(currentTab: 0)
                } label: {
                    Text("View 1")
                        .font(.subheadline)
                        .fontWeight(.semibold)
                }
                
                NavigationLink {
                    ScrollTab(currentTab: 1)
                } label: {
                    VStack {
                        Text("View 2")
                            .font(.subheadline)
                            .fontWeight(.semibold)
                    }
                    .frame(width: 76)
                }
            }
        }
    }
}

验证效果

  • 点击ContentView的「View 1」按钮,ScrollTab会正确显示"This is view 1"文本
  • 点击ContentView的「View 2」按钮,正常显示对应内容
  • TabBar的切换按钮与TabView的滚动功能均正常工作,符合Instagram式的标签切换逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:00:42