SwiftUI故障/错误 – 在LazyVStack和ScrollView中使用AVPlayer时,状态栏不显示。

huangapple go评论63阅读模式
英文:

SwiftUI glitch / bug - status bar not showing when using AVPlayer inside LazyVStack and ScrollView

问题

我正在尝试弄清楚为什么在使用AVPlayer在LazyVStack和ScrollView内部时,状态栏不显示很长时间,所以我制作了一个最小的示例,只需要复制并粘贴:

import SwiftUI
import AVKit

struct ViewOffsetKey: PreferenceKey {
    typealias Value = CGFloat
    static var defaultValue = CGFloat.zero
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value += nextValue()
    }
}

struct ContentView: View {
    @State var toolbarHeight: CGFloat = 64
    @State var freeScreenHeight: CGFloat = 0
    @State var toolbarOffset: CGFloat = 0
    @State var lastScrollOffset: CGFloat = 0
    @State var startChecking: Bool = false

    @State var player = AVPlayer()
    var videoUrl: String = "someExternal1:1ratioVideo"

    init() {
        UIScrollView.appearance().bounces = false
    }

    var body: some View {

        ZStack(alignment: .leading){

            VStack{

                HStack(spacing: 10){

                    Text("toolbar")

                    Spacer()

                }
                .padding(.horizontal, 12.0)
                .frame(height: toolbarHeight)
                .background(Color.green)
                .padding(.bottom, toolbarOffset)
                .offset(y: toolbarOffset)
                .zIndex(2)

                Spacer()
            }
            .clipped()
            .zIndex(2)


            ScrollView(.vertical, showsIndicators: false){

                LazyVStack(spacing: 0){

                    VStack{

                    }
                    .frame(width: round(UIScreen.main.bounds.width / 1.5), height: toolbarHeight + 8)

                    ForEach(1..<5) { index in
                        VideoPlayer(player: player)
                            .onAppear{
                                startChecking = true
                            }
                            .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.width)
                                        .padding(.bottom, 10)

                    }
                }
                .background(GeometryReader {
                    Color.clear.preference(key: ViewOffsetKey.self,
                        value: -$0.frame(in: .named("scroll")).origin.y)
                })
                .onPreferenceChange(ViewOffsetKey.self) {

                    if(startChecking){

                        if($0 > lastScrollOffset){

                            let howMuch = $0 - lastScrollOffset

                            if((toolbarOffset - howMuch) < -toolbarHeight){
                                toolbarOffset = -toolbarHeight
                            }else{
                                toolbarOffset -= howMuch
                            }

                        }else{

                            let howMuch = lastScrollOffset - $0

                            if((toolbarOffset + howMuch) > 0){
                                toolbarOffset = 0
                            }else{
                                toolbarOffset += howMuch
                            }
                        }
                    }

                    lastScrollOffset = $0
                }
            }
            .frame(height: freeScreenHeight)


        }
        .onAppear() {
                player = AVPlayer(url: URL(string: videoUrl)!)
        }
        .preferredColorScheme(.dark)
        .background(
            GeometryReader { proxy in

                Color.clear
                    .onAppear {

                        freeScreenHeight = UIScreen.main.bounds.height - proxy.safeAreaInsets.top - proxy.safeAreaInsets.bottom
                    }
            }
        )
        .clipped()
    }
}

这个 bug 的可能原因是什么?

英文:

I'm trying to figure out why the status bar doesn't show when using AVPlayer inside LazyVStack and ScrollView for many hours now so I made a minimal example that just needs to be copied and pasted:

import SwiftUI
import AVKit
struct ViewOffsetKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue = CGFloat.zero
static func reduce(value: inout Value, nextValue: () -&gt; Value) {
value += nextValue()
}
}
struct ContentView: View {
@State var toolbarHeight: CGFloat = 64
@State var freeScreenHeight: CGFloat = 0
@State var toolbarOffset: CGFloat = 0
@State var lastScrollOffset: CGFloat = 0
@State var startChecking: Bool = false
@State var player = AVPlayer()
var videoUrl: String = &quot;someExternal1:1ratioVideo&quot;
init() {
UIScrollView.appearance().bounces = false
}
var body: some View {
ZStack(alignment: .leading){
VStack{
HStack(spacing: 10){
Text(&quot;toolbar&quot;)
Spacer()
}
.padding(.horizontal, 12.0)
.frame(height: toolbarHeight)
.background(Color.green)
.padding(.bottom, toolbarOffset)
.offset(y: toolbarOffset)
.zIndex(2)
Spacer()
}
.clipped()
.zIndex(2)
ScrollView(.vertical, showsIndicators: false){
LazyVStack(spacing: 0){
VStack{
}
.frame(width: round(UIScreen.main.bounds.width / 1.5), height: toolbarHeight + 8)
ForEach(1..&lt;5) { index in
VideoPlayer(player: player)
.onAppear{
startChecking = true
}
.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.width)
.padding(.bottom, 10)
}
}
.background(GeometryReader {
Color.clear.preference(key: ViewOffsetKey.self,
value: -$0.frame(in: .named(&quot;scroll&quot;)).origin.y)
})
.onPreferenceChange(ViewOffsetKey.self) {
if(startChecking){
if($0 &gt; lastScrollOffset){
let howMuch = $0 - lastScrollOffset
if((toolbarOffset - howMuch) &lt; -toolbarHeight){
toolbarOffset = -toolbarHeight
}else{
toolbarOffset -= howMuch
}
}else{
let howMuch = lastScrollOffset - $0
if((toolbarOffset + howMuch) &gt; 0){
toolbarOffset = 0
}else{
toolbarOffset += howMuch
}
}
}
lastScrollOffset = $0
}
}
.frame(height: freeScreenHeight)
}
.onAppear() {
player = AVPlayer(url: URL(string: videoUrl)!)
}
.preferredColorScheme(.dark)
.background(
GeometryReader { proxy in
Color.clear
.onAppear {
freeScreenHeight = UIScreen.main.bounds.height - proxy.safeAreaInsets.top - proxy.safeAreaInsets.bottom
}
}
)
.clipped()
}
}

What could be the reason for this bug?

答案1

得分: 1

如果您需要快速修复,可以使用.statusBar(hidden:)修饰符来显示状态栏。

在您的ZStack底部添加以下代码行:

} // ZStack 结束位置
.statusBar(hidden: false) // &lt;---- 这里 *****
.onAppear() {
player = AVPlayer(url: URL(string: videoUrl)!)
}
.preferredColorScheme(.dark)
.background(
GeometryReader { proxy in ........
英文:

If you need a quick fix, you can use the .statusBar(hidden:) modifier to get the status bar to display.

At the bottom of your ZStack add the following line of code:

 } // ZStack ends here
.statusBar(hidden: false) // &lt;---- here *****
.onAppear() {
player = AVPlayer(url: URL(string: videoUrl)!)
}
.preferredColorScheme(.dark)
.background(
GeometryReader { proxy in ........

huangapple
  • 本文由 发表于 2023年5月29日 04:55:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76353565.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定