Я изучаю стек навигации SwiftUI и панели вкладок, большинство руководств просто показывают реализацию панелей вкладок. я пытаюсь скрыть свою пользовательскую панель вкладок в подпредставлениях. Пожалуйста, кто-нибудь может объяснить, что делать, чтобы я мог изучить и принять это к сведению для использования в будущем. заранее спасибо
struct MainTabbedView: View {
@State var selectedTab = 0
@Environment(\.isTabBarVisible) var isTabBarVisible
var body: some View {
ZStack(alignment: .bottom) {
TabView(selection: $selectedTab) {
HomeView()
.tag(0)
FavoriteView()
.tag(1)
FantasyView_Preview()
.tag(2)
ProfileView()
.tag(3)
}
if isTabBarVisible {
ZStack {
HStack {
ForEach((TabbedItems.allCases), id: \.self) { item in
Button {
selectedTab = item.rawValue
} label: {
CustomTabItem(imageName: item.iconName, title: item.title, isActive: (selectedTab == item.rawValue))
}
}
}
.padding(6)
}
.frame(height: 70)
.background(Color.yinmnBlue.opacity(0.2))
.cornerRadius(35)
.padding(.horizontal, 26)
}
}
extension MainTabbedView {
func CustomTabItem(imageName: String, title: String, isActive: Bool) -> some View {
HStack(spacing: 10) {
Spacer()
Image(systemName:imageName)
.resizable()
.renderingMode(.template)
.foregroundColor(isActive ? .black : .gray)
.frame(width: 25, height: 25)
if isActive {
Text(title)
.font(.system(size: 14))
.foregroundColor(isActive ? .black : .gray)
}
Spacer()
}
.frame(width: isActive ? .infinity : 60, height: 60)
.background(isActive ? Color.yinmnBlue.opacity(0.4) : .clear)
.cornerRadius(30)
}
}
HomeView.swift
struct HomeView: View {
@State private var showsubview = false
var body: some View {
NavigationStack{
Button(action: {
showsubview = true
}, label: {
Text("Go to sub view")
})
.navigationDestination(isPresented: $showsubview) {
navigation1(isPresented: $showsubview)
.environment(\.isTabBarVisible, false)
}
}
}
}
я пытался использовать переменные среды, но это не сработало
struct TabBarVisibilityKey: EnvironmentKey {
static let defaultValue: Bool = true
}
extension EnvironmentValues {
var isTabBarVisible: Bool {
get { self[TabBarVisibilityKey.self] }
set { self[TabBarVisibilityKey.self] = newValue }
}
}





Значения среды предназначены для передачи информации вниз по иерархии представлений, но в этом случае вы хотите, чтобы подпредставления сообщали своим родителям, хотят ли они, чтобы панель вкладок отображалась. Вместо этого вам следует использовать предпочтение.
Сначала напишите ключ предпочтения
struct CustomTabBarVisiblePreference: PreferenceKey {
// nil means "not set"
static let defaultValue: Bool? = nil
static func reduce(value: inout Bool?, nextValue: () -> Bool?) {
guard let next = nextValue() else { return }
value = next
}
}
В пункте назначения навигации HomeView установите для параметра значение false:
struct HomeView: View {
@State private var showsubview = false
var body: some View {
NavigationStack{
Button(action: {
showsubview = true
}, label: {
Text("Go to sub view")
})
.navigationDestination(isPresented: $showsubview) {
Text("Destination")
// here:
.preference(key: CustomTabBarVisiblePreference.self, value: false)
}
}
}
}
В представлении вкладок используйте overlayPreferenceValue вместо ZStack, чтобы наложить панель вкладок. Таким образом, вы можете прочитать значение предпочтения и определить, отображать ли панель вкладок.
struct MainTabbedView: View {
@State var selectedTab = 1
var body: some View {
TabView(selection: $selectedTab) {
HomeView()
.tag(0)
// I have replaced other views with simple Texts so that this is a minimal reproducible example
Text("Favourites View")
.tag(1)
Text("Fantasy View")
.tag(2)
Text("Profile View")
.tag(3)
}
.overlayPreferenceValue(CustomTabBarVisiblePreference.self, alignment: .bottom) { visible in
// "!= false" here so that the tab bar is visible if the preference is not set
if visible != false {
ZStack {
HStack {
ForEach(0..<4, id: \.self) { item in
Button {
selectedTab = item
} label: {
CustomTabItem(imageName: "circle", title: "Title \(item)", isActive: selectedTab == item)
}
}
}
.padding(6)
}
.frame(height: 70)
.background(Color.blue.opacity(0.2))
.cornerRadius(35)
.padding(.horizontal, 26)
}
}
}
}
// I refactored CustomTabItem as its own View struct
struct CustomTabItem: View {
let imageName: String
let title: String
let isActive: Bool
var body: some View {
HStack(spacing: 10) {
Spacer()
Image(systemName:imageName)
.resizable()
.renderingMode(.template)
.foregroundColor(isActive ? .black : .gray)
.frame(width: 25, height: 25)
if isActive {
Text(title)
.font(.system(size: 14))
.foregroundColor(isActive ? .black : .gray)
}
Spacer()
}
.frame(width: isActive ? nil : 60, height: 60)
.frame(maxWidth: isActive ? .infinity : nil)
.background(isActive ? Color.blue.opacity(0.4) : .clear)
.cornerRadius(30)
}
}
спасибо @Sweeper. это было информативно
Я хотел бы знать, если есть несколько кнопок, открывающих разные подпредставления, задаю ли я предпочтение для каждого пункта назначения навигации? или я могу просто поместить его под стек навигации?
@gillbates, вам следует изменить каждый пункт назначения, а не весь стек навигации. Стек навигации всегда «видим», поэтому его предпочтения всегда будут «преобладать» над пунктами назначения.
Я знаю, что это большой вопрос, но делаете ли вы обзоры кода?
Покажите минимальный воспроизводимый код, который создает вашу проблему, см.: Минимальный код. Некоторый (минимальный) код, который мы можем скомпилировать и запустить. Что такое
navigation1(isPresented: $showsubview)? Где называетсяMainTabbedView?