SwiftUI, как скрыть панель навигации «больше» на 5-й и 6-й вкладках в пользовательском представлении вкладок

Я использую настраиваемое представление вкладок, чтобы отображать 6 вкладок в представлении вкладок. Их количество ограничено только 5, поэтому, если вы добавите 6, будет создан раздел «Дополнительно», а 5-я и 6-я вкладки отобразятся в представлении навигации. Когда вы просматриваете 5-ю и 6-ю вкладки, сверху отображается задняя панель навигации с надписью «Еще». У меня есть просмотр вкладок, чтобы отображать все 6 вкладок без опции «еще», но когда я просматриваю 5-ю и 6-ю вкладки, сверху все равно отображается панель навигации с кнопкой «Еще» назад. X реализовал это с помощью 6-х вкладок без дополнительной панели навигации на 5-6 вкладках, так что это, безусловно, возможно.

В идеале я пытаюсь скрыть панель навигации «Еще» из первого представления и сохранить панель навигации фактического представления.

я пытался

                     View6()
                            .tag(Tab.home5)
                            .navigationBarTitle("")
                            .navigationBarBackButtonHidden(true)
                            .navigationBarHidden(true)

Просмотр вкладок

         VStack(spacing: 0){
                 TabView(selection: $currentTab) {
                     View1()
                            .tag(Tab.home1)
                     View2()
                            .tag(Tab.home2)
                     View3()
                            .tag(Tab.home3)
                     View4()
                            .tag(Tab.home4)
                     View5()
                            .tag(Tab.home5)
                     View6()
                            .tag(Tab.home6)

                 }
 
                         TabBar()
                         .toolbar(.hidden, for: .tabBar)
                 
             }

Конструктор пользовательских вкладок (показывает все 6 вкладок вместо дополнительного раздела на 5-й вкладке)

    @ViewBuilder
    func TabBar()->some View{
        
        HStack(spacing: 0){
                    ForEach(Icons){icon in
                        
                        let tabColor: SwiftUI.Color = currentTab == icon.tabIcon ? (scheme == .dark ? .white : .black) : .gray.opacity(0.6)
                        
                        ResizableIconView(IconView: icon.View,color: tabColor)
                            .aspectRatio(contentMode: .fit)
                            .frame(width: 30, height: 30)
                            .frame(maxWidth: .infinity)
                            .contentShape(Rectangle())
                            }
                    }
                }
                .padding(.horizontal)
                .padding(.vertical,10)
                .background {
                    (scheme == .dark ? Color.black : Color.white)
                        .ignoresSafeArea()
                }
    }

Когда я просматриваю 5-ю и 6-ю вкладки, отображается дополнительная навигация, как показано ниже: еще панель навигации

Я попытался установить для NavigationBarBackButtonHidden значение true, но это не сработало. Я также пробовал скрыть панель навигации глобально, но при этом удаляются все панели навигации со всех вкладок.

extension UINavigationController {
    open override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        navigationBar.isHidden = true
    }
}


Я думаю, что решение связано с UIKit

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
72
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Да, ответ в основном UIKit. Вы должны обернуть UITabBarController и установить для него moreNavigationController.isNavigationBarHidden значение true.

Я объединил этот ответ , который показывает простую оболочку вокруг UITabBarController, с этим ответом о правильном выборе времени для установки isNavigationBarHidden:

class CustomTabBarController: UITabBarController, UINavigationControllerDelegate {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        moreNavigationController.delegate = self
    }
    
    func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
        // hide the nav bar here:
        navigationController.isNavigationBarHidden = true
    }
}

struct TabBarController: UIViewControllerRepresentable {
    var controllers: [UIViewController]

    @Binding var switchTab: Int

    func makeUIViewController(context: Context) -> CustomTabBarController {
        let tabBarController = CustomTabBarController()
        tabBarController.tabBar.isHidden = true // hide the tab bar here
        tabBarController.viewControllers = controllers
        tabBarController.delegate = context.coordinator
        return tabBarController
    }

    func updateUIViewController(_ uiViewController: CustomTabBarController, context: Context) {
        uiViewController.selectedIndex = switchTab
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, UITabBarControllerDelegate {
        let owner: TabBarController
        init(_ owner: TabBarController) {
            self.owner = owner
        }
        func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
            owner.switchTab = tabBarController.selectedIndex
        }
    }
}

@MainActor
struct UIKitStyleTabView: View {
    var viewControllers: [UIHostingController<AnyView>]

    @Binding var switchTab: Int

    struct Tab {
        var view: AnyView
        var barItem: UITabBarItem

        init<V: View>(view: V, barItem: UITabBarItem) {
            self.view = AnyView(view)
            self.barItem = barItem
        }
    }

    init(_ tabs: [Tab], switchTab: Binding<Int>) {
        self.viewControllers = tabs.map {
            let host = UIHostingController(rootView: $0.view)
            host.tabBarItem = $0.barItem
            return host
        }
        self._switchTab = switchTab
    }

    var body: some View {
        TabBarController(controllers: viewControllers, switchTab: $switchTab)
            .edgesIgnoringSafeArea(.all)
    }
}

Пример использования: здесь показано представление вкладок с шестью вкладками, с кнопкой на первой вкладке, которая переводит вас на шестую вкладку.

struct ContentView : View {
    @State var switchTab: Int = 0

    let tabBarSymbolConfig = UIImage.SymbolConfiguration(scale: .medium)

