Программно определять панель вкладок или высоту TabView в SwiftUI - PullRequest
3 голосов
/ 29 января 2020

У меня есть приложение SwiftUI, в котором будет проигрыватель подкастов, похожий на проигрыватель Apple Musi c, который расположен чуть выше панели вкладок и сохраняется во всех вкладках и представлениях во время работы проигрывателя. Я не нашел хорошего способа расположить плеер так, чтобы он был flu sh над панелью вкладок, поскольку высота панели вкладок изменяется в зависимости от устройства. Основная проблема, которую я обнаружил, заключается в том, как мне разместить проигрыватель в оверлее или ZStack в представлении root моего приложения, а не в самом TabView. Поскольку мы не можем настроить иерархию представления макета TabView, нет способа внедрить представление между самой TabBar и содержимым представления над ним. Моя базовая c структура кода:

TabView(selection: $appState.selectedTab){
  Home()
  .tabItem {
    VStack {
        Image(systemName: "house")
        Text("Home")
    }
  }
  ...
}.overlay(
  VStack {
    if(audioPlayer.isShowing) {
      Spacer()
      PlayerContainerView(player: audioPlayer.player)
      .padding(.bottom, 58)
      .transition(.moveAndFade)
    }
  })

Основная проблема здесь заключается в том, что местоположение PlayerContainerView жестко запрограммировано с заполнением 58, так что оно очищает TabView. Если бы я мог определить фактическую высоту кадра TabView, я мог бы глобально настроить это для данного устройства, и я был бы в порядке. Кто-нибудь знает, как сделать это надежно? Или у вас есть идея, как я мог бы разместить PlayerContainerView внутри самого TabView, чтобы он просто появлялся МЕЖДУ представлением Home () и панелью вкладок, когда его переключали для отображения? Любые отзывы будут оценены.

Ответы [ 2 ]

3 голосов
/ 09 февраля 2020

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

Использование GeometryReader и PreferenceKey - удобный инструмент для этого

import Combine

struct Size: PreferenceKey {

    typealias Value = [CGRect]
    static var defaultValue: [CGRect] = []
    static func reduce(value: inout [CGRect], nextValue: () -> [CGRect]) {
        value.append(contentsOf: nextValue())
    }
}

struct HomeView: View {
    let txt: String
    var body: some View {
        GeometryReader { proxy in
            Text(self.txt).preference(key: Size.self, value: [proxy.frame(in: CoordinateSpace.global)])
        }
    }
}


struct ContentView: View {
    @State var playerFrame = CGRect.zero
    var body: some View {

        TabView {
            HomeView(txt: "Hello").tabItem {
                Image(systemName: "house")
                Text("A")
            }.border(Color.green).tag(1)

            HomeView(txt: "World!").tabItem {
                Image(systemName: "house")
                Text("B")
            }.border(Color.red).tag(2)

            HomeView(txt: "Bla bla").tabItem {
                Image(systemName: "house")
                Text("C")
            }.border(Color.blue).tag(3)
        }
        .onPreferenceChange(Size.self, perform: { (v) in
            self.playerFrame = v.last ?? .zero
            print(self.playerFrame)
        })
            .overlay(
                Color.yellow.opacity(0.2)
            .frame(width: playerFrame.width, height: playerFrame.height)
            .position(x: playerFrame.width / 2, y: playerFrame.height / 2)
        )
    }
}

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

В этом примере я уменьшаю размер на .padding() на желтом прозрачном прямоугольнике, чтобы ни одна деталь не могла быть скрыта (за пределами экрана)

enter image description here

Даже высоту панели вкладок можно рассчитать, если это необходимо, но я не могу представить, для чего.

3 голосов
/ 29 января 2020

Поскольку мост к UIKit официально разрешен и задокументирован, можно при необходимости прочитать необходимую информацию оттуда.

Здесь возможен подход для считывания высоты панели вкладок непосредственно с UITabBar

* 1005. *
...