SwiftUI TabView превышает высоту, поэтому дочерние элементы не центрируются

У меня возникла проблема с реализацией 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 неправильно обрабатывает панель инструментов. Была ли у кого-нибудь еще эта проблема раньше?

Когда ваш пример тестируется на симуляторе iPhone 15 под управлением iOS 17.5 (Xcode 15.4), только нижняя вставка безопасной области становится зеленой. Другими словами, фон за панелью инструментов синий, а не зеленый. Серый прямоугольник расположен точно по центру синей области по вертикали. Даже в предварительном просмотре все то же самое. Итак, какова среда для вашего скриншота?

Benzy Neez 17.05.2024 12:14

Сорри, забыл упомянуть, что поменял цвет нижнего бара, обновил пост.

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

Ответы 1

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

Причина, по которой серый квадрат не находится по центру, заключается в том, что (прокручиваемая) синяя область продолжается за панелью инструментов. Когда панель инструментов скрыта, серый квадрат располагается по центру по вертикали.

Вот два обходных пути:

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 и добавляю туда панель инструментов, все работает совершенно нормально. Второе решение, кажется, тоже работает, но я думаю, что выберу третье решение, поскольку оно у нас было раньше, и, возможно, это было одной из причин :-) Спасибо за объяснение :-)

Strassenrenner 20.05.2024 17:54

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