У меня возникла проблема с реализацией TabView, и я не знаю, использую ли я ее неправильно или есть проблема в SwiftUI. Я написал небольшой образец, чтобы воспроизвести его:
import SwiftUI
@main
struct MyPlaygroundAppApp: App {
init() {
let toolbarAppearance = UIToolbarAppearance()
toolbarAppearance.backgroundColor = UIColor(Color.green)
UIToolbar.appearance().standardAppearance = toolbarAppearance
UIToolbar.appearance().scrollEdgeAppearance = toolbarAppearance
UIToolbar.appearance().compactAppearance = toolbarAppearance
UIToolbar.appearance().compactScrollEdgeAppearance = toolbarAppearance
}
var body: some Scene {
WindowGroup {
PlayContentView()
}
}
}
import SwiftUI
struct PlayContentView: View {
var body: some View {
TabView {
ContentView()
}
.background(Color.green)
.edgesIgnoringSafeArea(.top)
.tabViewStyle(.page(indexDisplayMode: .never))
}
}
struct ContentView: View {
var body: some View {
NavigationStack {
VStack(spacing: 0) {
VStack(spacing: 0) {
ZStack {
VStack(spacing: 0) {
Text("Title")
Text("Text")
}
}
.frame(maxWidth: /*@START_MENU_TOKEN@*/.infinity/*@END_MENU_TOKEN@*/, maxHeight: 80, alignment: .bottom)
.padding(.top, 12)
.background(Color.yellow)
Divider()
.overlay(Color.black)
}
ScrollView([.vertical, .horizontal], showsIndicators: false) {
VStack {
}
.frame(width: 200, height: 300)
.frame(maxWidth: .infinity)
.background(Color.gray)
}
.background(Color.blue)
}
.toolbar {
ToolbarItem(placement: .status) {
Text("press me")
}
}
}
}
}
#Preview {
PlayContentView()
}
Результат выглядит следующим образом:
Как вы можете видеть, серый прямоугольник не центрирован по вертикали, у него больше места сверху, чем снизу. Когда я меняю TabView на ZStack, пространство кажется правильным, поэтому я думаю, что проблема заключается в TabView. Я также изменил tabViewStyle на displayMode.always, а затем вижу, что внутри нижней панели появляется маленькая точка. Поэтому я думаю, что TabView имеет неправильную высоту. Когда я отключаю панель инструментов, я также вижу, что синий фон опускается вниз, а затем я также вижу, что серое поле находится по центру. Я предполагаю, что TabView неправильно обрабатывает панель инструментов. Была ли у кого-нибудь еще эта проблема раньше?
Сорри, забыл упомянуть, что поменял цвет нижнего бара, обновил пост.





Причина, по которой серый квадрат не находится по центру, заключается в том, что (прокручиваемая) синяя область продолжается за панелью инструментов. Когда панель инструментов скрыта, серый квадрат располагается по центру по вертикали.
Вот два обходных пути:
1. Вместо этого прикрепите .toolbar к TabView или к NavigationStack.
Например:
NavigationStack {
VStack(spacing: 0) {
// ...
}
}
.toolbar {
// ...
}
2. Добавьте отступы под VStack.
Если панель инструментов остается прикрепленной к VStack, вы можете освободить для нее место, добавив немного нижнего поля. Однако я не смог найти способ измерить высоту панели инструментов по отображаемым компонентам, поэтому вам, возможно, придется прибегнуть к жестко запрограммированному значению.
При тестировании на симуляторе iPhone 15 с iOS 17.5 отступ должен составлять 49 пунктов, но это может измениться в будущей версии iOS. Хорошей новостью является то, что он, кажется, остается постоянным, даже когда используется больший размер текста.
NavigationStack {
VStack(spacing: 0) {
// ...
}
.padding(.bottom, 49)
.toolbar {
// ...
}
}
Альтернативный подход — использовать специальную панель инструментов и разместить ее внизу VStack. Вы могли бы назвать это третьим обходным путем.
Кстати, еще один способ установить цвет фона панели инструментов — использовать .toolbarBackground вместо настройки UIToolbarAppearance в инициализации приложения. Однако это работает только для второго (и третьего) обходного пути, а не для первого:
VStack(spacing: 0) {
// ...
}
.padding(.bottom, 49)
.toolbar {
// ...
}
.toolbarBackground(.visible, for: .bottomBar)
.toolbarBackground(.green, for: .bottomBar)
Спасибо за ваш ответ :-) Первый случай невозможен с NavigationStack, потому что панель инструментов не видна, когда она прикреплена к нему (я думаю, вам нужно сделать это с дочерним элементом NavigationView). Но когда я помещаю TabView в NavigationView и добавляю туда панель инструментов, все работает совершенно нормально. Второе решение, кажется, тоже работает, но я думаю, что выберу третье решение, поскольку оно у нас было раньше, и, возможно, это было одной из причин :-) Спасибо за объяснение :-)
Когда ваш пример тестируется на симуляторе iPhone 15 под управлением iOS 17.5 (Xcode 15.4), только нижняя вставка безопасной области становится зеленой. Другими словами, фон за панелью инструментов синий, а не зеленый. Серый прямоугольник расположен точно по центру синей области по вертикали. Даже в предварительном просмотре все то же самое. Итак, какова среда для вашего скриншота?