    var body : some View {

        UIKitStyleTabView([
            UIKitStyleTabView.Tab(view: Button("Go to tab 6") { self.switchTab = 5 }, barItem: UITabBarItem(title: "Social", image: UIImage(systemName: "person.3.fill", withConfiguration: tabBarSymbolConfig)!.withBaselineOffset(fromBottom: 4.5), selectedImage: nil)
            ), UIKitStyleTabView.Tab(view: Text("SearchView"), barItem: UITabBarItem(title: "Search", image: UIImage(systemName: "magnifyingglass", withConfiguration: tabBarSymbolConfig)!.withBaselineOffset(fromBottom: 4.5), selectedImage: nil)
            ), UIKitStyleTabView.Tab(view: Text("WorkoutsView"),barItem: UITabBarItem(title: "Workouts", image: UIImage(systemName: "doc.on.clipboard.fill", withConfiguration: tabBarSymbolConfig)!.withBaselineOffset(fromBottom: 4.5), selectedImage: nil)
            ), UIKitStyleTabView.Tab(view: Text("ExercisesView"), barItem: UITabBarItem(title: "Exercises", image: UIImage(systemName: "sportscourt", withConfiguration: tabBarSymbolConfig)!.withBaselineOffset(fromBottom: 4.5), selectedImage: nil)
            ), UIKitStyleTabView.Tab(view: Text("AccountView"), barItem: UITabBarItem(title: "Me", image: UIImage(systemName: "person.crop.circle", withConfiguration: tabBarSymbolConfig)!.withBaselineOffset(fromBottom: 4.5), selectedImage: nil)
            ), UIKitStyleTabView.Tab(view: Text("SomeOtherView"), barItem: UITabBarItem(title: "Other", image: UIImage(systemName: "person.crop.circle", withConfiguration: tabBarSymbolConfig)!.withBaselineOffset(fromBottom: 4.5), selectedImage: nil)
            )
        ], switchTab: $switchTab)
    }
}

Вы также можете использовать SwiftUI Introspect, чтобы напрямую получить UITabBarController от TabView, но он может анализировать только указанные вами версии, поэтому он вообще не ориентирован на будущее.

TabView(selection: $tab) {
    ForEach(0..<7) { i in
        Text("Tab \(i)").tabItem { Text("\(i)") }
            .toolbar(.hidden, for: .tabBar)
    }
}
.introspect(.tabView, on: .iOS(.v13, .v14, .v15, .v16, .v17)) { tabView in
    tabView.moreNavigationController.isNavigationBarHidden = true
}

Спасибо! Есть ли способ сохранить текущую панель вкладок и написать расширение UIKit, чтобы просто скрывать первую панель навигации, когда я перехожу на 5-ю и 6-ю вкладки?

URihal 07.06.2024 16:48

@URihal Вы можете использовать SwiftUI Introspect, чтобы получить UITabBarController, и, возможно, вы сможете сделать с этим что-то подобное. Но это не перспектива на будущее. При использовании SwiftUI-Introspect вы должны указать версии iOS, которые вы хотите проанализировать, чтобы она перестала работать с более новыми версиями, если только SwiftUI Introspect не выпустит новую версию, и вы не обновите свое приложение, а пользователь не установит обновление.

Sweeper 07.06.2024 17:01

Мне нравится подход Introspect. У меня это работает, но оно скрывает панель навигации представления, а не панель навигации «Дополнительно». Знаете ли вы, как это изменить? View6() .tag(Tab.home6) .introspect(.navigationView(style: .stack), on: .iOS(.v17)) { NavigationController в NavigationController.isNavigationBarHidden = true }

URihal 07.06.2024 17:57

@URihal Посмотрите редактирование. Вам нужно проанализировать .tabView и получить moreNavigationController.

Sweeper 08.06.2024 02:44

Дополнительный вопрос: я впервые включил собственное представление вкладок. Когда я выполняю поиск на вкладке поиска или когда при вводе текста появляется экранная клавиатура, панель вкладок перемещается над клавиатурой. Как лучше всего скрыть пользовательскую вкладку при поиске или вводе текста? (вместо того, чтобы проверять, выполняется ли поиск или набирать текст, а затем передавать $showtab bool через вкладку в представление и изменять его там, могу ли я проверить, включена ли экранная клавиатура, и если да, то отключить панель вкладок глобально?)

URihal 08.06.2024 15:42

@URihal А как насчет .ignoresSafeArea(.keyboard) на внешней стороне VStack? Это также может сработать, если вы поместите его на саму панель вкладок, но я не уверен. Я бы посоветовал опубликовать это отдельно, если вы все еще застряли.

Sweeper 08.06.2024 15:44

Оно работает! Великолепно! Хорошего дня, сэр!

URihal 08.06.2024 15:58

Другие вопросы по теме

UIActivityViewController отображается в неправильном положении на iPad, когда он представлен в виде всплывающего окна в SwiftUI
Есть ли какой-либо встроенный способ получить мантиссу и показатель степени (значения «научной нотации» или «электронной нотации») CGFloat в Swift?
Размещение представления в виде снизу в другом представлении не работает должным образом при использовании SwiftUI
Нет такого модуля «UIKit» для проекта SwiftUI
Можно ли добавить собственный переход к дочерним элементам TabView при изменении страницы?
Основное статическое свойство «текст», изолированное от актера, не может быть изменено из неизолированного контекста; это ошибка в Swift 6
Полная ширина UICollectionViewCells перекрывается во время вращения ориентации интерфейса, вызывая некрасивую анимацию
Каков правильный подход к модульному тестированию в iOS?
Разве UILabel sizeThatFits не должен возвращать размер, меньший или равный заданному размеру, а не больше, для однострочных меток?
Как центрировать UIImageView вертикально в UICollectionViewListCell в качестве специального аксессуара?