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

如何在SwiftUI tvOS中实现左侧垂直TabView并避免主视图重绘?

问题:避免垂直Tab切换时主视图重绘并实现对应功能

当TabButton获得焦点时,需在RightMainView展示对应内容。使用ViewModel的@Published属性可实现该功能,但切换标签时RightMainView会重绘。由于主视图是复杂UI且包含焦点引擎,因此绝对不希望其重绘。

已尝试的方案

  • 原生TabView:切换标签时视图不会重绘,但仅支持横向布局,不支持左侧垂直模式,询问能否用其实现带文字和图片的垂直TabView;
  • NavigationSplitView:在tvOS上的表现与iPad不同,仅显示TabButtons,主视图/详情视图不显示。

相关代码

import SwiftUI

struct Model: Identifiable, Equatable {
    let id = UUID()
    let title: String
    
    static func == (lhs: Model, rhs: Model) -> Bool {
        return lhs.title == rhs.title
    }
}

class ViewModel: ObservableObject {
    let titles = [Model(title: "Home"), Model(title: "live"), Model(title: "setting"), Model(title: "network")]
    @Published var selected: Model = Model(title: "Home")
}

struct ContentView: View {
    @ObservedObject var viewModel = ViewModel()
    
    var body: some View {
        HStack(spacing: 0) {
            leftTab
                .focusSection()
            rightMainView
        }.edgesIgnoringSafeArea(.all)
    }
    
    private var leftTab: some View {
        VStack {
            ForEach(viewModel.titles, id: \.self.id) { title in
                ZStack {
                    TabButton(viewModel: viewModel, title: title)
                }.focusable()
            }
        }
        .frame(maxWidth: 400, maxHeight: .infinity)
            .background(.yellow)
    }
    
    private var rightMainView: some View {
        VStack {
            let _ = print("Redrawing the View")
            Text(viewModel.selected.title)
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .background(.red)
        }
    }
}

struct TabButton: View {
    @Environment(\.isFocused) var isFocused
    let viewModel: ViewModel
    let title: Model
    var body: some View {
        Text(title.title)
            .frame(width: 200)
            .padding(30)
            .background(isFocused ? .orange : .white)
            .foregroundColor(isFocused ? .black : .gray)
            .cornerRadius(20)
            .onChange(of: isFocused) { newValue in
                if newValue {
                    viewModel.selected = title
                }
            }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 06:35:32