xcode 即使SwiftUI为黑色背景,方向更改期间也会闪烁白色

oyt4ldly  于 2022-11-17  发布在  Swift
关注(0)|答案(3)|浏览(252)

我有一个ZStack,我把颜色设置为黑色,然后添加了一个VideoPlayer。当我旋转设备时,播放器周围仍然有白色的闪光。我已经玩过各种各样的想法和背景色,前景色,不透明度,但没有任何工作。我只是希望背景是黑色的,这样看起来像一个平滑的旋转。有人有任何建议或修复吗?下面是我的代码:

import Foundation
import SwiftUI
import AVKit

struct VideoDetail: View {
    
var videoIDString: String
var videoThumbURL: String
@State var player = AVPlayer()

var body: some View {
    
    ZStack {

        Color.black
            .edgesIgnoringSafeArea(.all)
        
        let videoURL: String = videoIDString

        VideoPlayer(player: player)
            //.frame(height: 200)
            .edgesIgnoringSafeArea(.all)
            .onAppear {
                
                player = AVPlayer(url: URL(string: videoURL)!)
                player.play()
            }
            .onDisappear {
                
                player.pause()
            }
    }
    .navigationBarHidden(true)
    .background(Color.black.edgesIgnoringSafeArea(.all))
    }
}
kpbwa7wx

kpbwa7wx1#

我遇到了同样的问题,遇到了一个解决方案:你可以设置宿主窗口根视图控制器视图的背景颜色。你不能在SwiftUI中直接访问它,所以你可以使用this answer中描述的方法。
只需将包含HostingWindowFinderwithHostingWindow View扩展复制到某个位置,然后在视图中使用以下代码将背景色设置为黑色:

var body: some View {
        ZStack {
            // ...
        }
        .withHostingWindow { window in
            window?.rootViewController?.view.backgroundColor = UIColor.black
        }
    }

在这之后,旋转时的白色边角应该消失了!

esyap4oy

esyap4oy2#

我理解你的痛苦。这是一个SwiftUI的bug。SwiftUI目前的工作方式是它将你的视图树包含在一个UIKit视图中。在大多数情况下,SwiftUI和UIKit彼此配合得很好,但一个特别的问题似乎是UIKit和SwiftUI动画的同步。
因此,当设备旋转时,实际上是UIKit驱动动画,因此SwiftUI必须对它可能在动画曲线上的位置进行最佳猜测,但它的猜测相当糟糕。
我们现在能做的最好的事情就是文件反馈。重复的错误报告是苹果如何优先处理的,所以每个人的错误报告越多越好。它不需要很长。标题类似于“设备旋转时的SwiftUI动画伪影”,描述写上“FB 10376122的重复”,以引用同一主题的现有报告。
无论如何,在此期间,我们至少可以抓取包围窗口的UIKit视图,并在那里设置背景颜色。此解决方案有以下限制:1)它不会改变上述UIKit和SwiftUI动画之间同步的明显“跳跃性”; 2)只有在背景是块颜色时才有帮助。
也就是说,这里有一个WindowGroup替换和视图修改器对,它将这个变通方案联系在一起,以便尽可能好地与SwiftUI的其余部分一起使用。
示例用法:

import SwiftUI

@main
struct MyApp: App {
    
    var body: some Scene {
        // Should be at the very top of your view tree within your `App` conforming type
        StyledWindowGroup {
            ContentView()
                // view modifier can be anywhere in your view tree 
                .preferredWindowColor(.black)
        }
    }
}

若要使用,请将下列内容复制到名为StyledWindowGroup.swift的档案中,并加入到您的项目中:

import SwiftUI

/// Wraps a regular `WindowGroup` and enables use of the `preferredWindowColor(_ color: Color)` view modifier
/// from anywhere within its contained view tree. Use in place of a regular `WindowGroup`
public struct StyledWindowGroup<Content: View>: Scene {
    
    @ViewBuilder let content: () -> Content
    
    public init(content: @escaping () -> Content) {
        self.content = content
    }
    
    public var body: some Scene {
        WindowGroup {
            content()
                .backgroundPreferenceValue(PreferredWindowColorKey.self) { color in
                    WindowProxyHostView(backgroundColor: color)
                }
        }
    }
}

// MARK: - Convenience View Modifer

extension View {
    
    /// Sets the background color of the hosting window.
    /// - Note: Requires calling view is contained within a `StyledWindowGroup` scene
    public func preferredWindowColor(_ color: Color) -> some View {
        preference(key: PreferredWindowColorKey.self, value: color)
    }
}

// MARK: - Preference Key

fileprivate struct PreferredWindowColorKey: PreferenceKey {
    static let defaultValue = Color.white
    static func reduce(value: inout Color, nextValue: () -> Color) { }
}

// MARK: - Window Proxy View Pair

fileprivate struct WindowProxyHostView: UIViewRepresentable {
    
    let backgroundColor: Color
    
    func makeUIView(context: Context) -> WindowProxyView {
        let view = WindowProxyView(frame: .zero)
        view.isHidden = true
        return view
    }
    
    func updateUIView(_ view: WindowProxyView, context: Context) {
        view.rootViewBackgroundColor = backgroundColor
    }
}

fileprivate final class WindowProxyView: UIView {
    
    var rootViewBackgroundColor = Color.white {
        didSet { updateRootViewColor(on: window) }
    }
    
    override func willMove(toWindow newWindow: UIWindow?) {
        updateRootViewColor(on: newWindow)
    }
    
    private func updateRootViewColor(on window: UIWindow?) {
        guard let rootViewController = window?.rootViewController else { return }
        rootViewController.view.backgroundColor = UIColor(rootViewBackgroundColor)
    }
}
iecba09b

iecba09b3#

只需添加

ZStack{
    ...
}.preferredColorScheme(ColorScheme.dark)

相关问题